我已经开始学习如何在大学课程中使用 OpenMP。作为实验室练习,我们得到了一个需要并行化的串行程序。
我们首先意识到False Sharing的危险,尤其是当涉及到并行更新数组时 for 循环。
但是,我发现很难将以下代码片段转换为可并行化的任务而不会导致错误共享:
int ii,kk;
double *uk = malloc(sizeof(double) * NX);
double *ukp1 = malloc(sizeof(double) * NX);
double *temp;
double dx = 1.0/(double)NX;
double dt = 0.5*dx*dx;
// Initialise both arrays with values
init(uk, ukp1);
for(kk=0; kk<NSTEPS; kk++) {
for(ii=1; ii<NX-1; ii++) {
ukp1[ii] = uk[ii] + (dt/(dx*dx))*(uk[ii+1]-2*uk[ii]+uk[ii-1]);
}
temp = ukp1;
ukp1 = uk;
uk = temp;
printValues(uk,kk);
}
我的第一反应是尝试分享ukp1:
for(kk=0; kk<NSTEPS; kk++) {
#pragma omp parallel for shared(ukp1)
for(ii=1; ii<NX-1; ii++) {
ukp1[ii] = uk[ii] + (dt/(dx*dx))*(uk[ii+1]-2*uk[ii]+uk[ii-1]);
}
temp = ukp1;
ukp1 = uk;
uk = temp;
printValues(uk,kk);
}
但这清楚地表明与串行版本相比显着放缓。显而易见的原因是在对ukp1的某些写入操作期间发生了错误共享。
我的印象是也许我可以使用归约子句,但是我很快发现这不能用于数组。
有什么我可以用来并行化此代码以改善运行时的吗?有没有我没听说过的可以使用的子句?或者这是我需要重组代码以允许适当并行化的任务?
所有形式的输入将不胜感激!
编辑:有人指出我的代码有错误。我本地的代码是正确的,我只是错误地编辑了它(改变了代码的结构),很抱歉造成混乱!
编辑2:
@Sergey 向我指出的一些我觉得有用的信息:
将 uk 或 ukp1 设置为 private 本质上与将它们设置为 shared 具有相同的效果,因为它们都是指向同一内存位置的指针
理论上使用静态调度应该会有所帮助,但我仍然遇到同样的减速。另外,我觉得静态调度不是解决这个问题的最便携的方法。