2013-05-08 118 views
5

对不起,如果标题不清楚。我不知道该怎么说。OpenMP迭代并行区域循环

我不知道是否有什么办法可以做到以下几点:

#pragma omp parallel 
{ 
    for (int i = 0; i < iterations; i++) { 
     #pragma omp for 
     for (int j = 0; j < N; j++) 
      // Do something 
    } 
} 

忽略的东西,如在省略私人符for循环,是没有办法,我可以派生我的外表外螺纹任何方式循环,以便我可以并行内部循环?从我的理解(如果我错了,请纠正我),所有线程都会执行外部循环。我不确定内部循环的行为,但我认为for会将块分发给每个遇到它的线程。

我想要做的是不必叉/加入iterations次,但只是在外环做一次什么。这是否是正确的策略?

如果有什么是另一个外部循环不应该并行?这是...

#pragma omp parallel 
{ 

    for (int i = 0; i < iterations; i++) { 
     for(int k = 0; k < innerIterations; k++) { 
      #pragma omp for 
      for (int j = 0; j < N; j++) 
       // Do something 

      // Do something else 
     } 
    } 
} 

这将会是巨大的,如果有人点我到一个大的应用程序的示例使用OpenMP,这样我可以更好地了解策略使用OpenMP时可以采用并行。我似乎无法找到任何。

澄清:我正在寻找不改变循环排序或涉及阻塞,缓存和一般性能考虑的解决方案。我想了解如何在指定的循环结构中的OpenMP中完成此操作。 // Do something可能有也可能没有依赖关系,假设他们这样做,并且你不能移动。

+0

也许你可以举一个你想做什么的例子。我的意思是填写代码//做些什么 – 2013-05-08 15:36:54

+0

@raxman,这没有帮助。这意味着要求解决这个问题的一般解决方案,而不是针对特定应用的解决方案。 – Pochi 2013-05-08 16:05:18

+0

你可以继续并upvote /接受一些答案。似乎人们付出了一些努力,并得到了所有的最小upvotes。 – 2015-10-14 15:28:47

回答

1

我不知道我能回答你的问题。我现在只用了几个月的OpenMP,但是当我尝试回答这样的问题时,我会进行一些hello world printf测试,如下所示。我认为这可能有助于回答你的问题。也试试#pragma omp for nowait,看看会发生什么。

只要确保当你“//做一些事情,//做别的事情”,你不写同一个内存地址,并创建一个竞争状态。另外,如果您正在进行大量的阅读和写作,则需要考虑如何有效地使用缓存。

#include "stdio.h" 
#include <omp.h> 
void loop(const int iterations, const int N) { 
    #pragma omp parallel 
    { 
     int start_thread = omp_get_thread_num(); 
     printf("start thread %d\n", start_thread); 
     for (int i = 0; i < iterations; i++) { 
      printf("\titeration %d, thread num %d\n", i, omp_get_thread_num()); 
      #pragma omp for 
      for (int j = 0; j < N; j++) { 
       printf("\t\t inner loop %d, thread num %d\n", j, omp_get_thread_num()); 
      } 
     } 
    } 
} 

int main() { 
    loop(2,30); 
} 

就性能而言,您可能需要考虑像这样来融合循环。

#pragma omp for 
for(int n=0; n<iterations*N; n++) { 
    int i = n/N; 
    int j = n%N;  
    //do something as function of index i and j 
} 
0

这很难回答,因为它确实取决于代码中的依赖关系。但要解决这个问题的一般方法是颠倒循环的嵌套,就像这样:

#pragma omp parallel 
{ 
    #pragma omp for 
    for (int j = 0; j < N; j++) { 
     for (int i = 0; i < iterations; i++) { 
      // Do something 
     } 
    } 
} 

关当然,这可以或不可以是可能的,这取决于什么是循环中的代码。您处理

3

方式的两个for循环看起来我的权利,因为它达到你想要的行为的意义:外环不并行,而内循环。

为了更好地澄清发生的事情,我会尝试一些笔记添加到您的代码:

#pragma omp parallel 
{ 
    // Here you have a certain number of threads, let's say M 
    for (int i = 0; i < iterations; i++) { 
     // Each thread enters this region and executes all the iterations 
     // from i = 0 to i < iterations. Note that i is a private variable. 
     #pragma omp for 
     for (int j = 0; j < N; j++) { 
      // What happens here is shared among threads so, 
      // according to the scheduling you choose, each thread 
      // will execute a particular portion of your N iterations 
     } // IMPLICIT BARRIER    
    } 
} 

隐性障碍是同步的,其中线程等待对方的一个点。作为一个一般的经验法则因此优选并行外环而不是内部循环,因为这会创建同步的用于iterations*N迭代(而不是iterations点,你在上面创建)的单个点。

+0

外层循环应该指定某个算法的多次传递,所以它不能被并行化。对不起,如果我不清楚。 – Pochi 2013-05-08 23:18:30

+0

外循环没有并行化,因为没有工作共享指令 – Massimiliano 2013-05-09 06:50:04

+0

如果你使用我建议的代码运行“hello world printf”测试,它会显示所有这些。你可以看到,如果你添加nowait标签,屏障被删除。换句话说,没有nowait外部循环不是并行化的,而且它是。 – 2013-05-09 07:14:23