openMP是并行里面最简单的一个,使用共享存储式的并行,数据在同一个内存区中不需要进行数据交换。并且只需要将串行的代码段进行简单的注释就可以得到并行的程序,且这种并行在核数不太多的时候(小型服务器的规模内)并行效率还是很高的。此前已经在很多课程中学习到了这种并行,现在开始要大规模用到了,就再重新复习一下。
例子1:HelloThread.c
#include <stdio.h>
#include <stdlib.h>
#include "omp.h"
int main(int argc,char **argv){
int tid;
omp_set_num_threads(4);
#pragma omp parallel
{
tid = omp_get_thread_num();
printf("Hello, I am thread %d\n",tid);
}
return 0;
}
这里的omp_set_num_threads(4)
设置并行核数为4,#pragma omp parallel
下面括号括住的部分为并行区域。编译使用虚拟机Ubuntu16.04版本,gcc
和g++
都可以编译,但需要添加-fopenmp
选项,输出结果如下:
例子2:ParallelFor.c
代码段和之前相似:
#include <stdio.h>
#include <stdlib.h>
#include "omp.h"
int main(int argc,char **argv){
omp_set_num_threads(4);
#pragma omp parallel for
for (int i=0;i<6;i++)
printf("i=%d, I am Thread %d\n",i,omp_get_thread_num());
return 0;
}
注意其中的注释项#pragma omp parallel for
增加了一个for,即在代码块中的for循环是并行的,如果使用原来的选项#pragma omp parallel
该代码的输出结果为如下:
即每个CPU均执行这个循环,输出了很多,如果使用#pragma omp parallel for
。输出结果则为如下:
输出结果为4个CPU核一起一共执行了六次循环,而每个CPU执行循环的哪一步是openMP自动分配的。
例子3: ParaSum.c
#include <stdio.h>
#include <stdlib.h>
#include "omp.h"
int main(int argc,char **argv){
int n = 1000000;
int sum = 0;
omp_set_num_threads(4);
#pragma omp parallel
{
#pragma omp for
for (int i=0;i<n;i++)
{
#pragmma omp critical
sum = sum + 1;
}
}
printf("sum=%d\n",sum);
return 0;
}
执行结果为,
注意其中的注释选项#pragmma omp critical
,表示注释下面的代码块,一次只有一共CPU可以执行。避免出现变量sum
存取冲突的情况,去掉后,可能出现执行结果不是100000的情形,当时当前虚拟机为单核。。。执行不出有问题的结果。另外并行的代码块还可以替换成如下:
#pragma omp parallel
{
#pragma omp for schedule(static,3)
for (int i=0;i<n;i++)
{
sum = sum + 1;
}
}
新的编译选项#pragma omp for schedule(static,3)
也是循环并行的控制语句。两个输入值分别代表CPU的任务分配策略和每次分配的循环块大小。具体可以参考ttps://blog.csdn.net/billbliss/article/details/44131919
参考资料
这个帖子对openMP中的具体语句进行了完整的总结,了解大体结构后,需要更多功能可以查阅这个帖子:
https://www.cnblogs.com/lfri/p/10111315.html
https://www.cnblogs.com/lfri/p/10111466.html
https://www.cnblogs.com/lfri/p/10117193.html