Openmp中的数据处理子句


1. private

private 子句是将一个或者多个变量声明为线程私有的变量, 声明后指定的线程有他的私有副本,其他线程无法访问, 即使在并行程序外由同名的变量也不会起任何作用, 而且并行程序中的变量不会共享到并行程序之外。

code: (c++)
#include <iostream>
#include <omp.h>

using namespace std;

int main()
{
int k = 100;
#pragma omp parallel for private(k)
for(k = 0; k < 10; ++k){
printf("k = %d, ID = %d\n", k, omp_get_thread_num());
}

printf("lastK = %d\n", k);
return 0;
}
result:

这里写图片描述

2. firstprivate

private 声明的私有变量不能继承同名变量的值,但实际情况中有时需要继承原有共享变量的值, OpenMP 提供了 firstprivate 子句来实现这个功能。

code: (c++)
#include <iostream>
#include <omp.h>

using namespace std;

int main()
{
int k = 100;
#pragma omp parallel firstprivate(k)
for(int i = 0; i < 10; ++i)
{
k += i;
cout << "(k += i) : " << k <<endl;
}
cout << " real-k : " << k <<endl;
return 0;
}
result:

这里写图片描述

3. laseprivate

lastprivate 子句就是用来实现在退出并行区域时将私有变量的值赋给共享变量.

code: (c++)
#include <iostream>
#include <omp.h>

using namespace std;

int main()
{
int k = 100;

#pragma omp parallel for firstprivate(k) lastprivate(k)
for(int i = 0; i < 10; ++i)
{
k += i;
cout << " k = " << k <<endl;
}
cout << "last-k = " << k <<endl;
return 0;
}
result:

这里写图片描述

4.threadprivate

threadprivate 子句用来指定全局的对象被各个线程各自复制了一个私有的拷贝,即各个线程具有各自私有的全局对象。

code: (c++)
using namespace std;

int count = 0;
#pragma omp threadprivate(count)
int count_num()
{
count ++;
return count;
}
int main()
{
int k = 0;
#pragma omp parallel for
for(int i = 0; i < 10; ++i)
{
k = count_num();
}
cout << "k = " << k <<endl;
cout << "count = " << count << endl;
return 0;
}
result:

这里写图片描述

notice: 
threadprivate 和 private 的区别在于 threadprivate 声明的变量通常是全局范围内有效的,而private声明的变量只在它所属的并行构造中有效。threadprivate 的对应只能用于 copyin, copyprivate, schedule, num_threads 和 if 子句中,不能用于任何其他子句中。

5. shared

shared 子句用来声明一个或多个变量是共享变量。

notice:
需要注意的是,在并行区域内使用共享变量时,如果存在写操作,必须对共享变量加以保护,否则不要轻易使用共享变量,尽量将共享变量的访问转化为私有变量的访问。循环迭代变量在循环构造区域里是私有的。声明在循环构造区域内的自动变量都是私有的。

6.default

default 子句用来允许用户控制并行区域中变量的共享属性。

7.reduction

eduction 子句主要用来对一个或多个参数条目指定一个操作符,每个线程将创建参数条目的一个私有拷贝,在区域的结束处,将用私有拷贝的值通过指定的运行符运算,原始的参数条目被运算结果的值更新。
reduction 子句用法如下:
reduction(operator:list)

code: (c++)
#include <iostream>
#include <omp.h>

using namespace std;

int main()
{
int sum = 100;

#pragma omp parallel for reduction(+: sum)
for(int i = 0; i < 10; ++i)
{
sum += i;
}
cout << "sum = " << sum <<endl;
return 0;
}
result:

这里写图片描述

notice:
如果在并行区域内不加锁保护就直接对共享变量进行写操作,存在数据竞争问题,会导致不可预测的异常结果。共享数据作为 private、 firstprivate、 lastprivate、 threadprivate、reduction 子句的参数进入并行区域后,就变成线程私有了,不需要加锁保护了。

8. copyin

copyin 子句用来将主线程中 threadprivate 变量的值拷贝到执行并行区域的各个线程的threadprivate 变量中,便于线程可以访问主线程中的变量值. copyin 中的参数必须被声明成 threadprivate 的,对于类类型的变量,必须带有明确的拷贝赋值操作符。

code: (c++)
#include <iostream>
#include <omp.h>

using namespace std;

int count = 0;
#pragma omp threadprivate(count)
int count_num()
{
count++;
return count;
}

int main()
{
int cnt1 = 0, cnt2 = 0;

#pragma omp parallel sections copyin(count)
{
#pragma omp section
{
#pragma omp parallel for
for(int i = 0; i < 100; ++i)
{
cnt1 = count_num();
}
}

#pragma omp section
{
#pragma omp parallel for
for(int i = 0; i < 200; ++i)
{
cnt2 = count_num();
}
}
}
cout << "count = " << count << endl;
cout << " cnt1 = " << cnt1 <<endl;
cout << " cnt2 = " << cnt2 <<endl;
return 0;
}
result:

这里写图片描述

9. copyprivate

copyprivate 子句提供了一种机制用一个私有变量将一个值从一个线程广播到执行同一并行区域的其他线程。
copyprivate 子句可以关联 single 构造,在 single 构造的 barrier 到达之前就完成了广播工作。copyprivate 可以对 private 和 threadprivate 子句中的变量进行操作,但是当使用 single 构造时, copyprivate 的变量不能用于 private 和 firstprivate 子句中。

code: (c++)
#include <iostream>
#include <omp.h>

using namespace std;

int counter = 0;

#pragma omp threadprivate(counter)
int count_num()
{
counter++;
return (counter);
}

int main()
{
int ans = 0;
#pragma omp parallel
{
#pragma omp single copyprivate(counter)
{
counter = 50;
}

ans = count_num();
}

printf("counter = %d\n", counter);
printf("ans = %d\n", ans);
return 0;

}
result:

这里写图片描述

智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告