我对在代码的并行部分中指定线程数的方法感到很困惑。 我知道我可以使用:
#pragma omp parallel for num_threads(NB_OF_THREADS)
到目前为止我收集到的前两个是等价的。但是第三个呢? 有人可以提供更详细的差异说明,我在互联网上找不到关于1/2和3之间差异的任何信息。
答案 0 :(得分:24)
OMP_NUM_THREADS
和omp_set_num_threads()
不相同。环境变量仅用于设置 nthreads-var ICV(内部控制变量)的初始值,该值控制团队中的最大线程数。 omp_set_num_threads()
可用于随时更改 nthreads-var 的值(当然,在任何并行区域之外),并影响所有后续并行区域。因此,设置一个值,例如n
,OMP_NUM_THREADS
等同于在遇到第一个并行区域之前调用omp_set_num_threads(n)
。
在OpenMP网站上免费提供的OpenMP specification中非常清楚地描述了确定并行区域中线程数的算法:
如果存在
num_threads
子句然后让 ThreadsRequested 成为
num_threads
子句表达式的值;让 ThreadsRequested = nthreads-var 的第一个元素的值;
设置 nthreads-var 的不同方法的优先级列在规范的 ICV覆盖关系部分中:
num_threads
子句和omp_set_num_threads()
覆盖OMP_NUM_THREADS
环境变量的值以及 nthreads-var ICV的第一个元素的初始值。
翻译成人类语言,即:
OMP_NUM_THREADS
(如果存在)最初指定线程数; omp_set_num_threads()
的来电覆盖了OMP_NUM_THREADS
; num_threads
子句的存在会覆盖其他两个值。使用的实际线程数也受动态团队规模是否已启用( dyn-var ICV可通过OMP_DYNAMIC
和/或omp_set_dynamic()
设置)的影响,是否 thread-limit-var (可通过OMP_THREAD_LIMIT
设置)强制执行线程限制,以及是否启用嵌套并行(OMP_NESTED
/ omp_set_nested()
)或不。
答案 1 :(得分:4)
将其视为范围。选项3(num_threads)仅设置当前线程组的线程数。其他选项是全局/状态设置。我通常不设置线程数,而只是使用默认值。当我确实通常只在特殊情况下更改线程数时,所以我使用选项3,以便下次使用并行团队时它返回到全局(默认)设置。请参阅下面的代码。在我使用选项3后,下一个线程团队将返回到上一个全局设置。
#include <stdio.h>
#include <omp.h>
int main() {
#pragma omp parallel
{
#pragma omp single
{
printf("%d\n", omp_get_num_threads());
}
}
omp_set_num_threads(8);
#pragma omp parallel
{
#pragma omp single
{
printf("%d\n", omp_get_num_threads());
}
}
#pragma omp parallel num_threads(2)
{
#pragma omp single
{
printf("%d\n", omp_get_num_threads());
}
}
#pragma omp parallel
{
#pragma omp single
{
printf("%d\n", omp_get_num_threads());
}
}
}
4 8 2 8