OpenMP并行编程实例系列3 —— 线程设置
OpenMP 线程设置
OpenMP 可以在程序中设置线程数,常用的有 3 种方式:
- 使用环境变量
OMP_NUM_THREADS
设置线程数; - 调用 OpenMP 的环境函数
omp_set_num_threads
设置线程数; - 直接在
#pragma omp
语句中使用num_threads
关键字设置线程数。
另外,还支持在多个嵌套级别上控制线程数(不同嵌套中线程可以不同)。以下的实例展示如何使用环境变量 OMP_NUM_THREADS
在多个嵌套级别上控制线程数量,为了理顺逻辑,我添加了一些打印信息。
// desc: Controlling the Number of Threads on Multiple Nesting Levels
// file: omp_nthrs_nesting.cpp
#include <cstdio>
#include <omp.h>
int main(int argc, char const *argv[])
{
omp_set_nested(1);// 设置允许嵌套并行
omp_set_dynamic(0);// 静止动态改变线程数
#pragma omp parallel
{
int tid1 = omp_get_thread_num();
printf("-1: %d\n", tid1);
#pragma omp parallel
{// 嵌套并行
int tid2 = omp_get_thread_num();
printf("-2: %d - %d\n", tid1, tid2);
#pragma omp single
{
printf("inner1: num threads %d\n", omp_get_num_threads());
}
}
#pragma omp barrier
omp_set_nested(0);
#pragma omp parallel
{
int tid2 = omp_get_thread_num();
printf("-3: %d - %d\n", tid1, tid2);
#pragma omp single
{
printf("inner2: num threads %d\n", omp_get_num_threads());
}
}
#pragma omp barrier
printf("-4: %d\n", tid1);
#pragma omp single
{
printf("outter: num threads %d\n", omp_get_num_threads());
}
}
return 0;
}
程序中一些 omp 子句的说明:
-
#pragma omp single
指定并行域中的串行任务,创建仅由一个线程执行的任务,先到先执行,其他线程等待其执行结束后再一起执行后面的任务。
-
#pragma omp barrier
等待同步:用在并行域内,所有线程执行到 barrier 都要停下等待,直到所有线程都执行到 barrier,然后再继续往下执行
以下是线程数为 2 和 3 的输出结果
$ export OMP_NUM_THREADS=2# 通过环境变量,设置线程数为2
$ ./omp_nthrs_nesting
-1: 0# 外层的线程
-1: 1
-2: 0 - 0# 嵌套的线程
inner1: num threads 2# single输出
-2: 0 - 1
-2: 1 - 0
inner1: num threads 2# single输出
-2: 1 - 1
-3: 0 - 0 # 外层线程,禁止嵌套
inner2: num threads 1# single输出
-3: 1 - 0
inner2: num threads 1# single输出
-4: 0# 外层线程
outter: num threads 2# single输出
-4: 1
$ export OMP_NUM_THREADS=3
$ ./omp_nthrs_nesting
-1: 0
-1: 2
-1: 1
-2: 0 - 0
inner1: num threads 3
-2: 0 - 2
-2: 0 - 1
-2: 2 - 1
-2: 2 - 0
-2: 2 - 2
-2: 1 - 0
inner1: num threads 3
-2: 1 - 1
-2: 1 - 2
inner1: num threads 3
-3: 0 - 0
inner2: num threads 1
-3: 2 - 0
inner2: num threads 1
-3: 1 - 0
inner2: num threads 1
-4: 0
outter: num threads 3
-4: 1
-4: 2
运行环境函数
运行环境函数(Execution Environment Routines)是用于设置和获取 OpenMP 运行属性的函数,常用函数如下:
|
|
---|---|
omp_set_num_threads(int) | 设置并行域中的线程个数(用在串行域中) |
omp_get_num_threads() | 返回当前并行域中的线程个数 |
omp_get_max_threads() | 返回并行域中缺省可用的最大线程个数 |
omp_get_thread_num() | 返回当前线程的线程号,0号为主线程 |
omp_get_num_procs() | 返回系统中处理器的个数 |
omp_in_parallel() | 判断是否在并行域中 |
omp_set_dynamic(int) | 启用或关闭线程数目动态改变功能(用在串行域中) |
omp_get_dynamic() | 判断系统是否支持动态改变线程数目 |
omp_set_nested(int) | 启用或关闭并行域嵌套功能(缺省为关闭) |
omp_get_nested() | 判断系统是否支持并行域的嵌套 |
omp_set_dynamic 函数
函数 omp_set_dynamic
是启用或关闭线程数目动态改变功能,需要在串行域中调用。它可以使 num_threads
子句的设置失效。实例如下:
// desc: Interaction Between the num_threads Clause and omp_set_dynamic
// file: omp_nthrs_dynamic.1.cpp
#include <cstdio>
#include <omp.h>
int main(int argc, char const *argv[])
{
omp_set_dynamic(1);
// omp_set_dynamic(0);
#pragma omp parallel num_threads(10)
{
int tid1 = omp_get_thread_num();
printf("tid: %d\n", tid1);
}
return 0;
}
第 9 行调用 omp_set_dynamic(1)
支持动态改变线程数,输出如下:
$ export OMP_NUM_THREADS=3# 默认为3线程
$ ./omp_nthrs_dynamic.1# 运行时设为10个线程
tid: 3
tid: 2
tid: 0
tid: 6
tid: 4
tid: 5
tid: 1
tid: 7
tid: 9
tid: 8
若屏蔽第 9 行代码,放开第 10 行 omp_set_dynamic(0)
,不支持动态改变线程数,则输出如下:
$ ./omp_nthrs_dynamic.1
tid: 0
tid: 2
tid: 1
通过调用 omp_set_dynamic
函数显式设置 ICV( Internal Control Variables 内置控制变量,用于控制 OpenMP 程序行为的变量,比如存储线程数,线程号等信息) 是一种很好的做法,因为它的默认设置是由实现定义的,不同编译器都有各自的最优实现。
原文地址:https://blog.csdn.net/myw31415926/article/details/145267310
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!