如何通过循环将 OpenMP 线程拆分为子组
How to split OpenMP threads into subteams over a loop
假设我有一个以下函数,它在内部使用#pragma omp parallel
。
void do_heavy_work(double * input_array);
我现在想这样do_heavy_work
许多input_arrays
:
void do_many_heavy_work(double ** input_arrays, int num_arrays)
{
for (int i = 0; i < num_arrays; ++i)
{
do_heavy_work(input_arrays[i]);
}
}
假设我有N
硬件线程。上面的实现将导致do_heavy_work
的调用以串行方式发生num_arrays
每个N
线程在内部使用所有线程来执行它想要的任何并行操作。
现在假设num_arrays > 1
时,通过这个外部循环并行实际上比在do_heavy_work
内部并行更有效。我现在有以下选择。
- 将
#pragma omp parallel for
放在外环上并设置OMP_NESTED=1
。但是,通过设置OMP_NUM_THREADS=N
我最终将生成大量线程(N*num_arrays
(。 - 如上所述,但关闭嵌套并行性。这在
num_arrays < N
时浪费了可用的内核。
理想情况下,我希望 OpenMP 将其OMP_NUM_THREADS
线程团队拆分为num_arrays
子团队,然后每个do_heavy_work
都可以在其分配的子团队上线程(如果给定一些子团队(。
实现这一目标的最简单方法是什么?
(出于此讨论的目的,我们假设事先不一定知道num_arrays
,并且我无法更改do_heavy_work
本身的代码。该代码应该在多台机器上工作,因此N
应该是可自由指定的。
OMP_NUM_THREADS
可以设置为列表,从而指定每个嵌套级别的线程数。 例如 OMP_NUM_THREADS=10,4
将告诉 OpenMP 运行时执行具有 10 个线程的外部并行区域,每个嵌套区域将使用 4 个线程执行,总共最多有 40 个同时运行的线程。
或者,您可以使用类似于以下内容的代码使程序自适应:
void do_many_heavy_work(double ** input_arrays, int num_arrays)
{
#pragma omp parallel num_threads(num_arrays)
{
int nested_team_size = omp_get_max_threads() / num_arrays;
omp_set_num_threads(nested_team_size);
#pragma omp for
for (int i = 0; i < num_arrays; ++i)
{
do_heavy_work(input_arrays[i]);
}
}
}
如果 OMP_NUM_THREADS
的值不能被 num_arrays
整除,则此代码不会使用所有可用的线程。如果每个嵌套区域具有不同数量的线程是可以的(这可能会导致某些数组的处理速度比其他数组更快(,请了解如何分配线程并相应地在每个线程中设置nested_team_size
。从并行区域内调用omp_set_num_threads()
仅影响由调用线程启动的嵌套区域,因此可以具有不同的嵌套团队大小。
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- 将执行循环拆分为多个线程 (1-N-1-N-1..)
- 跨线程共享数据集与拆分每个线程的数据
- 如何通过循环将 OpenMP 线程拆分为子组
- 使用哪个线程并行接口来使用堆栈进行任务共享和拆分
- 是否可以将Qt GUI拆分为多个线程用于GUI,仿真和OpenGL
- 将2-Dim循环拆分为多个线程