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

MPI程序叠加OpenMP后并行区域性能严重下降的问题求助

MPI程序叠加OpenMP后并行区域性能严重下降的问题求助

我用C语言写了一个粒子模拟程序,用4个MPI进程运行,相比串行版本速度已经快很多了。但其中有一段N²复杂度的代码,需要把当前进程里的每个粒子和同进程的其他粒子,以及从其他进程共享过来的“边界粒子”做对比。我本来打算用#pragma omp parallel for并行化外层循环来提速,但试了各种OpenMP指令组合后,模拟反而变得巨慢——核心问题就是这段嵌套循环的耗时暴增。

我试过在并行区域里加schedule和reduction,但没什么效果;也试过用8线程或者4线程,同样没用;还测试了不同的系统规模(想看看是不是开销大到超过收益,但显然不是),也调过编译器优化选项,都没用。

计时结果显示,四个MPI进程里有一个在这段代码上耗时特别久,导致整个模拟必须等它完成才能进入下一个时间步,拖慢了整体速度。按理说任务分配得挺均匀的,不该出现这种情况。

代码片段(核心逻辑保留,部分细节做了伪代码处理)

double calc_1 = omp_get_wtime();
#pragma omp parallel for num_threads(4) private(distances, particle_one)
for (int p = 0; p < myNumParticles; p = p + 2){
    //Particle* particle_iter = &particles[0];
    // printf("p%d: I am thread %d\n", my_rank, omp_get_thread_num());
    // fflush(stdout);
    double force_x = 0;
    double force_y = 0;
    particle_one[0] = positions[p];
    particle_one[1] = positions[p+1];
    //#pragma omp parallel shared(force_x, force_y)
    // {
    if (particle_one real){
        // for (int i = 0; i < (myNumParticles-8); i = i + 8){   
        //#pragma omp parallel for private(distances)
        for (int i = 0; i < myNumParticles; i += 2){
            if (i != p){
                // lj_counter2++;
                particle_two[0] = positions[i];
                particle_two[1] = positions[i+1];
                if (particle within distance cutoff){
                    force_function(); // modifies forces array
                    force_x += (forces[0]);
                    force_y += (forces[1]);
                } 
                distances[0] = 0;
                distances[1] = 0;
            }
        }
        // repeat conparison against border particles
        for (int j = 0; j < (num_particles_local); j += 2){
            particle_three[0] = myBorderParticles[j];
            particle_three[1] = myBorderParticles[j+1];
            if (particle is real){
                if (within distance cutoff) {
                    force_function(); // modifies forces array
                    force_x += (forces[0]);
                    force_y += (forces[1]);
                } 
                distances[0] = 0;
                distances[1] = 0;
            } else {
                // if particle with position {0, 0} found, you're at the end
                break;
            }
        }
    }
    accelerations[p] = force_x;
    accelerations[p+1] = force_y;
}
double calc_2 = omp_get_wtime();
calc_time += (calc_2-calc_1);

3600个粒子系统的计时结果

  • 仅MPI版本:
    总耗时373.6秒,其中上述嵌套循环耗时在332.47-349.08秒之间
  • MPI+OpenMP版本:
    总耗时1606.2秒,其中上述嵌套循环耗时在583.09-1579.96秒之间(不同进程耗时差异极大)

更小规模系统的计时对比

粒子数量仅MPI耗时(秒)MPI+OpenMP耗时(秒)
2252730
4003733
62560101
90099293
1225153490
1600239735

我的运行环境是4个节点,每个节点有28+核心,内存需求也在合理范围内。用Slurm提交任务,启动命令是mpiexec -n 4 ./executable num_particles box_size > slurms/output.txt。

备注:内容来源于stack exchange,提问作者Luna Morrow

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 08:48:07