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

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

问题描述:

我最近被引入到OpenMP和并行编程中,并且在正确使用它时遇到了一些麻烦。如何在while循环的嵌套for循环中使用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,因为它需要在计算内部循环之前确定它是否需要再次运行。

+0

你说你相信下面的代码可以工作......嗯......是吗?如果没有,你会得到什么错误? –

+2

另外,在omp parallel之后不需要屏障,因为在omp parallel blocks的末尾有一个隐含的屏障 –

+1

不需要声明x和y私有。 – dreamcrash

假设代码工作,这里有一些改进,可以使:

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个线程,所以没有太多的负载平衡问题,但是如果要增加线程数,则可以使用块= 1的静态调度获得更好的性能。

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

+2

为最后一个'for'嵌套的内部循环创建一个私有累加变量,并且每次迭代外部循环只更新(共享)'e'一次可能没有用处? –

+0

是的,我现在正在加上那个 – dreamcrash

+0

@dreamcrash在你的顶部#pragma omg应该是#pragma omp?此外,我计划将线程增加到32个,因为我有16个内核,每个内核有2个线程。我不明白你为什么使私人,减少(+:E)做什么? – PiccolMan