如何在while循环中的嵌套for循环上使用OpenMP?

时间:2016-12-05 21:46:02

标签: c for-loop while-loop openmp

我最近已经介绍过OpenMP和并行编程,并且在使用它时遇到了一些麻烦。

我想在以下代码上实现OpenMP,以使其运行得更快。

int m = 101;
double e = 10;

double A[m][m], B[m][m];
for (int x=0; x<m; x++){
    for (int y=0; y<m; y++){
        A[x][y] = 0;
        B[x][y] = 1;
    }
}

while (e >= 0.0001){
    for (int x=0; x<m; x++){
        for (int y=0; y<m; y++){
            A[x][y] = 0.25*(B[x][y] - 0.2);
        }
    }
    e = 0;
    for (int x=0; x<m; x++){
        for (int y=0; y<m; y++){
            e = e + abs(A[x][y] - B[x][y]);
        }
    }    
}

我想同时运行循环,而不是一个接一个地运行循环,以加快运行时间。我相信以下代码应该可以工作,但我不确定我是否正确使用OpenMP。

int m = 101;
double e = 10;

double A[m][m], B[m][m];
#pragma omp parallel for private(x,y) shared(A,B) num_threads(2)
for (int x=0; x<m; x++){
    for (int y=0; y<m; y++){
        A[x][y] = 0;
        B[x][y] = 1;
    }
}

while (e >= 0.0001){
    #pragma omp parallel for private(x,y) shared(A,B) num_threads(2)
    for (int x=0; x<m; x++){
        for (int y=0; y<m; y++){
            A[x][y] = 0.25*(B[x][y] - 0.2);
        }
    }
    // I want to wait for the above loop to finish computing before starting the next
    #pragma omp barrier  
    e = 0;
    #pragma omp parallel for private(x,y) shared(A,B,e) num_threads(2)
    for (int x=0; x<m; x++){
        for (int y=0; y<m; y++){
            e = e + abs(A[x][y] - B[x][y]);
        }
    }    
}

我是否有效且正确地使用OpenMP?另外,我不确定我是否可以在我的while循环中使用OpenMP,因为它需要在确定是否需要再次运行之前计算内部循环。

1 个答案:

答案 0 :(得分:5)

假设代码有效,可以进行一些改进:

int m = 101;
double e = 10;

double A[m][m], B[m][m];

#pragma omp parallel num_threads(2) shared(A, B)
{

    #pragma omp for
    for (int x=0; x<m; x++){
        for (int y=0; y<m; y++){
            A[x][y] = 0;
            B[x][y] = 1;
       }
    }

   while (e >= 0.0001){
    #pragma omp for
    for (int x=0; x<m; x++){
        for (int y=0; y<m; y++){
            A[x][y] = 0.25*(B[x][y] - 0.2);
        }
    }

    #pragma omp single
    e = 0;

    #pragma omp for reduction (+:e)
    for (int x=0; x<m; x++){
        for (int y=0; y<m; y++){
            e = e + abs(A[x][y] - B[x][y]);
        }
    }    
  }
}

您可以通过仅为整个代码创建一个来改进,而不是每次创建并行区域。此外,由于您使用2个线程,因此没有太多的负载平衡问题,但如果您要增加线程数,则可以使用chunk = 1的静态调度获得更好的性能。

您不需要将循环x和y的变量设为私有,openmp将为您执行此操作。在嵌套的最后一个循环中,您有e = e + abs(A[x][y] - B[x][y]);,因此您可能希望线程具有添加“e”的结果,因此您必须使用“reduction(+:e)”来减少变量“e”线程。