vector<int> v;
#pragma omp parallel for ordered schedule(dynamic, anyChunkSizeGreaterThan1)
for (int i = 0; i < n; ++i){
...
...
...
#pragma omp ordered
v.push_back(i);
}
这会使v
填充n
大小的有序列表。
当到达omp ordered
块时,所有线程都需要等待最低迭代可能线程完成,但是如果没有任何线程被指定为特定迭代怎么办?或者OpenMP运行时库是否始终确保某个线程处理最低的迭代?
为什么建议将ordered
子句与dynamic schedule
一起使用? static schedule
会影响效果吗?
答案 0 :(得分:41)
ordered
子句的工作原理如下:不同的线程并发执行,直到它们遇到ordered
区域,然后按照与在串行循环中执行的顺序相同的顺序执行。这仍然允许一定程度的并发性,特别是如果ordered
区域之外的代码部分具有大量运行时间。
没有特别的理由使用dynamic
计划而不是static
计划使用小块大小。这一切都取决于代码的结构。由于ordered
引入了线程之间的依赖关系,如果与schedule(static)
一起使用默认块大小,则第二个线程必须等待第一个线程完成所有迭代,然后第三个线程将不得不等待第二个完成迭代(因此也是第一个),依此类推。可以通过3个线程和9个迭代(每个线程3个)轻松地将其可视化:
tid List of Timeline
iterations
0 0,1,2 ==o==o==o
1 3,4,5 ==.......o==o==o
2 6,7,8 ==..............o==o==o
=
表明线程并行执行代码。 o
是线程执行ordered
区域的时间。 .
是线程空闲,等待轮到执行ordered
区域。使用schedule(static,1)
会发生以下情况:
tid List of Timeline
iterations
0 0,3,6 ==o==o==o
1 1,4,7 ==.o==o==o
2 2,5,8 ==..o==o==o
我认为两种情况的区别都是显而易见的。对于schedule(dynamic)
,上面的图片将或多或少随机,因为分配给每个线程的迭代列表是不确定的。它还会增加额外的开销。只有当每次迭代的计算量不同时才会有用,并且与使用动态调度的额外开销相比,它需要花费更多的时间来进行计算。
不要担心编号最小的迭代。它通常被处理到团队中的第一个线程,以准备好执行代码。