OpenMP并行编程实例系列3 —— 线程设置

打印 上一主题 下一主题

主题 1051|帖子 1051|积分 3153

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
OpenMP 线程设置

OpenMP 可以在程序中设置线程数,常用的有 3 种方式:


  • 使用环境变量 OMP_NUM_THREADS 设置线程数;
  • 调用 OpenMP 的环境函数 omp_set_num_threads 设置线程数;
  • 直接在 #pragma omp 语句中使用 num_threads 关键字设置线程数。
别的,还支持在多个嵌套级别上控制线程数(不同嵌套中线程可以不同)。以下的实例展示如何使用环境变量 OMP_NUM_THREADS 在多个嵌套级别上控制线程数目,为了理顺逻辑,我添加了一些打印信息。
  1. // desc: Controlling the Number of Threads on Multiple Nesting Levels
  2. // file: omp_nthrs_nesting.cpp
  3. #include <cstdio>
  4. #include <omp.h>
  5. int main(int argc, char const *argv[])
  6. {
  7.     omp_set_nested(1);        // 设置允许嵌套并行
  8.     omp_set_dynamic(0);        // 静止动态改变线程数
  9.     #pragma omp parallel
  10.     {
  11.         int tid1 = omp_get_thread_num();
  12.         printf("-1: %d\n", tid1);
  13.         #pragma omp parallel
  14.         {        // 嵌套并行
  15.             int tid2 = omp_get_thread_num();
  16.             printf("-2: %d - %d\n", tid1, tid2);
  17.             #pragma omp single
  18.             {
  19.                 printf("inner1: num threads %d\n", omp_get_num_threads());
  20.             }
  21.         }
  22.         #pragma omp barrier
  23.         omp_set_nested(0);
  24.         #pragma omp parallel
  25.         {
  26.             int tid2 = omp_get_thread_num();
  27.             printf("-3: %d - %d\n", tid1, tid2);
  28.             #pragma omp single
  29.             {
  30.                 printf("inner2: num threads %d\n", omp_get_num_threads());
  31.             }
  32.         }
  33.         #pragma omp barrier
  34.         printf("-4: %d\n", tid1);
  35.         #pragma omp single
  36.         {
  37.             printf("outter: num threads %d\n", omp_get_num_threads());
  38.         }
  39.     }
  40.     return 0;
  41. }
复制代码
程序中一些 omp 子句的分析:


  • #pragma omp single
    指定并行域中的串行任务,创建仅由一个线程实行的任务,先到先实行,其他线程期待实在行结束后再一起实行后面的任务。
  • #pragma omp barrier
    期待同步:用在并行域内,全部线程实行到 barrier 都要停下期待,直到全部线程都实行到 barrier,然后再继续往下实行
以下是线程数为 2 和 3 的输出结果
  1. $ export OMP_NUM_THREADS=2        # 通过环境变量,设置线程数为2
  2. $ ./omp_nthrs_nesting
  3. -1: 0        # 外层的线程
  4. -1: 1
  5. -2: 0 - 0        # 嵌套的线程
  6. inner1: num threads 2        # single输出
  7. -2: 0 - 1
  8. -2: 1 - 0
  9. inner1: num threads 2        # single输出
  10. -2: 1 - 1
  11. -3: 0 - 0         # 外层线程,禁止嵌套
  12. inner2: num threads 1        # single输出
  13. -3: 1 - 0
  14. inner2: num threads 1        # single输出
  15. -4: 0        # 外层线程
  16. outter: num threads 2        # single输出
  17. -4: 1
  18. $ export OMP_NUM_THREADS=3
  19. $ ./omp_nthrs_nesting
  20. -1: 0
  21. -1: 2
  22. -1: 1
  23. -2: 0 - 0
  24. inner1: num threads 3
  25. -2: 0 - 2
  26. -2: 0 - 1
  27. -2: 2 - 1
  28. -2: 2 - 0
  29. -2: 2 - 2
  30. -2: 1 - 0
  31. inner1: num threads 3
  32. -2: 1 - 1
  33. -2: 1 - 2
  34. inner1: num threads 3
  35. -3: 0 - 0
  36. inner2: num threads 1
  37. -3: 2 - 0
  38. inner2: num threads 1
  39. -3: 1 - 0
  40. inner2: num threads 1
  41. -4: 0
  42. outter: num threads 3
  43. -4: 1
  44. -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 子句的设置失效。实比方下:
  1. // desc: Interaction Between the num_threads Clause and omp_set_dynamic
  2. // file: omp_nthrs_dynamic.1.cpp
  3. #include <cstdio>
  4. #include <omp.h>
  5. int main(int argc, char const *argv[])
  6. {
  7.     omp_set_dynamic(1);
  8.     // omp_set_dynamic(0);
  9.     #pragma omp parallel num_threads(10)
  10.     {
  11.         int tid1 = omp_get_thread_num();
  12.         printf("tid: %d\n", tid1);
  13.     }
  14.     return 0;
  15. }
复制代码
第 9 行调用 omp_set_dynamic(1) 支持动态改变线程数,输出如下:
  1. $ export OMP_NUM_THREADS=3        # 默认为3线程
  2. $ ./omp_nthrs_dynamic.1                # 运行时设为10个线程
  3. tid: 3
  4. tid: 2
  5. tid: 0
  6. tid: 6
  7. tid: 4
  8. tid: 5
  9. tid: 1
  10. tid: 7
  11. tid: 9
  12. tid: 8
复制代码
若屏蔽第 9 行代码,放开第 10 行 omp_set_dynamic(0) ,不支持动态改变线程数,则输出如下:
  1. $ ./omp_nthrs_dynamic.1
  2. tid: 0
  3. tid: 2
  4. tid: 1
复制代码
通过调用 omp_set_dynamic 函数显式设置 ICV( Internal Control Variables 内置控制变量,用于控制 OpenMP 程序举动的变量,比如存储线程数,线程号等信息) 是一种很好的做法,因为它的默认设置是由实现定义的,不同编译器都有各自的最优实现。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

自由的羽毛

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表