2012-01-19 20 views
20

今天我试着做一些优化到foreach声明,这对XDocument有效。为什么不是Parallel.ForEach运行多线程?

优化前:

foreach (XElement elem in xDoc.Descendants("APSEvent").ToList()) 
{ 
    //some operations 
} 

优化后:

Parallel.ForEach(xDoc.Descendants("APSEvent").ToList(), elem => 
{ 
    //same operations 
}); 

我看到.NET在Parallel.ForEach(...)打开只有一个线程!结果,Parallel的时间范围大于标准foreach

为什么你认为.NET只能打开1个线程?由于文件的锁定? 感谢

+10

你的机器有多少核心或逻辑处理器?列表中有多少个元素? –

+0

我无法看到标题与问题的任何关系。 –

+0

Christian.K,我的服务器采用至强处理器和8GB内存(戴尔PowerEdge R210),带有MS Server2008操作系统。我认为,这不取决于我在XML文档中有多少元素,我认为时间处罚是因为文件锁定。 – zzfima

回答

14

这是由设计Parallel.ForEach可以使用更少的线程比要求,以实现更好的性能。根据MSDN [link]

默认情况下,Parallel.ForEach和Parallel.For方法可以使用可变数量的任务。这就是为什么,例如,ParallelOptions类具有MaxDegreeOfParallelism属性,而不是“MinDegreeOfParallelism”属性。 这个想法是,系统可以使用比请求的线程更少的线程来处理循环。

.NET线程池通过允许并行任务的工作线程数量随时间变化而动态适应不断变化的工作负载。在运行时,系统会观察增加线程数是提高还是降低整体吞吐量,并相应地调整工作线程数。

0

是完全相同,Document.Load(...)locks the file并且由于资源的线程之间的竞争,第三方物流无法使用多线程的强大速度更快。尝试将XML加载到Stream,然后使用Parallel.For(...)

+6

这只会解释为什么只有一个线程_makes progress_,而不是为什么只有一个线程是_created_ - 正如OP声称的那样。 'Parallel.ForEach'不能(理智地)对它正在迭代的集合有任何了解(它只“看到”一个正在被传入的'List ',假设它有任何特殊的实现是不合理的)。另外,'ToList'基本上是提前获取所有元素,所以锁定(以及从文件中读取的事实)在这里应该没有什么区别。 –

-1

你碰巧有一个处理器?在这种情况下,TPL可能会将线程数限制为1。如果收藏品很小,可能会发生同样的事情。尝试更大的集合。 有关如何确定并行度的更多详细信息,请参阅this answer

+2

答案的笑话。可能适合作为评论。 – Mukus

1

使用这样的:

int ParallelThreads = 10; 
Parallel.ForEach(xDoc.Descendants("APSEvent").ToList(), new ParallelOptions() { MaxDegreeOfParallelism = ParallelThreads }, (myXDOC, i, j) => 
{ 
//do whatever you want here 
}); 
+0

请注意,MaxDegreeOfParallelism设置线程的最大数量,而不是最小值。因此,当您想限制或减少正在使用的线程/内核数量时很有用。 – coloboxp

1

从问题描述来看,没有什么能解释为什么TPL没有产生更多的线程。

问题中没有证据表明甚至是问题。这可以很容易地修复:在进入循环之前,您可以记录线程ID,并且可以在循环内执行第一件事

如果它始终是相同的数字,那么TPL无法产生线程。然后,您应该尝试使用不同版本的代码以及哪些更改会触发TPL序列化所有内容。一个原因可能是如果列表中有少量元素。TPL分割你的收藏,如果你只有几件物品,你最终可能只有一个批次。这种行为可以通过这种方式进行配置。

它可能是你无意中在循环中锁定,那么你会看到很多不同的数字,但没有加速。然后,简化代码,直到问题消失。

相关问题