用一个线程做一个部分,用多个线程做一个 for 循环

use*_*921 5 c c++ parallel-processing openmp

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

执行应该是这样的:

Section A (one thread)       ||      Section B (parallel-for, multiple threads)
         |                   ||        | | | | | | | | | |
         |                   ||        | | | | | | | | | |
         |                   ||        | | | | | | | | | |
         |                   ||        | | | | | | | | | |
         |                   ||        | | | | | | | | | |
         V                   ||        V V V V V V V V V V
Run Code Online (Sandbox Code Playgroud)

我不能只用 a 编写并行 for,#pragma omp once因为我不希望执行 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Mas*_*ano 2

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

OMP_NESTED 环境变量通过设置 Nest-var ICV 的初始值来控制嵌套并行性。该环境变量的值必须为 true 或 false。如果环境变量设置为true,则启用嵌套并行性;如果设置为 false,则禁用嵌套并行性。如果 OMP_NESTED 的值既不是 true 也不是 false,则程序的行为是实现定义的。

以下行应该适用于 bash:

 export OMP_NESTED=true
Run Code Online (Sandbox Code Playgroud)

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

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

这意味着应该将 的值设置OMP_NUM_THREADS为类似于n,n-1CPUn核心数。例如:

export OMP_NUM_THREADS=8,7
Run Code Online (Sandbox Code Playgroud)

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