当变量是数组元素时,我可以使用 OpenMP 缩减吗?

Can I use OpenMP reduction when the variable is an array element?

本文关键字:OpenMP 可以使 我可以 变量 数组元素      更新时间:2023-10-16

OpenMP 手册说

declare reduction 指令中的类型名不能是函数类型、数组类型、引用类型或限定为 constvolatilerestrict 的类型。

我该怎么做才能将结果生成到数组元素中? 我从:

int main()
{
    // create an input array
    static const int snum = 5000;
    int input[snum];
    for(int i=0; i<snum; ++i){
        input[i] = i+1;
    }
    // shared output variables for reduction
    int sum[2];
    sum[0] = 0;
    sum[1] = 0;
#pragma omp parallel for
#pragma omp declare reduction(+:sum[0])
#pragma omp declare reduction(+:sum[1])
    for(int i=0; i<snum; ++i) {
            int* p = input+i;
            if(i%2==0)
                sum[0] += *p;
            else
                sum[1] += *p;
        }
}

这给出了编译器错误:

27013152.cpp:16:9: error: ‘#pragma’ is not allowed here
 #pragma omp declare reduction(+:sum[0])
         ^~~
27013152.cpp:17:33: error: ‘sum’ does not name a type
 #pragma omp declare reduction(+:sum[1])
                                 ^~~
27013152.cpp:17:36: error: expected ‘:’ before ‘[’ token
 #pragma omp declare reduction(+:sum[1])
                                    ^
你弄

错了你得到的错误。这并不意味着你不能对交替元素进行减少。这意味着您无法将缩减为数组的元素。

也就是说,你不能做reduction(+:sum[0]).但是你可以将约简化为另一个标量变量,然后复制到数组的元素中:

void sum_int(const int input[], int num, int *sum)
{
    int sum_even = 0, sum_odd = 0;
    #pragma omp parallel for reduction(+:sum_even) reduction(+:sum_odd)
    for (int i = 0; i < num; i++) {
            if (i % 2 == 0)
                    sum_even += input[i];
            else
                    sum_odd += input[i];
    }
    sum[0] = sum_even;
    sum[1] = sum_odd;
}

从 OpenMP 4.5 开始,现在可以减少 C/C++ 中的数组。基本上,您必须指定数组部分(请参阅 OpenMP 4.5 规范的第 2.4 节,第 44 页)。您的 #pragma 规范如下所示:

#pragma omp parallel reduction(+:sum[:2])

但是要小心,您必须意识到每个线程都会分配自己的数组部分版本;如果你这样做具有许多线程的数组,您将使您的内存需求爆炸式增长。