今天我尝试对foreach
语句进行一些优化,该语句适用于XDocument
。
优化前:
foreach (XElement elem in xDoc.Descendants("APSEvent").ToList())
{
//some operations
}
优化后:
Parallel.ForEach(xDoc.Descendants("APSEvent").ToList(), elem =>
{
//same operations
});
我看到Parallel.ForEach(...)
中的.NET只打开了一个帖子!因此,Parallel
的时间跨度大于标准foreach
。
为什么你认为.NET只开了1个帖子?因为锁定文件? 感谢
答案 0 :(得分:15)
根据设计,Parallel.ForEach可以使用比请求更少的线程来实现更好的性能。根据MSDN [link]:
默认情况下,Parallel.ForEach和Parallel.For方法可以使用可变数量的任务。这就是为什么,例如,ParallelOptions类具有MaxDegreeOfParallelism属性而不是" MinDegreeOfParallelism"属性。 这个想法是系统可以使用比请求的线程更少的线程来处理循环。
.NET线程池通过允许并行任务的工作线程数随时间变化而动态适应不断变化的工作负载。在运行时,系统会观察增加线程数是否增加或降低整体吞吐量并相应地调整工作线程数。
答案 1 :(得分:1)
从问题描述中,没有任何东西可以解释为什么TPL不会产生更多线程。
问题中没有任何证据表明问题。这可以很容易地修复:你可以在进入循环之前记录线程id,并在循环中执行第一件事。
如果它始终是相同的数字,那么TPL无法产生线程。然后,您应该尝试不同版本的代码,以及哪些更改会触发TPL序列化所有内容。一个原因可能是列表中有少量元素。 TPL对您的集合进行分区,如果您只有几个项目,则最终只能使用一个批次。这种行为可以通过这种方式进行配置。
可能是你无意中在循环中锁定,然后你会看到许多不同的数字,但没有加速。然后,简化代码直到问题消失。
答案 2 :(得分:0)
并不总是并行方式比“旧时尚方式”更快 http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/c860cf3f-f7a6-46b5-8a07-ca2f413258dd
答案 3 :(得分:0)
确实是,Document.Load(...)
locks the file并且由于线程之间的资源争用,TPL无法使用多线程的强大功能。尝试将XML加载到Stream
,然后使用Parallel.For(...)
。
答案 4 :(得分:0)
像这样使用它:
int ParallelThreads = 10;
Parallel.ForEach(xDoc.Descendants("APSEvent").ToList(), new ParallelOptions() { MaxDegreeOfParallelism = ParallelThreads }, (myXDOC, i, j) =>
{
//do whatever you want here
});
答案 5 :(得分:-1)
你碰巧有一个处理器吗?在这种情况下,TPL可以将线程数限制为1。如果集合非常小,可能会发生同样的事情。尝试更大的收藏。 有关如何确定并行度的更多详细信息,请参阅this answer。