如何在cilk中摆脱for循环?

时间:2015-09-02 19:48:25

标签: cilk

for循环看起来像这样:

cilk_for (int i=0; i<1000000; i++){
    do something;
    if(tag == 0){
        break;
    }
}

然后在编译时,我收到了这个错误:

error: break from parallel loop is not currently supported

1 个答案:

答案 0 :(得分:1)

您无法突破cilk_for,因为cilk_for无法理解迭代次序。 Cilk Plus(以及TBB和OpenMP和......)中并行循环的迭代可以同时执行和/或乱序执行。除非程序可以预测未来,否则如果迭代100在执行50之前或同时运行,迭代100如何知道迭代50中有中断?

如果你真的需要在开始迭代i + 1之前在迭代i退出循环,那么你的算法本质上是顺序的,你不能使用cilk_for。然而,如果从循环中退出是关于性能(做更少的工作)而不是正确性,那么你就会知道一类问题&#34;推测并行性&#34;。在推测并行性中,你愿意做一些额外的工作来获得并行的好处,但是你试图避免做太多额外的工作,以至于并行性的好处都会丢失。

Cilk Plus没有明确设计用于推测并行性的任何构造,但您可以相当容易地编写代码。在这种情况下最简单的事情是将tag转换为循环外的原子变量并将条件更改为:

if (tag == 0)
    continue;

您可以使用顺序一致的内存排序写入tag,但您可以选择使用宽松的内存排序来读取它以减少内存争用。轻松的记忆排序通常被认为是专家领域,但在这种情况下,你还有相当坚实的基础。更复杂的系统将通过划分循环空间并使用树结构传播&#34;完成&#34;来进一步减少内存争用。横跨迭代标记。

请注意,如果您执行我上面建议的操作,那么所有尚未完成的迭代将会看到更改,即使是那些按顺序之前的更改< / em>将tag设置为零的迭代。如果您只想停止后续迭代,则不要更改tag,而是使用单独的原子stop_i变量,并将逻辑更改为:

atomic_int stop_i(1000000);
cilk_for (int i=0; i<1000000; i++) {
    if (atomic_load(&stop_i, memory_order_relaxed) >= i)
        continue;
    do something;
    if(tag == 0){
        atomic_store(&stop_i, i, memory_order_seq_cst);
        continue;
    }
}

但请注意,您仍会在尝试停止点之外进行多次迭代的推测性执行。只有在设置stop_i时尚未开始的迭代才会受到影响。