OpenMP并行化矩阵乘法三重for循环(性能问题)

sdf*_*dsf 7 parallel-processing performance loops openmp matrix-multiplication

我正在编写一个使用OpenMP进行矩阵乘法的程序,为了方便缓存,实现乘法A x B(转置)行X行而不是经典的A x B行x列,以获得更好的缓存效率.这样做我遇到了一个有趣的事实,对我来说是不合逻辑的:如果在这段代码中我并行化extern循环,程序比我将OpenMP指令放在最内层循环中慢,在我的计算机中,时间是10.9对8.1秒.

//A and B are double* allocated with malloc, Nu is the lenght of the matrixes 
//which are square

//#pragma omp parallel for
for (i=0; i<Nu; i++){
  for (j=0; j<Nu; j++){
    *(C+(i*Nu+j)) = 0.;
#pragma omp parallel for
    for(k=0;k<Nu ;k++){
      *(C+(i*Nu+j))+=*(A+(i*Nu+k)) * *(B+(j*Nu+k));//C(i,j)=sum(over k) A(i,k)*B(k,j)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*igt 4

尝试减少命中结果的次数。这会导致缓存行共享并阻止操作并行运行。使用局部变量将允许大多数写入发生在每个核心的 L1 缓存中。

另外,使用restrict可能会有所帮助。否则编译器无法保证写入C不会更改A并且B.

尝试:

for (i=0; i<Nu; i++){
  const double* const Arow = A + i*Nu;
  double* const Crow = C + i*Nu;
#pragma omp parallel for
  for (j=0; j<Nu; j++){
    const double* const Bcol = B + j*Nu;
    double sum = 0.0;
    for(k=0;k<Nu ;k++){
      sum += Arow[k] * Bcol[k]; //C(i,j)=sum(over k) A(i,k)*B(k,j)
    }
    Crow[j] = sum;
  }
}
Run Code Online (Sandbox Code Playgroud)

另外,我认为 Elalfer 关于如果并行化最内层循环则需要减少的说法是正确的。