Openmp:增加循环迭代次数

时间:2012-08-13 07:22:14

标签: c for-loop numbers iteration openmp

我有parallel for循环

struct p
{
    int n;
    double *l;
}

#pragma omp parallel for default(none) private(i) shared(p)
for (i = 0; i < p.n; ++i)
{
    DoSomething(p, i);
}

现在,内部DoSomething()p.n可能会增加,因为新元素已添加到p.l。我想以平行的方式处理这些元素。 OpenMP手册指出parallel for不能与列表一起使用,因此DoSomething()将这些p.l的新元素添加到另一个按顺序处理的列表中,然后将其与{p.l连接起来。 1}}。我不喜欢这种解决方法。谁知道更清洁的方法呢?

1 个答案:

答案 0 :(得分:3)

OpenMP 3.0中添加了一个支持动态执行的构造,它是task构造。任务被添加到队列中,然后尽可能同时执行。示例代码如下所示:

#pragma omp parallel private(i)
{
    #pragma omp single
    for (i = 0; i < p.n; ++i)
    {
       #pragma omp task
       DoSomething(p, i);
    }
}

这将产生一个新的并行区域。其中一个线程将执行for循环,并为i的每个值创建一个新的OpenMP任务。每个不同的DoSomething()调用都将转换为一个任务,稍后将在空闲线程内执行。但是存在一个问题:如果其中一个任务向p.l添加新值,则可能在创建者线程已退出for循环后发生。这可以使用任务同步结构和外部循环来修复:

#pragma omp single
{
   i = 0;
   while (i < p.n)
   {
      for (; i < p.n; ++i)
      {
         #pragma omp task
         DoSomething(p, i);
      }
      #pragma omp taskwait
      #pragma omp flush
   }
}

taskwait构造使线程等待直到执行所有排队的任务。如果将新元素添加到列表中,while的条件将再次变为真,并且将创建新一轮任务。 flush构造应该在线程之间同步内存视图,例如使用共享存储中的值更新优化的寄存器变量。

除了MSVC之外,所有现代C编译器都支持OpenMP 3.0,而MSVC则停留在OpenMP 2.0上。