我有这个 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
连接回去。我不喜欢这种解决方法。有人知道更简洁的方法吗?
最佳答案
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
构造应该同步线程之间的内存 View ,例如使用共享存储中的值更新优化的寄存器变量。
OpenMP 3.0 得到所有现代 C 编译器的支持,除了 MSVC,它停留在 OpenMP 2.0。
关于c - Openmp:增加循环迭代次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11929783/