在OpenMP中为每个内部循环启动一个线程

时间:2010-02-07 03:37:44

标签: c arrays loops parallel-processing openmp

我是OpenMP的新手,我正在尝试启动一个单独的线程来处理2D数组中的每个项目。

基本上,这个:

for (i = 0; i < dimension; i++) {
    for (int j = 0; j < dimension; j++) {
        a[i][j] = b[i][j] + c[i][j];

我正在做的是:

#pragma omp parallel for shared(a,b,c) private(i,j) reduction(+:diff) schedule(dynamic)
    for (i = 0; i < dimension; i++) {
        for (int j = 0; j < dimension; j++) {
            a[i][j] = b[i][j] + c[i][j];

这实际上是为每个2D项启动一个线程还是没有?我该如何测试?如果是错的,那么正确的方法是什么?谢谢!

注意:代码已经大大简化了

2 个答案:

答案 0 :(得分:7)

在代码示例中只有外部循环是并行的。您可以通过在内循环中打印omp_get_thread_num()进行测试,您会看到,对于给定的i,线程数是相同的(当然,此测试是示范性的而不是明确的,因为不同的运行将给出不同的结果)。例如,使用:

#include <stdio.h>
#include <omp.h>
#define dimension 4

int main() {
    #pragma omp parallel for
    for (int i = 0; i < dimension; i++)
        for (int j = 0; j < dimension; j++)
            printf("i=%d, j=%d, thread = %d\n", i, j, omp_get_thread_num());
    }

我明白了:

i=1, j=0, thread = 1
i=3, j=0, thread = 3
i=2, j=0, thread = 2
i=0, j=0, thread = 0
i=1, j=1, thread = 1
i=3, j=1, thread = 3
i=2, j=1, thread = 2
i=0, j=1, thread = 0
i=1, j=2, thread = 1
i=3, j=2, thread = 3
i=2, j=2, thread = 2
i=0, j=2, thread = 0
i=1, j=3, thread = 1
i=3, j=3, thread = 3
i=2, j=3, thread = 2
i=0, j=3, thread = 0

至于你的其余代码,你可能想在一个新问题中加入更多细节(很难从小样本中得知),但是例如,你不能在{private(j)时放置j 1}}仅在稍后声明。在我上面的例子中,它是自动私有的。我猜diff是我们在样本中看不到的变量。此外,循环变量i自动为私有(来自version 2.5 spec - 与3.0规范相同)

  

循环迭代变量   for for循环for for或parallel for   构造是私有的   构造

编辑:以上所有内容对于您和我展示的代码都是正确的,但您可能对以下内容感兴趣。对于OpenMP 3.0版(例如gcc version 4.4,但不是版本4.3),有一个collapse子句,您可以在其中编写代码,但是 #pragma omp parallel for collapse (2)并行化两个for循环(请参阅the spec)。

编辑:好的,我下载了gcc 4.5.0并运行了上面的代码,但使用collapse (2)获取以下输出,显示内部循环现在已并行化了:

i=0, j=0, thread = 0
i=0, j=2, thread = 1
i=1, j=0, thread = 2
i=2, j=0, thread = 4
i=0, j=1, thread = 0
i=1, j=2, thread = 3
i=3, j=0, thread = 6
i=2, j=2, thread = 5
i=3, j=2, thread = 7
i=0, j=3, thread = 1
i=1, j=1, thread = 2
i=2, j=1, thread = 4
i=1, j=3, thread = 3
i=3, j=1, thread = 6
i=2, j=3, thread = 5
i=3, j=3, thread = 7

评论here(搜索“变通方法”)也适用于版本2.5中的变通方法,如果您想要并行化两个循环,但上面引用的2.5版规范是非常明确的(请参阅不符合规范) A.35)部分中的示例。

答案 1 :(得分:0)

您可以尝试使用嵌套的omp并行fors(在omp_set_nested(1)调用之后),但在所有openmp实现上都不支持它们。

所以我想制作一些2D网格并从单个网格开始网格上的所有线程(例如固定的4x4线程网格):

#pragma omp parallel for
for(k = 0; k < 16; k++)
{
    int i,j,i_min,j_min,i_max,j_max;
    i_min=(k/4) * (dimension/4);
    i_max=(k/4 + 1) * (dimension/4);
    j_min=(k%4) * (dimension/4);
    j_max=(k%4 + 1) * (dimension/4);

    for(i=i_min;i<i_max;i++)
      for(j=j_min;j<j_max;j++)
       f(i,j);

}