OMP中的缩减和崩溃条款都让我困惑, 突然出现了一些问题
关于崩溃.. 我们可以在嵌套循环上应用折叠但在它们之间有一些代码行 例如
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 << "*";
}
}
答案 0 :(得分:2)
1&amp; 2.对于减号,你从中减去什么?如果您有两个主题,那么您是result_thread_1 - result_thread_2
还是result_thread_2 - result_thread_1
?如果你有2个以上的主题,那就更容易让人困惑:我只有一个否定词而其他所有词都是正面的吗?是否只有一个积极的术语而其他的是否定的?这是一个混合?哪个结果是哪个?因此,不,没有解决方法。
如果是x++
或x--
,假设它们在减少循环内,它们应该发生在每个部分结果中。
是的,我相信。
答案 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];