omp ordered子句如何工作?

Mih*_*csu 18 c++ parallel-processing openmp

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);
    }
Run Code Online (Sandbox Code Playgroud)

这将填充v一个n大小有序的列表.

当到达omp ordered块时,所有线程都需要等待最低迭代可能线程完成,但是如果没有任何线程被指定为特定迭代怎么办?或者OpenMP运行时库是否始终确保某个线程处理最低的迭代?

另外为什么建议该ordered条款与dynamic schedule?一起使用?会static schedule影响表现吗?

Hri*_*iev 45

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
Run Code Online (Sandbox Code Playgroud)

=表明线程并行执行代码.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
Run Code Online (Sandbox Code Playgroud)

我相信两种情况的区别都是显而易见的.由于schedule(dynamic)分配给每个线程的迭代列表是非确定性的,因此上面的图片将变得或多或少随机.它还会增加额外的开销.仅当每次迭代的计算量不同并且与使用动态调度所增加的开销相比花费更多时间进行计算时,它才有用.

不要担心编号最小的迭代.它通常被处理到团队中的第一个线程以准备执行代码.

  • @Cookie503,请注意,如果块大小太小,那么由于丢失数据局部性,缓存可能变得不那么有用.这可能会比隐含的序列化更糟糕.尝试不同的块大小,直到达到最佳加速.明智地使用`ordered`循环,如果可能的话,避免它们,即使它会导致内存占用增加 - 例如(给定您的特定示例),应使用简单的预分配数组(或其他线程安全的随机访问容器)而不是向量: `arr [i] = i;` (2认同)