带嵌套for循环的OpenMP双重缩减

时间:2018-06-28 10:00:38

标签: c openmp

我开始学习OpenMP,但是我无法处理此代码。每次运行都会给出不同的结果。

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

int main() {
    int numsmp = 10;
    double d = 0.0;
    double d1 = 0.0;
    float trace[10];
    #pragma omp parallel for num_threads(2) reduction(+ : d, d1)
    for (int i = 0; i < numsmp; i++) {
        for (long int k = 0; k < 2; k++) {
            printf("\n");
            d++;
            printf("i  = %d k = %d d = %lf", i, k, d);
        }
        d1 += d;
        trace[i] = d;
    }
    for (int i = 0; i < 10; i++) {
        printf("\n%lf", trace[i]);
    }
    printf("d1=%f\n", d1);
}

1 个答案:

答案 0 :(得分:3)

我会注意到,在我的机器上似乎给出了一致的结果(但显然是错误的)(60而不是110)-但这在不同的机器上可能会有所不同,它还取决于当前的系统负载。

您的问题是,您正在使用归约变量d中的一个来计算另一个。 OpenMP简化将为每个线程创建一个局部变量(在这种情况下,每个线程将具有一个局部dd1),最后将它们加在一起。

在您的情况下,如果不按顺序运行此命令,则将dd1的以下值相加:2, 4, 6, 8, 10, 12, 14, 16, 18, 20,但是如果使用2个线程( ,让我们假设,平均分配负载),它们每个都会将其 local d的以下值加到其 local d1中: 1}}。之后,代码将对每个线程的本地2, 4, 6, 8, 10求和,以得出最终结果。

要检查我们的推理,我们可以自己尝试求和,单线程求和应该给我们110,而代码也是如此。然后使用2个线程(假设负载均匀分布)应该给我们2x30 = 60,这也是。

我将假设这只是一个非常好的最小示例,因此我无法建议您应该如何解决您想要做的任何事情。但是在这种情况下,您可以简单地根据d1计算d。如果不可能(在其他情况下),可以使用i区域,但是这些区域并不总是一个好的解决方案(取决于问题)。

例如,可以在以下位置进一步了解减少量:http://pages.tacc.utexas.edu/~eijkhout/pcse/html/omp-reduction.html