c++ OMP中的归约和折叠条款有一些容易混淆的地方

nwlqm0z1  于 2022-12-01  发布在  其他
关注(0)|答案(2)|浏览(133)

OMP中的归约条款和崩溃条款都让我感到困惑,一些观点突然出现在我的脑海中
1.为什么reduction不能与minus一起使用?这里列出的限制
1.是否有任何解决方案来实现负?
1.一元运算符是如何工作的,即x还是x--?--或是应用于每个部分结果?还是在创建全局结果时只应用一次?这两种情况完全不同。
关于collapse..我们是否可以在嵌套循环上应用collapse,但中间要有一些代码行,例如

for (int i = 0; i < 4; i++)
{
    cout << "Hi"; //This is an extra line. which breaks the 2 loops.
    for (int j = 0; j < 100; j++)
    {
        cout << "*";
    }
}
yyyllmsg

yyyllmsg1#

1和2。对于minus,您要减去什么?如果您有两个线程,您要执行result_thread_1 - result_thread_2还是result_thread_2 - result_thread_1?如果您有两个以上的线程,则会更加混乱:我是否只有一个负项,而所有其他项都是正项?是否只有一个正项,而其他项都是负项?是否混合?哪些结果是哪些结果?因此,不,没有解决方法。
1.在x++x--事件中,假设它们在归约循环中,它们应该发生在每个部分结果上。
1.是的,我想是的。

o8x7eapl

o8x7eapl2#

reduction子句要求运算是关联的,并且中的x = a[i] - x运算

for(int i=0; i<n; i++) x = a[i] - x;

不是关联的。请尝试几次迭代。

n = 0:  x = x0;
n = 1:  x = a[0] - x0;
n = 2:  x = a[1] - (a[0] - x0)
n = 3:  x = a[2] - (a[1] - (a[0] - x0))
          = a[2] - a[1] + a[0] - x0;

但是x = x - a[i]确实有效,例如。

n = 3:  x = x0 - (a[2] + a[1] + a[0]);

然而,有一个变通办法。符号每隔一个术语交替。这里有一个工作解决方案。

#include <stdio.h>
#include <omp.h>

int main(void) {
    int n = 18;

    float x0 = 3;

    float a[n];
    for(int i=0; i<n; i++) a[i] = i;
    float x = x0;
    for(int i=0; i<n; i++) x = a[i] - x; printf("%f\n", x);

    int sign = n%2== 0 ? -1 : 1 ;
    float s = -sign*x0;
    #pragma omp parallel
    {
        float sp = 0;
        int signp = 1;
        #pragma omp for schedule(static)
        for(int i=0; i<n; i++) sp += signp*a[i], signp *= -1;

        #pragma omp for schedule(static) ordered
        for(int i=0; i<omp_get_num_threads(); i++)
            #pragma omp ordered
            s += sign*sp, sign *= signp;
    }
    printf("%f\n", s);
}

这里有一个更简单的版本,它使用reduction子句。需要注意的是,奇数项都是一个符号,偶数项是另一个符号。因此,如果我们一次约简两项,符号不会改变,运算是结合的。

x = x0;
for(int i=0; i<n; i++) x = a[i] - x

可以像这样并行减少。

x = n%2 ? a[0] - x0 : x0;
#pragma omp parallel for reduction (+:x)
for(int i=0; i<n/2; i++) x += a[2*i+1+n%2] - a[2*i+n%2];

相关问题