我怎么知道在OpenMP"中做了多少工作?对于指令"?

时间:2012-09-15 09:22:35

标签: c++ openmp

我想知道使用OpenMP的for循环的进展。 我知道减少指令不起作用,但我写的是这样的:

#pragma omp for reduction (+:sum)
    for (int i=0; i < size; i++){
    // do something that takes about 10seconds 
    sum++;
#pragma omp critical
    cout << sum << " / " << size << endl; 
    }

这将返回如下内容:

1 / 100
1 / 100
2 / 100
1 / 100
...

但我想要这个:

1 / 100
2 / 100
3 / 100

。 ..

sum指令期间,有没有办法获得正确的reduction值? 或者我应该使用其他方法?

3 个答案:

答案 0 :(得分:0)

您应该使用其他方法。减少会创建一个线程私有变量(在您的情况下为sum),当所有线程都加入时,它仅在结尾处减少。减少高度依赖于实现。它可以等待所有线程完成,它可以在线程完成时减少,它可以创建缩减树等等。

相反,要跟踪进度,您可以使用另一个变量numDone,每个线程都会原子地增加。

修改

Wikipedia解释得非常好:

  

reduction(operator | intrinsic:list):变量具有本地副本   在每个线程中,但将汇总本地副本的值   (缩小)为全局共享变量。

答案 1 :(得分:0)

为了避免通信的需要(来自更新共享计数器),您可以打印出线程号以及它到目前为止处理的项目数,即

#pragma omp parallel
{
   int count = 0;
#pragma omp for schedule(dynamic)           // or whatever schedule you want
  for(int i=0; i<size; ++i) {
    // ...
    printf("@ %d: done %d loops\n",
           omp_get_thread_num(),++count);   // should not need a critical section
  }
}

在您的特定情况下,由于工作大约需要10秒,因此任何通信都不重要,但使用动态计划可能是值得的,特别是如果工作可能在不同的i之间变化。

答案 2 :(得分:0)

reduction子句具有非常明确的含义,详见latest OpenMP standard的2.9.3.6节。我怀疑你是否能够将它用于上述目的。

无论如何,只需对源进行一些修改即可实现该行为:

sum = 0
#pragma omp for shared(sum) schedule(guided)
for (int i=0; i < size; i++){
    // do something that takes about 10seconds 
#pragma omp critical(PRINT)
    {
      sum++;
      cout << sum << " / " << size << endl;     
    }
}

通过这种方式,您可以确保一次只有一个线程尝试增加“总和”并在屏幕上打印。鉴于每次迭代花费的时间很长,这种同步不应该引起性能问题。