我试图理解为什么在以下情况下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;
}
这意味着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());
Parallel.For
的代码当然更加简洁,而且我无法理解的是,它甚至更快!任务调度程序真的那么好吗?同步被消除了,没有繁忙等待,然而线程方法始终较慢(对我来说)。发生了什么?线程方法能否变得更快?编辑:感谢所有答案,我希望我可以选择多个答案。我选择采用一个也展示了实际可能改进的答案。