Parallel.For 与常规线程 [英] Parallel.For vs regular threads

查看:39
本文介绍了Parallel.For 与常规线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to understand why Parallel.For is able to outperform a number of threads in the following scenario: consider a batch of jobs that can be processed in parallel. While processing these jobs, new work may be added, which then needs to be processed as well. The Parallel.For solution would look as follows:

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;
}

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

This means that there are multiple times where the Parallel.For needs to synchronize. Consider a bread-first graph algorithm algorithm; the number of synchronizations would be quite large. Waste of time, no?

在老式线程方法中尝试相同的方法:

Trying the same in the old-fashioned threading approach:

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());

Parallel.For 代码当然更简洁,但我无法理解的是,它甚至更快!任务调度器就那么好?同步被取消了,没有忙等待,但线程方法始终较慢(对我而言).这是怎么回事?线程方法可以更快吗?

The Parallel.For code is of course much cleaner, but what I cannot comprehend, it's even faster as well! Is the task scheduler just that good? The synchronizations were eleminated, there's no busy waiting, yet the threaded approach is consistently slower (for me). What's going on? Can the threading approach be made faster?

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

thanks for all the answers, I wish I could pick multiple ones. I chose to go with the one that also shows an actual possible improvement.

推荐答案

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

The two code samples are not really the same.

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

The Parallel.ForEach() will use a limited amount of threads and re-use them. The 2nd sample is already starting way behind by having to create a number of threads. That takes time.

maxThreads 的值是多少?非常关键,在 Parallel.ForEach() 中它是动态的.

And what is the value of maxThreads ? Very critical, in Parallel.ForEach() it is dynamic.

任务调度器有那么好吗?

Is the task scheduler just that good?

还不错.TPL 使用工作窃取和其他自适应技术.你很难做得更好.

It is pretty good. And TPL uses work-stealing and other adaptive technologies. You'll have a hard time to do any better.

这篇关于Parallel.For 与常规线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆