在OpenMP中并行化嵌套循环并使用更多线程执行内部循环

时间:2013-07-22 23:07:47

标签: c++ c performance openmp

我有这种嵌套循环:我想知道如何以最佳形式并行化:

  1. 第二个和第三个for以及第五个和第六个for同时运行     时间

  2. 序列号

  3. 中的第一个和第四个for

    如果我有24个核心,并希望在16个线程之间划分外部并使用其余部分来执行内部for,例如执行第二个for,8个线程,而不仅仅是一个线程,我该怎么办 ?

    void main()
    {
    //first_for
       for(int y=0; y< height; y++)
    {
          //second_for 
          for(int x=0; x< width-1; x++)
       {
         func1();
       }
          //third_for
          for(int x=0; x< width-1; x++)
       {
         func2();
       }
    
    }
    //fourth_for
       for(int x=0; x<width; x++)
    {
         //fifth_for
         for(int y=0; y< height-1; y++)
       {
         func3();
       }
         //sixth_for
         for(int y=0; y< height-1; y++)
       {
         func4();
       }
    }
    }
    

2 个答案:

答案 0 :(得分:0)

关于并行性介绍,通常会说较粗糙的级别更好,所以如果你可以在粗略的级别添加并行指令,那么为什么你还要添加嵌套的并行性呢?

所以基于可以同时运行的内容,我会像这样编写主要内容:

int main()
{
     //first_for
     #pragma parallel for
     for(int y=0; y< height; y++)
     {
          //second_for and third_for
      for(int x=0; x< width-1; x++)
     {
          func1();
          func2();

      }
  }
 //fourth_for
 #pragma parallel for
 for(int x=0; x<width; x++)
 {
      //fifth_for and  //sixth_for
     for(int y=0; y< height-1; y++)
    {
          func3();
          func4();
     }
  }
 return 0;
}
  1. 我们通过合并2个内循环来增加每行和每列的工作量

  2. 我们添加openMP指令,根据您的核心数量将该计算循环拆分为较小的块。

  3. 看看你是否可以反转第一个循环,因为取决于你在里面做什么以及你的“图像”如何在内存中映射,首先处理列可能会导致很多缓存错误....

  4. 修改

    你可以启用嵌套并行,但是它的方式错误,过多的循环和线程访问不同的内存只会降低性能,你也会有一个专为24核设计的解决方案,可能无法扩展32, 48核心等...但如果你坚持你必须设置一个env变量或调用openMP函数:

     call omp_set_nested()
     or
     set OMP_NESTED=TRUE|FALSE
    

    在顶级循环上添加openMP子句后指定指定所需的chunck大小,以便只有X线程。

    int  chunckSize = height / X;
    #pragma parallel for schedule ( static , chunckSize)
    

    openMP线程团队应该由24个线程组成,但通过这样做,只有X才能完成工作。遵循嵌套循环的逻辑。

    但这不是我推荐的解决方案!

答案 1 :(得分:0)

除了已经说过的内容之外,您可能希望明确启用嵌套并行性。可以在运行时使用库调用或使用环境变量(对于OpenMP)来执行此操作。

有关详细信息,请查看此Oracle Docs