文章目录
- 配置CMakeList.txt文件
- OpenMP之HelloWorld
- 数据共享属性
- shared子句
- private子句
- default子句
- default(shared)
- default(none)
配置CMakeList.txt文件
文件底部加入以下内容,即可支持OpenMP
FIND_PACKAGE(OpenMP REQUIRED)
if (OPENMP_FOUND)
message("OPENMP FOUND")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif ()
参考链接:openmp基本使用
OpenMP之HelloWorld
#include <iostream>
#include "omp.h"
using namespace std;
int main() {
//设置线程数,一般设置的线程数不超过CPU核心数,这里开3个线程执行并行代码段
omp_set_num_threads(3);
#pragma omp parallel
{
printf("hello, I am Thread %d\n", omp_get_thread_num());
}
}
注意:
- #pragma后 “{” 一定要换行。
- 使用printf来避免输出混乱(cout流输出会造成输出混乱)
可以看到,多线程执行,导致输出不确定。
数据共享属性
openmp并行区域中的变量可以是共享的,也可以是私有的
- 如果一个变量是共享的,那么这个变量存在一个实例,在所有线程之间共享。请始终记住共享变量会产生额外的开销。 因此当需要良好的性能时,通常最好尽量减少共享变量的数量。
- 如果一个变量是私有的,那么线程组中的每个线程都有自己的私有变量的本地副本。
另外,openmp有一套规则,当变量的属性没有被声明的时候,可以推断变量的数据共享属性。
- 在并行区域之外声明的变量的数据共享属性通常是共享的,因此n和a是共享变量。
- 循环迭代变量默认情况下是私有的,因此i是私有的。
- 在平行区域内局部声明的变量是私有的,因此b是私有变量。
shared子句
- i,a都是parallel区域之外声明的变量,所以他们的数据共享属性是共享的。
- 我们也可以使用shared子句,显式的声明变量的共享属性。
- parallel区域内改变变量会对区域外的变量有影响。
#include <iostream>
#include "omp.h"
using namespace std;
int main() {
int i = 0;
float a = 512.3;
#pragma omp parallel //shared(a,n)
{
i = i + 1;
printf("thread %d ,i = %d ,a= %lf\n", omp_get_thread_num(), i, a);
}
printf("out of parallel i = %d", i);
}
可以看到,parallel区域内改变i的值,区域外的i也被改变。证明他们是同一个i。
private子句
我们可以通过在并行区域内声明私有变量来避免在 openMP 结构中列出私有变量。最好尽可能在并行区域内声明私有变量,这条准则简化了代码并提高了可读性。
#include <iostream>
#include "omp.h"
using namespace std;
int main() {
int i = 0;
float a = 512.3;
#pragma omp parallel private(i,a)
{
i = i + 1;
printf("thread %d ,i = %d ,a= %lf\n", omp_get_thread_num(), i, a);
}
printf("out of parallel i = %d", i);
}
区域内的变量被声明为private时,各线程内各自的变量都被随机初始化,而且和并行区域外部同名变量无关。
default子句
default(shared)
- 默认并行区域内的变量都属于共享变量
- 严重不建议使用default(shared),它只会令代码的阅读性非常差。
default(none)
default (none) 子句强制程序员明确指定所有变量的数据共享属性