【发布时间】:2019-04-15 21:01:21
【问题描述】:
你怎么能从tbb::paralel_for 中取出break,类似于连续的for?
【问题讨论】:
-
这个问题和休息有什么关系??
标签: c++ parallel-processing tbb
你怎么能从tbb::paralel_for 中取出break,类似于连续的for?
【问题讨论】:
标签: c++ parallel-processing tbb
也许你可以抛出一个专门的异常。 TBB 运行时应在运行特定任务的线程中捕获异常,导致任务组被取消,并从取消组的根重新抛出异常。
【讨论】:
您可以抛出异常,也可以使用取消 API。在后一种情况下,break; 的“替换”是tbb::task::self().cancel_group_execution(); return;。但是,两者都没有在串行循环中为您提供break 的保证。更准确地说,取消/异常之后的任何循环迭代(在串行意义上)仍可能由其他线程执行;此外,取消/异常之前的一些迭代(在串行意义上)可能永远不会运行。
如果tbb::parallel_for 的主体内部有一个循环(例如,在blocked_range 上迭代的循环),您可以考虑跳出该循环以防tbb::task::self().is_cancelled() 是true;这可能会减少浪费的工作并更快地完成循环。
有关其他详细信息,您可以查看 TBB 文档,例如https://www.threadingbuildingblocks.org/docs/help/tbb_userguide/Exceptions_and_Cancellation.html 和 https://www.threadingbuildingblocks.org/docs/help/reference/task_scheduler/cancellation.html。
如果在序列代码中使用break 来查找满足条件的“最左侧”点(例如最小循环索引或容器中的第一项),则不应使用取消或异常,因为结果可能不正确。相反,使用一种减少形式(例如tbb::parallel_reduce)来选择所有合适点中的“最左边”一个。一种可能的优化是使用原子变量(在循环之外指定)来保持最小的合适索引,并跳过所有具有更大索引的迭代。要更新原子变量,您需要使用compare_and_swap 操作来检查是否有另一个线程使用比当前线程找到的值更小的值对其进行了更新。
【讨论】: