the for loop looks like this:
cilk_for (int i=0; i<1000000; i++){
do something;
if(tag == 0){
break;
}
}
Then when compiling, i got this error:
error: break from parallel loop is not currently supported
the for loop looks like this:
cilk_for (int i=0; i<1000000; i++){
do something;
if(tag == 0){
break;
}
}
Then when compiling, i got this error:
error: break from parallel loop is not currently supported
你不能脱离 acilk_for
因为 acilk_for
不理解迭代的顺序。Cilk Plus(以及 TBB 和 OpenMP 和...)中的并行循环的迭代可以同时和/或无序执行。除非程序可以预测未来,否则如果迭代 100 在执行 50 之前或同时运行,那么迭代 100 怎么知道迭代 50 中存在中断?
如果您确实需要在开始迭代 i+1 之前在迭代 i 处退出循环,那么您的算法本质上是顺序的,您不能使用cilk_for
. 但是,如果跳出循环是关于性能(做更少的工作)而不是正确性,那么您就会遇到一类称为“推测并行性”的问题。在推测性并行中,您愿意为并行的好处做一些额外的工作,但您会尽量避免做太多的额外工作,以免失去并行的好处。
Cilk Plus 没有为推测并行性明确设计的任何构造,但您可以相当容易地编写一些代码。在这种情况下,最简单的事情是在tag
循环外创建一个原子变量并将您的条件更改为:
if (tag == 0)
continue;
您可以tag
使用顺序一致的内存顺序进行写入,但您可以选择使用宽松的内存顺序来读取它以减少内存争用。放松的记忆排序通常在专家的范围内被考虑,但在这种情况下,你的基础非常稳固。更复杂的系统将通过划分循环空间并使用树结构在迭代中传播“完成”标志来进一步减少内存争用。
请注意,如果您按照我上面的建议进行操作,那么所有尚未完成的迭代都会看到变化,即使是那些按顺序在设置为零的迭代之前发生的变化。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
才会受到影响。