我有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}}。我不喜欢这种解决方法。谁知道更清洁的方法呢?
答案 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
构造应该在线程之间同步内存视图,例如使用共享存储中的值更新优化的寄存器变量。