【问题标题】:In a Parallel.For, is it possible to synchronize each threads?在 Parallel.For 中,是否可以同步每个线程?
【发布时间】:2014-07-10 01:55:15
【问题描述】:

在 Parallel.For 中,是否可以使用 'WaitAll' 同步每个线程?

  Parallel.For(0, maxIter, i =>
  {
            // Do stuffs

           // Synchronisation : wait for all threads => ???

           // Do another stuffs
  });

【问题讨论】:

  • 为什么不调用 Parallel.For 两次?
  • 不要!严重地。您在线程池线程上运行,从不在线程池线程上做任何等待或锁定(这是获得死锁的好方法,如果您正在编写一个库并且有人从例如 ASP.NET,会有很多乐趣)——很可能,有更好的方法来做到这一点。例如,为什么不调用两次Parallel.For - 第一次是第一部分,当它结束时,所有线程都完成了。然后是第二部分,另一个For 电话。
  • 我同意你的观点,但有可能吗?

标签: c# synchronization parallel.for


【解决方案1】:

Parallel.For,在后台将循环的迭代批处理成一个或多个Tasks,可以并行执行。除非您拥有分区的所有权,否则任务(和线程)的数量将(并且应该!)被抽象掉。控制只会在所有任务完成后退出Parallel.For 循环(即不需要WaitAll)。

这个想法当然是每个循环迭代都是独立的,不需要同步。

如果紧循环需要同步,说明你没有正确隔离Tasks,或者说明Amdahl's Law生效,无法通过并行化加速问题。

但是,对于聚合类型模式,您可能需要在完成每个任务后进行同步 - 使用 overloadlocalInit / localFinally 来执行此操作,例如:

// allTheStrings is a shared resource which isn't thread safe
var allTheStrings = new List<string>();
Parallel.For(         // for (
  0,                  // var i = 0;
  numberOfIterations, // i < numberOfIterations;
  () => new List<string> (), // localInit - Setup each task. List<string> --> localStrings
  (i, parallelLoopState, localStrings) =>
  {
     // The "tight" loop. If you need to synchronize here, there is no point 
     // using parallel at all
     localStrings.Add(i.ToString());
     return localStrings;
  },
  (localStrings) => // local Finally for each task.
  {
     // Synchronization needed here is needed - run once per task
     lock(allTheStrings)
     {
        allTheStrings.AddRange(localStrings);
     }
  });

在上面的示例中,您也可以将allTheStrings 声明为

var allTheStrings = new ConcurrentBag<string>();

在这种情况下,我们就不需要lock 中的localFinally

【讨论】:

  • localFinally 并没有真正帮助我,因为我想在同一个 Parallel.For 同步后开始一些计算
  • 为了避免同步,您需要确保每个Task 都获得自己的主体所需资源实例(紧密循环)。如果您在体内进行同步,那么您的瓶颈很可能在其他地方,并且并行化不会提高性能。我添加了 cmets?
【解决方案2】:

您不应该(出于其他用户说明的原因),但如果您愿意,可以使用Barrier。这可用于使所有线程在 X 数量的参与者遇到障碍之前在某个点等待(阻塞),从而导致障碍继续进行并且线程解除阻塞。正如其他人所说,这种方法的缺点是死锁

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    • 2014-03-23
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    相关资源
    最近更新 更多