如果更改 2 个部分中的线程数,OpenMP 线程的 SPID 是否应该更改?
Should SPIDs of OpenMP thread change if altering the number of threads in 2 sections?
我有 2 个 OpenMP 并行区域(我在 Linux 下的 gcc 下使用 C++)具有不同数量的线程 - 假设一个 4 个,另一个 8 个。然后,如果我 运行 ps -T $(pidof name_of_process)
,4 个 SPID 始终相同,但每次调用都会更改剩余的 4 个。示例输出:
The first output
PID SPID TTY STAT TIME COMMAND
7578 7578 pts/1 Rl+ 1:18 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7579 pts/1 Rl+ 0:57 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7580 pts/1 Rl+ 0:57 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7581 pts/1 Rl+ 0:57 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 19381 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 19382 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 19383 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 19384 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
The second output
PID SPID TTY STAT TIME COMMAND
7578 7578 pts/1 Rl+ 1:23 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7579 pts/1 Rl+ 1:01 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7580 pts/1 Rl+ 1:01 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7581 pts/1 Rl+ 1:01 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 22314 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 22315 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 22316 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 22317 pts/1 Sl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
这是否意味着OpenMP在进入8线程段时不断创建新的4线程并在之后销毁(或进入4线程段时)?我会这么认为,但是很多地方,比如 here suggest, that the threads should persist and wait for their turn. I wouldn't be bothered about the internal workings of OpenMP, but 那里的内存莫名其妙地泄漏,我开始怀疑某些线程资源没有释放(或者内存变得越来越碎片化?)。
那么这是正确的行为吗?我正在使用 gcc,gcc --version
: gcc-8 (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0
.
此外,如果是这样,是否可以在不使 2 个部分使用相同数量的线程的情况下强制 OpenMP 不不断销毁和生成新线程?
可能是新线程是的。这完全取决于平台和 OpenMP 实现。此外,这在 OpenMP 规范中未指定,因此是一种合规行为。然而,GCC runtime (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
environment variable controls dynamic adjustment of the number of threads to use for executing parallel
regions by setting the initial value of the dyn-var
ICV. The value of this environment variable must be one of the following: true
| false
. If the environment variable is set to true
, the OpenMP implementation may adjust the number of threads to use for executing parallel
regions in order to optimize the use of system resources. If the environment variable is set to false
, the dynamic adjustment of the number of threads is disabled. The behavior of the program is implementation defined if the value of OMP_DYNAMIC
is neither true
nor false
.
但是,使用 OMP_DYNAMIC=TRUE
并不能解决 GOMP/GCC 上的问题。此外,在 GOMP/GCC 和 IOMP/Clang 上,它将创建的线程数限制为可用硬件线程数(至少在我的机器上)。
请记住,观察到的 OpenMP 运行时行为符合规范,您的程序不应假设没有创建新线程(尽管您可能希望为了性能调整行为)。
我有 2 个 OpenMP 并行区域(我在 Linux 下的 gcc 下使用 C++)具有不同数量的线程 - 假设一个 4 个,另一个 8 个。然后,如果我 运行 ps -T $(pidof name_of_process)
,4 个 SPID 始终相同,但每次调用都会更改剩余的 4 个。示例输出:
The first output
PID SPID TTY STAT TIME COMMAND
7578 7578 pts/1 Rl+ 1:18 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7579 pts/1 Rl+ 0:57 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7580 pts/1 Rl+ 0:57 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7581 pts/1 Rl+ 0:57 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 19381 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 19382 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 19383 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 19384 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
The second output
PID SPID TTY STAT TIME COMMAND
7578 7578 pts/1 Rl+ 1:23 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7579 pts/1 Rl+ 1:01 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7580 pts/1 Rl+ 1:01 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 7581 pts/1 Rl+ 1:01 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 22314 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 22315 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 22316 pts/1 Rl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
7578 22317 pts/1 Sl+ 0:00 ./rampack casino -i banana_cube.ini --start-from=0p5 --continue=100000
这是否意味着OpenMP在进入8线程段时不断创建新的4线程并在之后销毁(或进入4线程段时)?我会这么认为,但是很多地方,比如 here suggest, that the threads should persist and wait for their turn. I wouldn't be bothered about the internal workings of OpenMP, but
那么这是正确的行为吗?我正在使用 gcc,gcc --version
: gcc-8 (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0
.
此外,如果是这样,是否可以在不使 2 个部分使用相同数量的线程的情况下强制 OpenMP 不不断销毁和生成新线程?
可能是新线程是的。这完全取决于平台和 OpenMP 实现。此外,这在 OpenMP 规范中未指定,因此是一种合规行为。然而,GCC runtime (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
environment variable controls dynamic adjustment of the number of threads to use for executingparallel
regions by setting the initial value of thedyn-var
ICV. The value of this environment variable must be one of the following:true
|false
. If the environment variable is set totrue
, the OpenMP implementation may adjust the number of threads to use for executingparallel
regions in order to optimize the use of system resources. If the environment variable is set tofalse
, the dynamic adjustment of the number of threads is disabled. The behavior of the program is implementation defined if the value ofOMP_DYNAMIC
is neithertrue
norfalse
.
但是,使用 OMP_DYNAMIC=TRUE
并不能解决 GOMP/GCC 上的问题。此外,在 GOMP/GCC 和 IOMP/Clang 上,它将创建的线程数限制为可用硬件线程数(至少在我的机器上)。
请记住,观察到的 OpenMP 运行时行为符合规范,您的程序不应假设没有创建新线程(尽管您可能希望为了性能调整行为)。