目录
openmp 数据环境
子句:
shared(list)
private(list)//默认构造 值未被初始化
对于图6-5:
//File #1
int tmp;
void danger()
{
tmp = 0;
#pragma omp parallel private(tmp)
work();
printf("%d\n", tmp); // tmp has unspecified value
}
// File #2
extern int tmp;
void work()
{
tmp = 5;
}
输出5;
当
#include"test6_5.hpp"
#include<iostream>
#include<omp.h>
int tmp;
int main(){
tmp = 0;
#pragma omp parallel private(tmp)
work(tmp);
std::cout<<tmp;
return 0;
}
extern int tmp;
void work(int& tmp){
tmp = 5;
}
输出0;
当
#include"test6_5.hpp"
#include<iostream>
#include<omp.h>
int tmp;
int main(){
tmp = 0;
#pragma omp parallel private(tmp)
work(tmp);
std::cout<<tmp;
return 0;
}
//extern int tmp;
void work(int& tmp){
tmp = 5;
}
输出0;
个人理解:extern int tmp 不知道应该使用文件域范围的tmp还是数据环境中私有的tmp所以会出现第一种情况。
firstprivate(list) //copy复制构造
default(none) //如果在构造体上使用default(none),那么所有从遭遇线程传递到区域的变量必须明确地列在private、firstprivate、shared、或reduction子句中,编译器会将没有列出的变量标记为错误。
在上述三个子句中也可以传入指针和数组
具体参考:https://www.openmp.org/spec-html/5.0/openmpsu21.html#:~:text=When%20the%20size%20of%20the%20array%20dimension%20is,the%20lower-bound%20is%20absent%20it%20defaults%20to%200.
openmp 任务:
#pragma omp task //task构造创建一个显式的任务
#pragma omp single //single构造创建一个共享工作构造,与所有的共享工作构造一样,末尾有一个栅栏,可以使用nowait去除栅栏
图7—9:
#pragma omp parallel
{
#pragma omp single
{
p = listhead;
while (p)
{
#pragma omp task firstprivate(p)
{
process (p);
} // end of task creation
p = p->next;
}
} // end of single region
} // end of parallel region
#pragma omp single 只允许一个线程创建任务,其他线程虽然在栅栏处等待,但是会处理process()而且此时single线程,不一定运行到了single块最后,可能还在创建线程。
图7-11:
int fib (int n)
{
int x,y;
if (n < 2) return n;
#pragma omp task shared(x)
x = fib(n-1);
#pragma omp task shared(y)
y = fib(n-2);
#pragma omp taskwait
return (x+y);
}
int main()
{
int NW = 30;
#pragma omp parallel
{
#pragma omp single
fib(NW);
}
}
#pragma omp taskwait
使用taskwait强制等待这个点以前的所有兄弟任务和子任务完成,
对于这个程序,为了x,y在每个任务的数据环境之外可用,他们必须被共享。
openmp内存模型:
三个简单的规则来描述openmp通用核心中的内存模型:
1.当混合来自多个线程的共享变量的读写操作时,确保在写入和后续读取之间有一个栅栏(显示栅栏或隐式栅栏)
2.在算法的控制流不支持栅栏的区域内更新共享变量时,要用临界区保护更新
3.不使用变量的值来定义线程之间的排序约束,即使它们是以无竞争的方式更新的。顺序约束在通用核心中是通过栅栏来定义的。
内存一致性规则:
线程使用冲刷来使其变量与内存保持一致。在以下位置隐含了一次冲刷:
1.进入和退出临界区构造;
2.从显式或隐式栅栏中退出