最近我开始使用OpenMP。使用c ++中创建的三维矩阵作为向量进行数值计算,并使用并行for循环来加速代码。但它比串行代码运行得慢。我使用Windows 7中的Codeblocks编译代码。代码是这样的。
int main(){
vector<vector<vector<float> > > Dx; //
/*create 3d array Dx[IE][JE][KE] as vectors*/
Dx.resize(IE);
for (int i = 0; i < IE; ++i) {
for (int j = 0; j < JE; ++j){
dx[i][j].resize(KE);
}
}
//declare and initialize more matrices like this
.
.
.
double wtime = omp_get_wtime(); // start time
//and matrix calculations using parallel for loop
#pragma omp parallel for
for (int i=1; i < IE; ++i ) {
for (int j=1; j < JE; ++j ) {
for (int k=1; k < KE; ++k ) {
curl_h = ( Hz[i][j][k] - Hz[i][j-1][k] - Hy[i][j][k] + Hy[i][j][k-1]);
idxl[i][j][k] = idxl[i][j][k] + curl_h;
Dx[i][j][k] = gj3[j]*gk3[k]*dx[i][j][k]
+ gj2[j]*gk2[k]*.5*(curl_h + gi1[i]*idxl[i][j][k]);
}
}
}
wtime = omp_get_wtime() - wtime;
}
但是并行循环的代码比串行代码运行得慢。有任何想法吗 ? Thxs。
答案 0 :(得分:0)
循环使用变量curl_h
,该变量未声明为线程私有。这既是一个错误,也是您感知性能问题的原因:
由于内存中只有一个存储curl_h
的位置,所有线程不断地同时尝试读取和写入。一个CPU核心将值加载到其缓存中,下一个将对其发出写入,使第一个CPU的缓存无效,当它本身尝试使用curl_h
时,它将再次获取缓存行(读取或写入) ,两者都要求高速缓存行在本地缓存中。)
关键是,硬件提出的只有一个名为curl_h
的内存位置的强烈借口要求其致敬。你在缓存一致性协议中得到了大量的喋喋不休,并且让你的内存总线忙于不断从内存中重新获取相同的缓存行。你所有的线程都在努力争夺那一个高速缓存行。
当然,线程之间的不断变换是一个很大的错误,因为没有任何过程可以确定它当前使用的值实际上是它在上面的语句中计算的值。
因此,只需在private()
语句中添加正确的omp parallel for
声明,即可解决错误和性能问题。