0

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

  1. 二、三for、五、六for同时跑

  2. 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();
   }
}
}
4

2 回答 2

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

编辑

您可以启用嵌套并行性,但它走错了路,过多的循环和线程访问不同的内存块只会降低性能,而且您还将拥有一个为 24 核设计的解决方案,它可能无法与 32、48 核等扩展...但是如果你坚持你必须设置一个环境变量或调用一个 openMP 函数:

 call omp_set_nested()
 or
 set OMP_NESTED=TRUE|FALSE

在您的顶级循环上添加一个 openMP 子句以指定您想要的块大小以便只有 X 线程。

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

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

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

于 2013-07-23T15:59:23.147 回答
0

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

有关更多信息,请查看此Oracle 文档

于 2013-07-23T17:02:46.527 回答