我正在使用 OpenMP 编写矩阵乘法程序,为了缓存方便,实现乘法 A x B(transpose) 行 X 行而不是经典的 A x B 行 x 列,以提高缓存效率。这样做我遇到了一个有趣的事实,对我来说是不合逻辑的:如果在这段代码中我并行化外部循环,则程序比将 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)
}
}
}
最佳答案
尝试不那么频繁地达到结果。这会导致缓存行共享并阻止操作并行运行。改用局部变量将允许大多数写入发生在每个内核的 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;
}
}
此外,我认为 Elalfer 是正确的,如果您并行化最内层循环,则需要减少。
关于performance - OpenMP 通过三重 for 循环并行化矩阵乘法(性能问题),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4726712/