OMP中的减少和崩溃条款有一些令人困惑的地方

时间:2016-03-08 16:38:27

标签: c++ openmp collapse reduction

OMP中的缩减和崩溃条款都让我困惑, 突然出现了一些问题

  1. 为什么减少不能用减号?与列出的限制here
  2. 一样
  3. 是否有任何工作可以实现减去?
  4. 一元运算符如何工作,即x ++或x--?是 - 或++应用于每个部分结果?或者只在创建全球结果时一次?两种情况完全不同。
  5. 关于崩溃.. 我们可以在嵌套循环上应用折叠但在它们之间有一些代码行 例如

    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 << "*";
        }
    }
    

2 个答案:

答案 0 :(得分:2)

1&amp; 2.对于减号,你从中减去什么?如果您有两个主题,那么您是result_thread_1 - result_thread_2还是result_thread_2 - result_thread_1?如果你有2个以上的主题,那就更容易让人困惑:我只有一个否定词而其他所有词都是正面的吗?是否只有一个积极的术语而其他的是否定的?这是一个混合?哪个结果是哪个?因此,不,没有解决方法。

  1. 如果是x++x--,假设它们在减少循环内,它们应该发生在每个部分结果中。

  2. 是的,我相信。

答案 1 :(得分:0)

还原子句要求操作是关联的,并且

中的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];
相关问题