使用一个线程和一个包含多个线程的for循环执行一个部分

时间:2014-04-20 03:43:33

标签: c++ c parallel-processing openmp

我正在使用OpenMP,我想生成线程,使得一个线程执行一段代码并完成,与N个线程并行运行并行for循环的迭代。

执行应该是这样的:

Section A (one thread)       ||      Section B (parallel-for, multiple threads)
         |                   ||        | | | | | | | | | |
         |                   ||        | | | | | | | | | |
         |                   ||        | | | | | | | | | |
         |                   ||        | | | | | | | | | |
         |                   ||        | | | | | | | | | |
         V                   ||        V V V V V V V V V V

我不能只用#pragma omp once写一个parallel-for,因为我不希望执行A节的线程执行for循环。

我试过这个:

#pragma omp parallel sections {
    #pragma omp section
    {
         // Section A
    }

    #pragma omp section
    {
         // Section B;
         #pragma omp parallel for
         for (int i = 0; i < x; ++i)
             something();
    }
}

但是,parallel-for总是只用一个线程执行(我知道因为我创建了循环打印体omp_get_thread_num()并且它们都是相同的数字,1或0取决于哪个线程两个执行了第二个并行部分。)

我也试过

#pragma omp sections {
    #pragma omp section
    {
         // Section A
    }

    #pragma omp section
    {
         // Section B;
         #pragma omp parallel for
         for (int i = 0; i < x; ++i)
             something();
    }
}

允许for循环使用多个线程执行,但它使这些部分不平行,第一部分在第二部分之前顺序执行。

我需要的是两种方法的组合,其中for循环和第一部分的每次迭代都是并行运行。

3 个答案:

答案 0 :(得分:2)

必须显式设置嵌套并行性,因为在大多数实现中默认情况下禁用它。站在OpenMP 4.0标准中,您必须设置OMP_NESTED环境变量:

  

OMP_NESTED环境变量控制嵌套并行度   设置nest-var ICV的初始值。这个的价值   环境变量必须为true或false。如果是环境   变量设置为true,启用嵌套并行性;如果设置为   false,嵌套并行性被禁用。该计划的行为是   如果OMP_NESTED的值既不是真也不是,则定义实现   假的。

以下行应该适用于bash:

 export OMP_NESTED=true

另外,正如@HristoIliev在下面的评论中指出的那样,您很可能想要设置OMP_NUM_THREADS环境变量来调整性能。引用标准:

  

此环境变量的值必须是正数列表   整数值。列表的值设置了线程数   用于相应嵌套级别的并行区域。

这意味着应该将OMP_NUM_THREADS的值设置为n,n-1,其中n是CPU核心数。例如:

export OMP_NUM_THREADS=8,7

用于8核系统(从下面的评论中复制的示例)。

答案 1 :(得分:0)

也许以下代码可以解决这个问题:

#pragma omp parallel for
for (int i = -1; i < x; ++i) {
    if (i==-1) {
        // Section A
    }
    else {
        // Section B
        something();
    }
}

但是,您需要确保x&gt; = 0。

答案 2 :(得分:0)

您是否尝试过具有差异化活动的单个并行区域?例如 不应该需要嵌套并行性。

#pragma omp_parallel 
{

#pragma omp task  
  once();

#pragma omp for 
  for(int i=0;i<N;i++){
    many(i);
  }

}

你也可以在并行中使用基于threadnum的显式if / else 区域并自己为第二个循环进行工作共享计算。