首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在循环中突破循环?

如何在循环中突破循环?
EN

Stack Overflow用户
提问于 2015-09-02 19:48:24
回答 1查看 433关注 0票数 1

for循环如下所示:

代码语言:javascript
复制
cilk_for (int i=0; i<1000000; i++){
    do something;
    if(tag == 0){
        break;
    }
}

然后,在编译时,我得到了以下错误:

代码语言:javascript
复制
error: break from parallel loop is not currently supported
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-09-03 22:01:01

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

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

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

代码语言:javascript
复制
if (tag == 0)
    continue;

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

请注意,如果您按照我前面的建议进行,那么所有尚未完成的迭代都会看到更改,甚至是那些在将tag设置为零的迭代之前就会出现的变化。如果只想停止后续的迭代,那么不要更改tag,而是使用一个单独的原子stop_i变量,并将逻辑更改为:

代码语言:javascript
复制
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时尚未开始的迭代才会受到影响。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32361859

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档