向量的矩阵乘法OpenMP C

我试图通过C(OpenMP)中的向量乘法来编写Matrix,但是当我添加处理器时我的程序会变慢…

1 proc - 1,3 s 2 proc - 2,6 s 4 proc - 5,47 s 

我在我的PC(核心i5)和我们学校的集群上进行了测试,结果相同(程序运行缓慢)

这是我的代码(矩阵是10000 x 10000),矢量是10000:

 double start_time = clock(); #pragma omp parallel private(i) num_threads(4) { tid = omp_get_thread_num(); world_size = omp_get_num_threads(); printf("Threads: %d\n",world_size); for(y = 0; y < matrix_size ; y++){ #pragma omp parallel for private(i) shared(results, vector, matrix) for(i = 0; i < matrix_size; i++){ results[y] = results[y] + vector[i]*matrix[i][y]; } } } double end_time = clock(); double result_time = (end_time - start_time) / CLOCKS_PER_SEC; printf("Time: %f\n", result_time); 

我的问题是:有什么错误吗? 对我来说,它看起来很简单,应该加快速度

我本质上已经回答了这个问题并行化 – 矩阵 – 时间 – 矢量逐列和逐行 – 与openmp 。

当您写入results[y]时,您会遇到竞争条件。 要解决此问题,并仍然并行化内部循环,您必须创建results[y]私有版本results[y] ,并行填充它们,然后将它们合并到一个关键部分。

在下面的代码中,我假设您正在使用double ,将其替换为floatint或您正在使用的任何数据类型(请注意,您的内部循环遍历matrix[i][y]的第一个索引,这是缓存不友好的)。

 #pragma omp parallel num_threads(4) { int y,i; double* results_private = (double*)calloc(matrix_size, sizeof(double)); for(y = 0; y < matrix_size ; y++) { #pragma omp for for(i = 0; i < matrix_size; i++) { results_private[y] += vector[i]*matrix[i][y]; } } #pragma omp critical { for(y=0; y 

如果这是家庭作业,你想真正给你的教练留下深刻印象,那么就可以在没有关键部分的情况下进行合并。 看到这个链接,了解如何做填充直方图 - arrays减少 - 并行 - 使用openmp-without-using-a-critic虽然我不能保证它会更快。

我暂时没有进行任何并行编程,也没有任何数学,但是你不想并行分割矩阵的行而不是列吗?

如果您尝试这样做会发生什么:

 double start_time = clock(); #pragma omp parallel private(i) num_threads(4) { tid = omp_get_thread_num(); world_size = omp_get_num_threads(); printf("Threads: %d\n",world_size); #pragma omp parallel for private(y) shared(results, vector, matrix) for(y = 0; y < matrix_size ; y++){ for(i = 0; i < matrix_size; i++){ results[y] = results[y] + vector[i]*matrix[i][y]; } } } double end_time = clock(); double result_time = (end_time - start_time) / CLOCKS_PER_SEC; printf("Time: %f\n", result_time); 

此外,你确定一切正常编译和与openMP链接?

您有一个典型的缓存冲突案例。

考虑到CPU上的缓存行可能长达64个字节。 让一个处理器/核心写入前4个字节( float )会导致该高速缓存行在每个其他L1 / L2和L3上无效。 这是很多开销。

更好地划分数据!

  #pragma omp parallel for private(i) shared(results, vector, matrix) schedule(static,16) 

应该做的伎俩。 如果这没有帮助,请增加chunksize。

另一个优化是在将结果刷新到内存之前将结果存储在本地。

此外,这是一个OpenMP的东西,但你不需要为循环启动一个新的并行区域(每次提及parallel启动一个新的团队):

 #pragma omp parallel default(none) \ shared(vector, matrix) \ firstprivate(matrix_size) \ num_threads(4) { int i, y; #pragma omp for schedule(static,16) for(y = 0; y < matrix_size ; y++){ double result = 0; for(i = 0; i < matrix_size; i++){ results += vector[i]*matrix[i][y]; } result[y] = result; } }