OpenMP并行化循环

时间:2013-10-29 17:10:53

标签: parallel-processing openmp sections

我想并行化这种循环。请注意,每个“calc_block”使用在上一次迭代中获得的数据。

for (i=0 ; i<MAX_ITER; i++){

    norma1 = calc_block1();
    norma2 = calc_block2();
    norma3 = calc_block3();
    norma4 = calc_block4();

    norma = norma1+norma2+norma3+norma4;
    ...some calc...
    if(norma<eps)break;
}

我试过这个,但加速很小~1.2

for (i=0 ; i<MAX_ITER; i++){
  #pragma omp parallel sections{
     #pragma omp section
       norma1 = calc_block1();
     #pragma omp section
       norma2 = calc_block2();
     #pragma omp section
       norma3 = calc_block3();
     #pragma omp section
       norma4 = calc_block4();
  }

  norma = norma1+norma2+norma3+norma4;
    ...some calc...
  if(norma<eps)break;
}

我认为这是因为在循环中使用部分的开销。但我不知道如何修复它... 提前谢谢!

1 个答案:

答案 0 :(得分:3)

您可以通过在并行区域内移动整个循环来减少开销。因此,用于实现团队的池中的线程只会被“唤醒”一次。这有点棘手,需要仔细考虑变量共享类:

#pragma omp parallel private(i,...) num_threads(4)
{
   for (i = 0; i < MAX_ITER; i++)
   {
      #pragma omp sections
      {
         #pragma omp section
         norma1 = calc_block1();
         #pragma omp section
         norma2 = calc_block2();
         #pragma omp section
         norma3 = calc_block3();
         #pragma omp section
         norma4 = calc_block4();
      }

      #pragma omp single
      {
         norma = norm1 + norm2 + norm3 + norm4;
         // ... some calc ..
      }

      if (norma < eps) break;
   }
}

sectionssingle结构都有两个隐含的障碍,因此线程会在进入下一个循环迭代之前进行同步。 single构造重现了程序的先前序列部分。 ...子句中的private部分应列出尽可能多的仅与... some calc ...相关的变量。我们的想法是使用线程局部变量运行串行部分,因为大多数OpenMP实现对共享变量的访问速度较慢。

请注意,由于完全不同的原因,通常加速时间可能不是线性的。例如calc_blockX()X1234)可能计算强度太低,因此要求非常高内存带宽。如果内存子系统无法同时为所有4个线程提供数据,则加速将小于4.这种情况的一个示例 - this question