当前位置: 首页 > 网络知识

OpenMP 基本使用和critical指令

时间:2026-01-26 14:19:54

  MPI是可以针对分布式内存,在进程级别实现并行的API;OpenMP则是针对共享内存,在线程级别实现并行的API。

基本使用
  不同于MPI的init和finalize,OpenMP用携带了parallel指令的预处理指令指示接下来的一个代码块被多个线程执行。

  OpenMP预处理指令(携带)>OpenMP指令(携带)>OpenMP指令的子句。

  隐式路障是OpenMP的一个特点,所有执行这个代码块的线程在同一个线程组中以隐式路障隐式同步。

1 #include<stdio.h> 2 #include<stdlib.h> 3 4 //检查是否定义了_OPENMP预处理宏,即编译器是否支持OpenMP 5 #ifdef _OPENMP 6 #include<p.h> //支持时包含OpenMP头文件 7 #endif 8 9 int main(int argc,char *argv[]) 10 //隐式路障:完成代码块的线程要等待其它所有线程完成此代码块 39 printf("路障解除了\n"); 40 return 0; 41 }

输出

1 [lzh@hostlzh OpenMP]$ !gcc 2 gcc fopenmp o hello.o hello 3 [lzh@hostlzh OpenMP]$ ./hello.o 4 4 strtol()函数从主函数参数解析得的线程数:4 5 我是0/4 6 我是1/4 7 我是2/4 8 我是3/4 9 路障解除了 10 [lzh@hostlzh OpenMP]$

critical指令
  OpenMP里变量的作用域可以按照块内是否共享分为共享作用域和私有作用域。对于并行代码块而言,在块前声明的变量缺省作用域是共享的(不过这个”共享”当然不能穿透函数)。

某些地方未使用critical时可能存在的问题
  当块内共同操作了共享的资源时,不对其做互斥保护就可能会在运行时出问题。因为只能保证一次汇编级的指令是原子的,甚至不能保证一条C语言语句在并发执行过程中不会发生线程的切换,在并行的情况下就更加危险了:

1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<p.h> 4 5 int main(int argc,char *argv[]) 6

输出

1 [lzh@hostlzh OpenMP]$ !gcc 2 gcc fopenmp o test1.o test1 3 [lzh@hostlzh OpenMP]$ ./test1.o 15 4 a=5 5 [lzh@hostlzh OpenMP]$ ./test1.o 15 6 a=5 7 [lzh@hostlzh OpenMP]$ ./test1.o 15 8 a=5 9 [lzh@hostlzh OpenMP]$ ./test1.o 15 10 a=5 11 [lzh@hostlzh OpenMP]$ ./test1.o 15 12 a=5 13 [lzh@hostlzh OpenMP]$ ./test1.o 15 14 a=6 15 [lzh@hostlzh OpenMP]$ ./test1.o 15 16 a=5 17 [lzh@hostlzh OpenMP]$ ./test1.o 15 18 a=5

才执行了这么几次就发生了出错,可见问题严重。

使用critical时

1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<p.h> 4 5 int main(int argc,char *argv[]) 6 17 printf("a=%d\nb=%d\n",a,b);//最终输出看一下 18 return 0; 19 }

输出

1 [lzh@hostlzh OpenMP]$ !gcc 2 gcc fopenmp o test1.o test1 3 [lzh@hostlzh OpenMP]$ ./test1.o 15 4 a=5 5 b=5 6 [lzh@hostlzh OpenMP]$ ./test1.o 15 7 a=5 8 b=5 9 [lzh@hostlzh OpenMP]$ ./test1.o 15 10 a=5 11 b=5 12 [lzh@hostlzh OpenMP]$ ./test1.o 15 13 a=5 14 b=5 15 [lzh@hostlzh OpenMP]$ ./test1.o 15 16 a=5 17 b=5 18 [lzh@hostlzh OpenMP]$ ./test1.o 15 19 a=5 20 b=5 21 [lzh@hostlzh OpenMP]$ ./test1.o 15 22 a=5 23 b=5 24 [lzh@hostlzh OpenMP]$ ./test1.o 15 25 a=5 26 b=5 27 [lzh@hostlzh OpenMP]$ ./test1.o 15 28 a=5 29 b=5 30 [lzh@hostlzh OpenMP]$ ./test1.o 15 31 a=5 32 b=5 33 [lzh@hostlzh OpenMP]$ ./test1.o 15 34 a=5 35 b=5 36 [lzh@hostlzh OpenMP]$ ./test1.o 15 37 a=5 38 b=5 39 [lzh@hostlzh OpenMP]$ ./test1.o 15 40 a=5 41 b=5 42 [lzh@hostlzh OpenMP]$ ./test1.o 15 43 a=5 44 b=6 45 [lzh@hostlzh OpenMP]$ ./test1.o 15 46 a=5 47 b=5 48 [lzh@hostlzh OpenMP]$ ./test1.o 15 49 a=5 50 b=5 51 [lzh@hostlzh OpenMP]$ ./test1.o 15 52 a=5 53 b=5 54 [lzh@hostlzh OpenMP]$

可见受critical指令保护的a能够正常执行了,而不受保护的b仍然会发生前面的问题。



上一篇:C++ 计时方法 std::chrono
下一篇:Expat XML解析库
OpenMP
  • 英特尔与 Vertiv 合作开发液冷 AI 处理器
  • 英特尔第五代 Xeon CPU 来了:详细信息和行业反应
  • 由于云计算放缓引发扩张担忧,甲骨文股价暴跌
  • Web开发状况报告详细介绍可组合架构的优点
  • 如何使用 PowerShell 的 Get-Date Cmdlet 创建时间戳
  • 美光在数据中心需求增长后给出了强有力的预测
  • 2027服务器市场价值将接近1960亿美元
  • 生成式人工智能的下一步是什么?
  • 分享在外部存储上安装Ubuntu的5种方法技巧
  • 全球数据中心发展的关键考虑因素
  • 英特尔与 Vertiv 合作开发液冷 AI 处理器

    英特尔第五代 Xeon CPU 来了:详细信息和行业反应

    由于云计算放缓引发扩张担忧,甲骨文股价暴跌

    Web开发状况报告详细介绍可组合架构的优点

    如何使用 PowerShell 的 Get-Date Cmdlet 创建时间戳

    美光在数据中心需求增长后给出了强有力的预测

    2027服务器市场价值将接近1960亿美元

    生成式人工智能的下一步是什么?

    分享在外部存储上安装Ubuntu的5种方法技巧

    全球数据中心发展的关键考虑因素