OpenMP 嵌套未关闭

  • 本文关键字:嵌套 OpenMP c++ c openmp
  • 更新时间 :
  • 英文 :


我正在尝试使用 OpenMP(4.5,通过 GCC 7.2.0(管理嵌套的并行区域,但在关闭嵌套时遇到了一些问题。

示例程序:

#include <stdio.h>
#include <omp.h>
void foobar() {
int tid = omp_get_thread_num();
#pragma omp parallel for
for (int i = 0; i < 4; i++) {
int otid = omp_get_thread_num();
printf("%d | %dn", tid, otid);
}
}
int main(void) {
omp_set_nested(0);
#pragma omp parallel
{
foobar();
}
printf("n");
foobar();
return 0;
}

期望在这里发生的是 foobar(( 上的并行区域和非并行调用都会吐出 4 行,类似于

// parallel region foobar()
0 | 0
1 | 1
2 | 2
3 | 3
// serial region foobar()
0 | 0
0 | 1
0 | 2
0 | 3

因为我不允许嵌套并行。 但是,我在具有正确 TID 的并行区域内获得 16 行,但 OTID 始终为 0(即每个线程都生成自己的 4 行,并在其上执行整个循环(,我在外面得到 4 行(即并行 for 正在生成 4 个线程,正如我所期望的那样(

我觉得我在这里错过了一些非常明显的东西,有人能为我提供一些启示吗? 禁用嵌套不是应该将 omp 并行转换为常规 omp for 并相应地分配工作吗?

您的问题来自错误的假设,即无论哪个区域处于活动状态parallel,都将解释omp for指令并在线程之间分配相应的工作。遗憾的是,在您的代码中,omp for仅与函数foobar()中声明的parallel区域相关联。因此,当此区域被激活时(这意味着由于您禁用了嵌套并行性,当foobar()未从另一个parallel区域调用时(,您的循环将分布在新生成的线程中。但当不是时,由于foobar()是从另一个parallel区域调用的,因此将忽略omp for,并且循环不会分布在调用线程之间。因此,它们中的每一个都执行整个循环,从而导致您看到的printf()的复制。

一个可能的解决方案是这样的:

#include <stdio.h>
#include <omp.h>
void bar(int tid) {
#pragma omp for
for (int i = 0; i < 4; i++) {
int otid = omp_get_thread_num();
printf("%d | %dn", tid, otid);
}
}
void foobar() {
int tid = omp_get_thread_num();
int in_parallel = omp_in_parallel();
if (!in_parallel) {
#pragma omp parallel
bar(tid);
}
else {
bar(tid);
}
}
int main() {
#pragma omp parallel
foobar();
printf("n");
foobar();
return 0;
}

我真的不觉得这个解决方案完全令人满意,但我现在没有看到更好的解决方案。也许以后我会得到一些启发...

编辑:好吧,我有另一个想法:以相反的方式执行此操作并强制嵌套并行性,每当从实际parallel区域调用函数时,只有一个活动线程:

#include <stdio.h>
#include <omp.h>
void foobar() {
int tid = omp_get_thread_num();
omp_set_nested(1);
#pragma omp single
#pragma omp parallel for
for (int i = 0; i < 4; i++) {
int otid = omp_get_thread_num();
printf("%d | %dn", tid, otid);
}
}
int main() {
#pragma omp parallel
foobar();
printf("n");
foobar();
return 0;
}

这次代码看起来更好,没有任何重复,并给出(例如(:

$ OMP_NUM_THREADS=4 ./nested
3 | 2
3 | 3
3 | 1
3 | 0
0 | 3
0 | 1
0 | 0
0 | 2

最新更新