我正在编写 more-less 的计算代码,其原理图如下:
#pragma omp parallel
{
#pragma omp for nowait
// Compute elements of some array A[i] in parallel
#pragma omp single
for (i = 0; i < N; ++i) {
// Do some operation with A[i].
// This time it is important that operations are sequential. e.g.:
result = compute_new_result(result, A[i]);
}
}
计算 A[i]
和 compute_new_result
都相当昂贵。所以我的想法是并行计算数组元素,如果有任何线程空闲,它就会开始执行顺序操作。很有可能已经计算了起始数组元素,其他线程将由仍在执行第一个循环的其他线程提供。
但是,为了使这个概念可行,我必须实现两件事:
让 OpenMP 以替代方式拆分循环,即对于两个线程:线程 1 计算A[0]
、A[2]
、A[4]
和线程 2:A[1]
、A[3]
、A[5]
等提供一些信号系统。我正在考虑一组标志,表明
A[i]
已经被计算出来。然后compute_new_result
应等待相应A[i]
的标志在继续之前被释放。
对于如何实现这两个目标的任何提示,我会很高兴。我需要能够跨 Linux、Windows 和 Mac 移植的解决方案。我正在用 C++11 编写整个代码。
编辑:
我已经找到第一个问题的答案了。看起来将 schedule(static,1)
子句添加到 #pragma omp for
指令就足够了。
不过,我还在思考第二个问题的优雅解法……
最佳答案
如果您不介意将 OpenMP for 工作共享结构替换为生成任务的循环,则可以使用 OpenMP 任务来实现应用程序的两个部分。
在第一个循环中,您将创建(而不是循环 block )承担迭代计算负载的任务。然后,第二个循环的每次迭代也成为一个 OpenMP 任务。重要的部分将是同步不同阶段之间的任务。
为此,您可以使用任务依赖性(在 OpenMP 4.0 中引入):
#pragma omp task depend(out:A[0])
{ A[0] = a(); }
#pragma omp task depend(in:A[0])
{ b(A[0]); }
将确保任务 b 不会在任务 a 完成之前运行。
干杯, -迈克尔
关于c++ - OpenMP 中的信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19133922/