【问题标题】:Parallelizing many nested for loops in openMP c++在openMP c ++中并行化许多嵌套的for循环
【发布时间】:2018-04-17 08:11:12
【问题描述】:

嗨,我是 C++ 新手,我编写了一个可以运行的代码,但由于许多嵌套的 for 循环,它很慢,我想通过 openmp 任何可以指导我的人来加速它。我尝试在 ip 循环之前使用“#pragma omp parallel”,在此循环中我在之前使用了“#pragma omp parallel for” >it 循环,但它不起作用

    #pragma omp parallel
    for(int ip=0; ip !=nparticle; ip++){
        inf14>>r>>xp>>yp>>zp;
        zp/=sqrt(gamma2);
        counter++;
        double para[7]={0,0,Vz,x0-xp,y0-yp,z0-zp,0};
        if(ip>=0 && ip<=43){
             #pragma omp parallel for
             for(int it=0;it<NT;it++){  
             para[6]=PosT[it];
                for(int ix=0;ix<NumX;ix++){
                    para[3]=PosX[ix]-xp;
                    for(int iy=0;iy<NumY;iy++){
                        para[4]=PosY[iy]-yp;
                        for(int iz=0;iz<NumZ;iz++){
                            para[5]=PosZ[iz]-zp;
                            int position=it*NumX*NumY*NumZ+ix*NumY*NumZ+iy*NumZ+iz;
                            rotation(para,&Field[3*position]);
                            MagX[position] +=chg*Field[3*position];
                            MagY[position] +=chg*Field[3*position+1];
                            MagZ[position] +=chg*Field[3*position+2];
                        }   
                    }
                }
            }   
        }
    }enter code here

我的旋转函数也有无限积分循环,如下所示

for(int i=1;;i++){
    gsl_integration_qag(&F, 10*i, 10*i+10, 1.0e-8, 1.0e-8, 100, 2, w, &temp, &error);
    result+=temp;
    if(abs(temp/result)<ACCURACY){
        break;
    }
}

我也在使用 gsl 库。那么如何加快这个过程或如何制作openmp?

【问题讨论】:

  • 在开始并行化你的代码之前,首先要确保没有相互依赖。例如。当第一个语句之一是para[6]=PosT[it]; 时,我看不出如何并行运行 for 循环。当您为并行计算准备代码时,请确保将 __restrict__ 用于函数参数,例如如果 MagX、MagY、MagZ 和 Field 是参数并且从不重叠。 (或__restrict 取决于您使用的编译器)

标签: c++ parallel-processing openmp nested-loops


【解决方案1】:

如果您没有循环间依赖,您可以使用collapse 关键字来并行化多个循环。示例:

void scale( int N, int M, float A[N][M], float B[N][M], float alpha ) {
  #pragma omp for collapse(2)
  for( int i = 0; i < N; i++ ) {
    for( int j = 0; j < M; j++ ) {
      A[i][j] = alpha * B[i][j];
    }
  }
}

我建议您查看OpenMP C/C++ cheat sheet (PDF),其中包含循环并行化的所有规范。

【讨论】:

    【解决方案2】:

    不要在另一个并行 pragma 中设置并行 pragma。您可能会在机器上创建超出其处理能力的线程。我会在外循环中建立并行化(如果它足够大):

    #pragma omp parallel for
        for(int ip=0; ip !=nparticle; ip++)
    

    还要确保线程之间没有任何race condition(例如 RAW)。

    建议:如果你没有得到很好的加速,一个好的做法是按块迭代,而不仅仅是一个增量。例如:

    int num_threads = 1;
    #pragma omp parallel
    {
    #pragma omp single
        {
            num_threads = omp_get_num_threads();
        }
    }
    int chunkSize = 20; //Define your own chunk here
    for (int position = 0; position < total; position+=(chunkSize*num_threads)) {
        int endOfChunk = position + (chunkSize*num_threads);
        #pragma omp parallel for
        for(int ip = position; ip < endOfChunk ; ip += chunkSize) {
            //Code
        }
    }
    

    【讨论】:

    • omp for 的默认调度策略是static,它已经将迭代空间划分为连续的块,然后分布在线程之间。我不会说手动执行此操作是一种好习惯,因为效果是更复杂的代码,没有真正的好处。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 1970-01-01
    相关资源
    最近更新 更多