操作 #pragma omp xxx reduction()"/>
OpenMP中的Reduction操作 #pragma omp xxx reduction()
参考
OpenMP: For & Reduction
Reduction
Reduction
操作类似于我们将很多东西组合组合在一起,比如MapReduce
中先Map
操作将数据分散,再通过Reduce
将相同键的值合并起来。而OpenMP
中的Reduction
操作就用在这方面。
简单的for循环
int sum = 0;
for (int i = 0; i <= 10; ++i)
{sum += i;
}
cout<<sum<<endl;
例如上述的一个简单的for
循环,如果我们使用parallel for
并行,因为sum
是被所有的线程共享的值,所以很可能出现很多线程同时读取sum
并将其加上一些值,这就带来数据冲突,产生错误。
#include <omp.h>
#include <iostream>
using namespace std;int main()
{int sum = 0;omp_set_num_threads(5);#pragma omp parallel forfor (int i = 0; i <= 10; ++i){sum += i;}cout<<sum<<endl;return 0;
}
上述代码结果应为55,多次执行其结果并不一致。
这里我们就可以用到reduction
。
使用Reduction
会造成冲突的数据是sum
,我们要对sum
执行的操作是+
,所以在使用Reduction
时,我们声明类似为:reduction(+: sum)
。代码如下:
#include <omp.h>
#include <iostream>
using namespace std;int main()
{int sum = 0;omp_set_num_threads(5);#pragma omp parallel for reduction(+: sum)for (int i = 0; i <= 10; ++i){sum += i;}cout<<sum<<endl;return 0;
}
这样,执行的结果就正确了。
原理
我们输出线程号看看都是哪个线程操作了哪个`i``。
omp_set_num_threads(5);
#pragma omp parallel for reduction(+: sum)
for (int i = 0; i <= 10; ++i)
{int id = omp_get_thread_num();sum += i;printf("thread %d is operating loop %d, sum is %d\n", id, i, sum);
}
结果为:
thread 0 is operating loop 0, sum is 0
thread 0 is operating loop 1, sum is 1
thread 0 is operating loop 2, sum is 3
thread 1 is operating loop 3, sum is 3
thread 1 is operating loop 4, sum is 7
thread 4 is operating loop 9, sum is 9
thread 4 is operating loop 10, sum is 19
thread 3 is operating loop 7, sum is 7
thread 3 is operating loop 8, sum is 15
thread 2 is operating loop 5, sum is 5
thread 2 is operating loop 6, sum is 11
可以看到,线程0 1 2
操作了0 1 2
,并且最后sum = 3
。但是当线程1
操作i=3
后,sum
为3,也就是没有把之前的0 1 2
加进来。其他线程也是如此。也就是说,10次循环分给了5个线程,在每个线程中,都创建了一个私有的sum
,把该线程操作的数累加,之后5个线程再汇集其私有的sum
,得到最终的sum
,这样每个线程的私有sum
互不干涉,就防止数据冲突。
总结
sum += i, sum *= i, sum -= i
等可以使用Reduction
,这些都有一个共同点,就是把他们分给几个线程分别做线程私有变量上的操作,最后得到的线程结果再一起做一次操作,结果一致。但是类似于sum = i - sum
就不可以,因为这相当于sum = i / 2
,sum
的值完全由最后一个i
决定,不符合上述的共同点,就算分给多线程,最终线程结果合并时,也不知道到底该用哪个线程的结果。
更多推荐
OpenMP中的Reduction操作 #pragma omp xxx reduction()
发布评论