问题描述
int v[10] = {2,9,1,3,5,7,2,0};
int maximo = 0;
int b = 0;
int i;
#pragma omp parallel for shared(v) private(i) reduction(max:maximo)
for(i = 0; i< 10; i++){
if (v[i] > maximo)
maximo = v[i];
b = i + 100;
}
当 maximo 获得其最大值(因此,它在 for 循环之后的值)时,我如何获得 b 在迭代期间获得的值?
解决方法
TL;DR 您可以使用 User-Defined Reduction。
首先,而不是:
for(i = 0; i< 10; i++){
if (v[i] > maximo)
maximo = v[i];
b = i + 100;
}
你的意思是:
for(i = 0; i< 10; i++){
if (v[i] > maximo){
maximo = v[i];
b = i + 100;
}
}
OpenMP 具有考虑单个目标值的内置归约函数,但是在您的情况下,您希望将 max
和数组索引这两个值考虑在内进行归约。在 OpenMP 4.0 之后,可以创建自己的归约函数(即 User-Defined Reduction)。
首先,创建一个结构体来存储两个相关的值:
struct MyMax {
int max;
int index;
};
然后我们需要教OpenMP实现如何减少它:
#pragma omp declare reduction(maximo : struct MyMax : omp_out = omp_in.max > omp_out.max ? omp_in : omp_out)
我们相应地设置我们的平行区域:
#pragma omp parallel for reduction(maximo:myMaxStruct)
for(int i = 0; i< 10; i++){
if (v[i] > myMaxStruct.max){
myMaxStruct.max = v[i];
myMaxStruct.index = i + 100;
}
}
旁注您并不真的需要 private(i)
,因为使用 #pragma omp parallel for
,for 循环的索引变量无论如何将是隐式私有的.
全部放在一起:
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
struct MyMax {
int max;
int index;
};
int main(void)
{
#pragma omp declare reduction(maximo : struct MyMax : omp_out = omp_in.max > omp_out.max ? omp_in : omp_out)
struct MyMax myMaxStruct;
myMaxStruct.max = 0;
myMaxStruct.index = 0;
int v[10] = {2,9,1,3,5,7,2,0};
#pragma omp parallel for reduction(maximo:myMaxStruct)
for(int i = 0; i< 10; i++){
if (v[i] > myMaxStruct.max){
myMaxStruct.max = v[i];
myMaxStruct.index = i + 100;
}
}
printf("Max %d : Index %d\n",myMaxStruct.max,myMaxStruct.index);
}
输出:
Max 9 : Index 101
(索引是 101 因为你有 b = i + 100)
,我已经编写了代码但没有编译或测试它:
int v[10] = { 2,0 };
int maximo = 0;
int b = 0;
int i;
int nt = omp_get_num_threads();
int bv[nt] = { 0 };
#pragma omp parallel for shared(v) shared(bv) private(i) reduction(max:maximo)
for (i = 0; i < 10; i++) {
if (v[i] > maximo) {
maximo = v[i];
bv[omp_get_thread_num()] = i + 100;
}
}
for (i = 0; i < nt; ++i)
printf("bv[%d] = %d\n",i,bv[i]);
注意“返回当前团队中的线程数。在程序的连续部分中,omp_get_num_threads 返回 1”
好的,我已经重新编码[并构建/运行它]并且它确实产生一个非零bv
输出:
#include <stdio.h>
#include <omp.h>
int
main(void)
{
int v[10] = { 2,0 };
int i;
int nt;
int maximo = 0;
int index = 0;
int bv[32] = { 0 };
int max[32] = { 0 };
#pragma omp parallel shared(v,bv)
{
nt = omp_get_num_threads();
int thread_id = omp_get_thread_num();
#pragma omp for private(i)
for (i = 0; i < 10; i++) {
if (v[i] > max[thread_id]) {
max[thread_id] = v[i];
bv[thread_id] = i + 100;
}
}
}
// Reducing sequentially
for (i = 0; i < nt; ++i){
if(max[i] > maximo){
maximo = max[i];
index = bv[i];
}
}
printf("Max %d at index %d\n",maximo,index);
return 0;
}
这是程序输出:
Max 9 at index 101