繁体   English   中英

使用嵌套for循环进行OpenMP双精度缩减

[英]OpenMP double reduction with nested for loops

我开始学习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);
}

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

您的问题是您正在使用其中一个缩减变量d来计算另一个。 OpenMP减少将为每个线程创建一个局部变量(在这种情况下,每个线程将有一个本地dd1 )并在最后将它们加在一起。

在你的情况下,如果运行此没有顺序,你将以下值相加dd12, 4, 6, 8, 10, 12, 14, 16, 18, 20 ,但如果用2运行它螺纹(谁,让我们假设,均匀地分担负载)它们中的每将总结其本地的下列值d到他们的本地 d12, 4, 6, 8, 10 之后,代码将对每个线程的本地d1求和,以给出最终结果。

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

我将假设这只是一个非常好的最小例子,所以我不能建议你应该如何去解决你想做的事情。 但在这种情况下,你可以简单地从i计算d 如果这种情况不可能(在某些其他情况下),您可以使用critical区域,但这些并不总是一个好的解决方案(取决于问题)。

关于减少的进一步阅读可以(例如)在这里找到: http//pages.tacc.utexas.edu/~eijkhout/pcse/html/omp-reduction.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM