Parallel.For vs常规线程

Fra*_*erg 9 c# performance multithreading

我试图理解为什么Parallel.For在以下场景中能够胜过许多线程:考虑一批可以并行处理的作业.在处理这些作业时,可能会添加新工作,然后也需要对其进行处理.该Parallel.For解决方案将如下所示:

var jobs = new List<Job> { firstJob };
int startIdx = 0, endIdx = jobs.Count;
while (startIdx < endIdx) {
  Parallel.For(startIdx, endIdx, i => WorkJob(jobs[i]));
  startIdx = endIdx; endIdx = jobs.Count;
}
Run Code Online (Sandbox Code Playgroud)

这意味着Parallel.For需要同步多次.考虑面包优先图算法算法; 同步的数量会非常大.浪费时间,不是吗?

尝试使用老式的线程方法:

var queue = new ConcurrentQueue<Job> { firstJob };
var threads = new List<Thread>();
var waitHandle = new AutoResetEvent(false);
int numBusy = 0;
for (int i = 0; i < maxThreads; i++) 
  threads.Add(new Thread(new ThreadStart(delegate {
    while (!queue.IsEmpty || numBusy > 0) {
      if (queue.IsEmpty)
        // numbusy > 0 implies more data may arrive
        waitHandle.WaitOne();

      Job job;
      if (queue.TryDequeue(out job)) {
        Interlocked.Increment(ref numBusy);
        WorkJob(job); // WorkJob does a waitHandle.Set() when more work was found
        Interlocked.Decrement(ref numBusy);
      }
    }
    // others are possibly waiting for us to enable more work which won't happen
    waitHandle.Set(); 
})));
threads.ForEach(t => t.Start());
threads.ForEach(t => t.Join());
Run Code Online (Sandbox Code Playgroud)

Parallel.For代码是当然更清洁的,但我无法理解,它甚至也更快!任务调度程序是那么好吗?同步被激活,没有繁忙的等待,但线程方法一直较慢(对我而言).这是怎么回事?线程化方法可以更快吗?

编辑:感谢所有答案,我希望我可以选择多个答案.我选择了那个也显示出实际可能改进的那个.

Hen*_*man 13

这两个代码示例并不完全相同.

Parallel.ForEach()将使用的线程数量有限,并重新使用它们.必须创建多个线程,第二个样本已经开始落后了.这需要时间.

什么是价值maxThreads?非常关键,Parallel.ForEach()因为它是动态的.

任务调度程序是那么好吗?

非常好.TPL使用工作窃取和其他自适应技术.你将很难做得更好.