2.3 模式变体
上面的信用分析实例为我们展示了一个并行循环的典型用法,但它还可以有很多变体用法。本节将介绍其中最重要的几个。尽管这些变体被使用的机会并不会太多,但是你应该知道它们是可行的。
2.3.1 提前退出循环
在串行迭代中,退出循环的操作并不会令人感到陌生,而这类操作在并行循环中并不常见,但有时我们依然会用得着它。下面是一个串行情况下的做法:
- int n = ...
- for (int i = 0; i < n; i++)
- {
- // ...
- if (/ stopping condition is true */)
- break;
- }
相比较而言,并行循环的情况会更复杂一些。因为其中往往会有不止一个步骤在同时运行,而且各步骤的执行顺序完全无法预知。但是,我们倒是可以通过取消任务组的方式来实现从一个并行循环中提前退出的效果。关于任务组,我们将会在第3章中详细介绍。
使用task_group::cancel方法可以帮助你提前退出一个并行循环。
下面是一段如何提前跳出并行循环的示范代码:
- vector<double> results = ...
- int workLoad = ...
- task_group tg;
- size_t fillTo = results.size() - 5 ;
- fill(results.begin(), results.end(), -1.0);
- task_group_status status = tg.run_and_wait([&]
- {
- parallel_for(0u, results.size(), [&](size_t i)
- {
- if (i > fillTo)
- tg.cancel();
- else
- results[i] = DoWork(i, workLoad);
- });
- });
如你所见,如果想要提前退出一个并行循环,我们需要先为该循环建立一个任务组对象,然后让该循环在任务组内执行。这时候,如果你想退出循环,只需要调用该任务组的cancel方法即可。
不要忘了并行循环是无序执行的,所以取消一个并行循环时并不能确保位置更靠后的迭代操作没有先被运行。
但是和串行循环不一样的是,我们应该始终牢记并行循环中的步骤是无序执行的。因此当你取消一个并行循环任务组的时候,并不能保证没有更靠后的迭代在cancel被执行之前已经运行完成。