【问题标题】:How to parallelize correctly a nested for loops如何正确并行化嵌套的 for 循环
【发布时间】:2011-12-01 08:11:10
【问题描述】:

我正在使用 OpenMP 来并行化嵌套的标量 for 循环:

double P[N][N];
double x=0.0,y=0.0;

for (int i=0; i<N; i++)
{
    for (int j=0; j<N; j++)
    {
        P[i][j]=someLongFunction(x,y);
        y+=1;
    }
    x+=1;
}

在这个循环中,重要的是矩阵 P 在标量和并行版本中必须相同:

我所有可能的尝试都没有成功...

【问题讨论】:

    标签: c++ c for-loop nested openmp


    【解决方案1】:

    这里的问题是您添加了迭代到迭代的依赖项:

    x+=1;
    y+=1;
    

    因此,就目前的代码而言,它是不可并行的。尝试这样做会导致错误的结果。 (你可能已经看到了)

    幸运的是,在您的情况下,您可以直接计算它们而无需引入此依赖项:

    for (int i=0; i<N; i++)
    {
        for (int j=0; j<N; j++)
        {
            P[i][j]=someLongFunction((double)i, (double)N*i + j);
        }
    }
    

    现在您可以尝试在此上面添加一个 OpenMP 编译指示,看看它是否有效:

    #pragma omp parallel for
    for (int i=0; i<N; i++)
    {
        for (int j=0; j<N; j++)
        {
            P[i][j]=someLongFunction((double)i, (double)N*i + j);
        }
    }
    

    【讨论】:

    • 好的,谢谢您的回答。我能再问你一个问题吗?如果我想在内循环之前每次 y=0 重置怎么办? openmp 实现将如何变化?
    • 然后将(double)N*i + j更改为(double)j。这里的关键是我将xy 的表达式导出为循环索引的函数。这可以让你打破依赖关系。
    • 非常感谢您的回答,他们阐明了如何解开循环以为 OpenMP 并行化做好准备。最后一个问题,为什么这段代码的串行和并行版本只给了我一小部分不同的元素? for (int i=0; i&lt;N; i++) { #pragma omp parallel for ordered schedule(dynamic) for ( int j=0; j&lt;N; j++) { x = i*step+xmin; y = j*step+ymin; P[i][j]=x+y; } } 不同的元素通常小于 1 超过 10^4,但为什么呢?
    • 应该没有什么不同,除非你在某个地方有错误。您可能想将其作为一个单独的问题发布。另外两件事:1)我对ordered 指令不太熟悉,但我认为您使用它的方式可能会弄巧成拙。 2)如果可能,并行化外循环而不是内循环。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多