You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 10:27:05