2010-02-07 199 views
6

我对OpenMP相当陌生,我试图启动一个单独的线程来处理2D数组中的每个项目。在OpenMP中为每个内部循环启动线程

所以基本上,这样的:

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项目或没有?我将如何测试?如果它是错误的,那么正确的方法是什么?谢谢!

注意:代码已被大大简化

+0

可能要与你所使用的语言来标记它,虽然您必须移除其中一个现有标签。 – 2010-02-07 03:45:48

+0

好点mmyers - 参考它看起来像他正在使用c/c + +(openMP是c/c + +和fortran只) – 2010-02-07 03:59:25

回答

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 

至于你的代码的其余部分,你可能想要把更多的细节在一个新的问题(这是很难由小样本告诉),但例如,当j仅在稍后声明时,不能放private(j)。它在我上面的示例中是自动隐私的。我猜diff是我们在样本中看不到的变量。此外,循环变量i是自动私人(从version 2.5 spec - 在3.0规范相同)

的循环迭代变量在 for循环的一个为或平行于 构建体是在 构建私人。

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

编辑:OK,我下载了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中的不合格示例)。

+0

谢谢,崩溃是我正在寻找的把戏! – achinda99 2010-02-08 13:28:51

0

你可以尝试使用嵌套的omp parallel 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); 

}