今天是OpenMP库,并发编程的一天
参考链接
https://zhuanlan.zhihu.com/p/608946001?utm_id=0
一.OpenMp的基本介绍
1. 它是gcc自带的,并发编程的标准库,它利用代码块的并行性来并发执行程序
2. 编译时需要加上 -fopenmp 选项
二.例程
下面这个程序是最基本的用法,os会分配可能多的线程去执行代码块中的语句。
```c++
#include <iostream>
#include <omp.h>
using std::cout;
using std::endl;
int main()
{
int i = 0;
#pragma omp parallel
{
cout << "hello OpenMP" << i ++ << endl;
}
return 0;
}
```
从实验结果可以看出一些。
cout << "hello OpenMP" << i ++ << endl;
上面的操作会被看成多个操作
- cout << “hello OpenMP”;
- cout << i; i ++;
- cout << endl
因此显示的结果五花八门.
三. 控制线程数量
-
使用预处理指令设置线程数量
#include <iostream> #include <omp.h> using std::cout; using std::endl; int main() { int i = 0; #pragma omp parallel num_threads(5) { cout << "hello OpenMP" << i ++ << endl; } return 0; }
-
使用api函数修改线程数目
#include <iostream> #include <omp.h> using std::cout; using std::endl; int main() { int i = 0; omp_set_num_threads(5); #pragma omp parallel { cout << "hello OpenMP" << i ++ << endl; } return 0; }
-
使用linux命令,修改环境变量
export OMP_NUM_THREADS=5 # 编译之前
四. for loop
```c++
#include <iostream>
#include <omp.h>
using std::cout;
using std::endl;
int main()
{
int i = 0;
#pragma omp parallel for
for(int i = 0; i < 10; ++i) {
printf("hello,openmp! ThreadNO.%d\n",omp_get_thread_num());
}
return 0;
}
```
这里用的是parallel for,为下面的for循环分配多个线程异步的去执行。
此外,这里用的是printf,而不是cout,从结果上看,printf只有一个输出流
而cout时有多个数处流,这其实也能理解,cout是ostream重载了<<操作符。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=.%2Fparallel_for_printf.png&pos_id=img-lDFw1vXy-1702910969313
五. 线程同步
```c++
#include <iostream>
#include <omp.h>
using std::cout;
using std::endl;
int main()
{
int sum = 0;
#pragma omp parallel for
for(int i = 0; i < 10; ++i) {
sum += i;
// printf("hello,openmp! ThreadNO.%d\n",omp_get_thread_num());
}
std::cout << sum << std::endl; //(0 + 9) * 10 / 2
return 0;
}
```
实验结果如下:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=.%2F%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%AD%A5.png&pos_id=img-I15EFV90-1702910969314
从实验结果看出,少了部分加的次数。
这是为什么呢?与数据库并发操作时出现的读未提交错误一致。
解决方案:使用临界区
```c++
#include <iostream>
#include <omp.h>
using std::cout;
using std::endl;
int main()
{
int sum = 0;
#pragma omp parallel for
for(int i = 0; i < 10; ++i) {
#pragma omp critical
{
sum += i;
}
// printf("hello,openmp! ThreadNO.%d\n",omp_get_thread_num());
}
std::cout << sum << std::endl; //(0 + 9) * 10 / 2
return 0;
}
```
此时输出正确!