什么是取消parallel_for的最有效方法?

5

如何最有效地退出parallel_for循环? 要退出标准的for循环,我们可以执行以下操作:

for(int i = 0; i < 100; i+)
{
    bool bValue = DoSomething();

   //Break if bValue is true
   if(bValue)
      break;
}

我做了一些研究,发现关于PPL中的取消操作有一些信息可供参考Cancellation in the PPL。我正在考虑三种选择:
-任务组
// To enable cancelation, call parallel_for in a task group.
structured_task_group tg;

task_group_status status = tg.run_and_wait([&] 
{
   parallel_for(0, 100, [&](int i) 
   {

      bool bValue = DoSomething();
      if (bValue)
      {
         tg.cancel();
      }
   });
});

-抛出异常

try
{
   parallel_for(0, 100, [&](int i) 
   {
      bool bValue = DoSomething();
      if (bValue)
          throw i;
   });
}
catch (int n)
{
   wcout << L"Caught " << n << endl;
}

- 使用布尔值
// Create a Boolean flag to coordinate cancelation.
bool bCanceled = false;

parallel_for(0, 100, [&](int i) 
{       
   // Perform work if the task is not canceled.
   if (!bCanceled)
   {
       bool bValue = DoSomething();
       if (bValue)
          bCanceled = true;
   }
});

1
你是否考虑过优化你的代码结构,以避免取消并行循环?因为这不是你应该想要做的事情。 - Nicol Bolas
为什么这不好?我的意思是,在普通的循环中,如果条件成立,你不想做300000次循环,而是想在10次后停止。 - Jean-François Côté
@Nicol Bolas:在大多数情况下,这是我会做的。然而,有些循环太复杂了,无法重写。 - Goldorak84
@Jean-FrançoisCôté:通常,parallel_for是一个简单问题的简单工具:我有一堆沉重的任务要执行,并且我希望它们并行完成。parallel_for负责处理所有细节。一旦您开始想要做一些parallel_for明显不设计做的事情(比如中途停止),那么您显然需要比parallel_for更强大的机制。 - Nicol Bolas
2个回答

3
从Visual Studio 2012开始,有一个名为run_with_cancellation_token的函数,可以执行一个lambda和一个cancellation_token。在lambda内部,可以使用cancellation_token来取消操作。

链接:run_with_cancellation_token Function

您可以在MSDN上找到代码示例:How to: Use Cancellation to Break from a Parallel Loop

我无法确定这种方法的“效率”,因为我怀疑它的实现中涉及了C++异常。但是,这段代码可能比其他方法更简单,并且允许使用大多数PPL结构,而不仅限于structured_task_group

3

structured_task_group选项是唯一合理的选择。#3非常不安全,#2则是异常的可怕滥用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接