C语言OpenMP求解3D拉普拉斯方程HPC集群并行性能低于串行问题问询
3D拉普拉斯方程OpenMP并行代码性能劣化问题排查
问题背景
使用C语言编写的3D拉普拉斯方程求解OpenMP代码,在HPC集群运行时未达到预期性能,并行版本耗时高于串行版本。
核心迭代代码
while( tol <= error ) { iter = iter + 1 ; # pragma omp parallel shared ( error , To , T ) private ( i, j , k ) { #pragma omp for private ( i, j , k ) // Updating new values T = To for(i=0 ; i < ni ; i++ ){ for(j=0 ; j < nj ; j++ ){ for(k=0 ;k < nk ;k++) { To[i][j][k] = T[i][j][k] ; } } } error = 0.00 ; //Solving for mid-nodes - Central differencing #pragma omp for private(i,j,k) reduction(max:error) for(i=1 ; i < ni-1 ; i++ ) { for(j=1 ; j < nj-1 ; j++ ){ for(k=1 ; k < nk-1 ;k++ ){ T[i][j][k] = ( To[i+1][j][k] +To[i][j+1][k] +To[i][j][k+1] + To[i-1][j][k] + To[i][j-1][k] + To[i][j][k-1] )/6; //printf("T_%d%d%d = %f from thread %d \n",i,j,k,T[i][j][k],omp_get_thread_num() ); error = fmax (error,fabs(T[i][j][k] - To[i][j][k])); } } } } printf(" %d %lE \n",iter ,error); }
性能测试结果
测试显示串行版本运行耗时161秒,加OpenMP并行指示的版本运行耗时为180秒,性能反而劣化。
数组声明与初始化代码
double error = 1e-4 , tol = error , start , end ; printf(" ******************************\n Variables Declared\n ******************************\n\n"); double ***T , ***To ; T = (double***)malloc(ni * sizeof(double**)); To = (double***)malloc(ni * sizeof(double**)); for (i = 0; i < ni; i++) { T[i] = (double**)malloc(nj * sizeof(double*)); To[i] = (double**)malloc(nj * sizeof(double*)); for (j = 0; j < nj; j++) { T[i][j] = (double*)malloc(nk * sizeof(double)); To[i][j] = (double*)malloc(nk * sizeof(double)); } } // Initializing T for(i=0 ; i < ni ; i++ ){ for(j=0 ; j < nj ; j++ ){ for(k=0 ;k < nk ; k++){ T[i][j][k] = 0.00 ; } } }
性能劣化核心原因
- 并行区域重复创建开销:
#pragma omp parallel被放在while循环内部,每轮迭代都会重新创建、销毁线程组,线程管理开销远大于并行计算带来的收益,应该将parallel指令移到while循环外部,全程只创建一次线程。 - 分散内存布局导致缓存失效:使用三重指针逐层malloc的三维数组不是连续内存块,访问时会出现大量地址跳转,缓存命中率极低,同时容易触发跨线程假共享问题。建议改为连续一维内存模拟三维数组,访问逻辑为
T[i*nj*nk + j*nk +k],保证内存连续性,大幅提升缓存命中率。 - 共享变量操作逻辑问题:
error=0.00的赋值操作在并行区域内部、两个for循环之间,属于共享变量的串行赋值,虽然第一个omp for结束有隐式屏障保证赋值时机正确,但冗余的共享变量读写也会增加同步开销。 - 编译优化缺失:若编译时未开启
-O2/-O3优化,也未指定对应架构的编译选项,并行版本的额外开销会被放大,导致性能劣于串行。
内容的提问来源于stack exchange,提问作者Harshad bhusare
相关产品推荐
相关产品推荐

