这可能是新线程是的。这完全取决于平台和 OpenMP 实现。此外,OpenMP 规范未指定这一点,因此是合规行为。然而,GCC 运行时 (GOMP) 和 Intel/Clang one (IOMP) 在实践中倾向于尽可能地重用线程。在我的机器(6 核)上,我无法使用 GCC-10.2 的 GOMP 和 Clang-11.0 的 IOMP 重现您的问题。此外,以下程序显示相同的线程 ID,这可能意味着它们被重用:
#include <cstdio>
#include <unistd.h>
#include <sys/types.h>
int main() {
#pragma omp parallel num_threads(4)
printf("%d\n", gettid());
printf("----------\n");
#pragma omp parallel num_threads(8)
printf("%d\n", gettid());
printf("----------\n");
#pragma omp parallel num_threads(4)
printf("%d\n", gettid());
/*
// Update n°1
printf("----------\n");
#pragma omp parallel num_threads(8)
printf("%d\n", gettid());
*/
}
您应该检查该程序的结果。如果您无法在这个简单的示例中重现程序的行为,则意味着该问题特定于您的应用程序的行为。这可能表明您使用了多个相互冲突的 OpenMP 运行时。要检查这个假设,请设置环境变量OMP_DISPLAY_ENV=TRUE
并查看结果。当您使用嵌套区域时,这种行为也经常出现。
更新n°1:对于另一部分 8 个线程,GCC-10.2 上的 GOMP 创建新的不需要的线程,而 Clang-11.0 上的 IOMP 不会创建额外的线程。这可能是一个错误(或者是 GOMP 的一个非常令人惊讶的行为)。
更新n°2:虽然运行时的行为是实现定义的,但您可以使用环境变量向运行时提供一些提示OMP_DYNAMIC
。以下是 OpenMP 规范的规定:
The OMP_DYNAMIC
环境变量控制用于执行的线程数量的动态调整parallel
区域通过设置的初始值dyn-var
智能网联汽车。该环境变量的值必须是以下之一:true
| false
。如果环境变量设置为true
, OpenMP 实现可能会调整用于执行的线程数parallel
区域以优化系统资源的使用。如果环境变量设置为false
,线程数的动态调整被禁用。程序的行为是实现定义的,如果OMP_DYNAMIC
两者都不是true
nor false
.
然而,使用OMP_DYNAMIC=TRUE
不能解决 GOMP/GCC 上的问题。此外,在 GOMP/GCC 和 IOMP/Clang 上,它将创建的线程数量限制为可用硬件线程的数量(至少在我的机器上)。
请记住,观察到的 OpenMP 运行时行为符合规范,您的程序不应假设没有创建新线程(尽管您可能希望为了性能而调整行为)。