并行化矩阵按行和按行使用OpenMP按行计算

对于我的一些家庭作业,我需要通过向量实现矩阵的乘法,按行和列并行化。 我确实理解行版本,但我在列版本中有点困惑。

可以说我们有以下数据:

Matix时代矢量

行版本的代码:

#pragma omp parallel default(none) shared(i,v2,v1,matrix,tam) private(j) { #pragma omp for for (i = 0; i < tam; i++) for (j = 0; j < tam; j++){ // printf("Hebra %d hizo %d,%d\n", omp_get_thread_num(), i, j); v2[i] += matrix[i][j] * v1[j]; } } 

这里的计算是正确的,结果是正确的。

列版本:

 #pragma omp parallel default(none) shared(j,v2,v1,matrix,tam) private(i) { for (i = 0; i < tam; i++) #pragma omp for for (j = 0; j < tam; j++) { // printf("Hebra %d hizo %d,%d\n", omp_get_thread_num(), i, j); v2[i] += matrix[i][j] * v1[j]; } } 

这里,由于并行化的完成方式,每次执行的结果都会有所不同,具体取决于执行每列的线程。 但它发生了一些有趣的事情(我认为是因为编译器优化)如果我取消注释printf然后结果与行版本完全相同,因此,更正,例如:

 Thread 0 did 0,0 Thread 2 did 0,2 Thread 1 did 0,1 Thread 2 did 1,2 Thread 1 did 1,1 Thread 0 did 1,0 Thread 2 did 2,2 Thread 1 did 2,1 Thread 0 did 2,0 2.000000 3.000000 4.000000 3.000000 4.000000 5.000000 4.000000 5.000000 6.000000 V2: 20.000000, 26.000000, 32.000000, 

是的,但如果我删除printf:

 V2: 18.000000, 11.000000, 28.000000, 

我应该使用什么样的机制来使列版本正确?

注意 :我更关心的是解释而不是您可能发布的代码作为答案,因为我真正想要的是了解列版本中出了什么问题。

编辑

我找到了一种摆脱Z boson在他的回答中提出的私人向量的方法。 我已经用变量替换了该向量,这里是代码:

  #pragma omp parallel { double sLocal = 0; int i, j; for (i = 0; i < tam; i++) { #pragma omp for for (j = 0; j < tam; j++) { sLocal += matrix[i][j] * v1[j]; } #pragma omp critical { v2[i] += sLocal; sLocal = 0; } } } 

我不知道你的作业究竟是什么意思,通过行和列并行化,但我知道为什么你的代码不起作用。 当您写入v2[i]时,您有竞争条件。 您可以通过制作v2[i]私有版本,并行填充它们,然后将它们与关键部分合并来修复它。

 #pragma omp parallel { float v2_private[tam] = {}; int i,j; for (i = 0; i < tam; i++) { #pragma omp for for (j = 0; j < tam; j++) { v2_private[i] += matrix[i][j] * v1[j]; } } #pragma omp critical { for(i=0; i 

我测试了这个。 你可以在这里看到结果http://coliru.stacked-crooked.com/a/5ad4153f9579304d

请注意,我没有明确定义任何共享或私有。 没有必要这样做。 有些人认为你应该明确定义一切。 我个人认为恰恰相反。 通过在并行部分中定义ij (和v2_private ),它们将v2_private私有。