如何在代码中跳出for循环

  • 本文关键字:for 循环 代码 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

您不能脱离cilk_for,因为cilk_for不理解迭代的顺序。Cilk Plus(以及TBB和OpenMP等)中并行循环的迭代可以同时执行和/或乱序执行。除非程序可以预测未来,否则如果迭代100在执行50之前或同时运行,那么迭代100如何知道迭代50中有中断呢?

如果你真的需要在开始迭代i+1之前在迭代i退出循环,那么你的算法本质上是顺序的,你不能使用cilk_for。然而,如果跳出循环是关于性能(做更少的工作)而不是正确性,那么你就有了一类被称为"推测并行"的问题。在推测并行中,您愿意做一些额外的工作以获得并行的好处,但您试图避免做太多额外的工作,以免失去并行的好处。

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

if (tag == 0)
    continue;

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

请注意,如果您按照我上面的建议进行操作,那么所有尚未完成的迭代都将看到更改,即使是那些在将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时尚未开始的迭代才会受到影响。

相关内容

  • 没有找到相关文章

最新更新