并行“任务的内线已经并行for循环OpenMP中

问题描述:

背景:OpenMP的V4 +英特尔的编译器ICC]并行“任务的内线已经并行for循环OpenMP中

我想并行化已经是一个并行循环内的任务。我看见科目接近这一个,例如:

但是在尝试它时,除了编译时错误消息,我无法得到明确的答案。

代码:

#pragma omp parallel for private(a,bd) reduction(+:sum) 
    for (int i=0; i<128; i++) { 
     a = i%2; 
     for (int j=a; j<128; j=j+2) { 
      u_n = 0.25 * (u[ i*128 + (j-3) ]+ 
          u[ i*128 + (j+3) ]+ 
          u[ (i-1)*128 + j ]+ 
          u[ (i+1)*128 + j ]); 
      // #pragma omp single nowait 
      // { 
      // #pragma omp task shared(sum1) firstprivate(i,j) 
      // sum1 = (u[i*128+(j-3)]+u[i*128+(j-2)] + u[i*128+(j-1)])/3; 
      // #pragma omp task shared(sum2) firstprivate(i,j) 
      // sum2 = (u[i*128+(j+3)]+u[i*128+(j+2)]+u[i*128+(j+1)])/3; 
      // #pragma omp task shared(sum3) firstprivate(i,j) 
      // sum3 = (u[(i-1)*128+j]+u[(i-2)*128+j]+u[(i-3)*128+j])/3; 
      // #pragma omp task shared(sum4) firstprivate(i,j) 
      // sum4 = (u[(i+1)*128+j]+u[(i+2)*128+j]+u[(i+3)*128+j])/3; 
      // } 
      // #pragma omp taskwait 
      // { 
      // u_n = 0.25*(sum1+sum2+sum3+sum4); 
      // } 
      bd = u_n - u[i*128+ j]; 
      sum += diff * diff; 
      u[i*128+j]=u_n; 
     }  
    } 

在上面的代码中,我试图替换u_n = 0.25 *(...);符合15注释行,不仅尝试通过2个for循环来paralllelize迭代,而且还acheive一定程度在涉及数组u[]的4次计算(sum1sum4)中的每一次计算上都是并行性的。

编译错误是相当明确的:

error: the OpenMP "single" pragma must not be enclosed by the "parallel for" pragma

有没有解决的办法,所以我可以进一步优化该计算使用OpenMP?

标准禁止在循环工作共享结构中的单个工作共享构造,但您不需要它。

通常parallel - >single - >task设置的任务是要确保你有一个线程组设置为您的任务(parallel),但后来只产卵每个任务一次(single)。你不需要parallel for上下文中的后者,因为每次迭代只能执行一次。所以你可以直接在循环中产生任务。这似乎在gnu和Intel编译器上都有预期的行为,即已完成自己的循环迭代的线程确实帮助其他线程执行其任务。

但是,在你的情况下这是一个坏主意。与产卵任务的开销相比,像sum1之类的微小计算本身会更快。

删除除parallel for以外的所有编译指示,这是非常合理的并行化。 之前进一步优化计算,你应该措施!尤其是,您对所有可用线程是否总是在计算某些内容感兴趣,或者某些线程是否提前完成并等待其他线程(负载不均衡)。要衡量,您应该为您的平台寻找并行性能分析工具。如果是这样的话,你可以用调度策略来解决它,或者可能通过内部循环中的嵌套并行。

关于代码性能的完整讨论比较复杂,需要一个minimal, complete and verifiable example,详细的系统描述和实际测量的性能数字。

+0

谢谢佐兰。Yr解释肯定会击败编译时错误信息。根据你的指针,我将在我的集群上查看测量仪器。干杯, – Cbhihe