更新:我使用线程在内核数量中分割循环(在我的情况下为8),完整循环在1秒内完成。所以问题不在于,线程操作不会更快。为什么Parralel Extension在这种情况下会失败?
嘿大家好我想用Parrallel.Foreach转换我的ForEach。 问题是,parralelisation对我来说几乎没有任何好处。原件:
foreach (Entities.Buchung buchung in buchungen) {
Int32 categoryID = manager.GetCategoryID(new Regelengine.Booking(buchung)); // Average 4ms
buchung.Category = categoryID.ToString();
}
并行:
System.Threading.Tasks.Parallel.ForEach(buchungen, buchung => {
Int32 categoryID = manager.GetCategoryID(new Regelengine.Booking(buchung));
buchung.Category = categoryID.ToString();
});
结果:
---------------------------
Stopwatched Results for 1550 entries in the List:
---------------------------
Parallel.Foreach 00:00:07.6599066
Average Foreach: 00:00:07.9791303
也许问题是,循环中的实际操作是如此之短?但是没有人能告诉我,在英特尔I7上并行执行1550操作并不会节省任何时间。
答案 0 :(得分:9)
只有一个资源可以通过使用Parallel.For:CPU周期来利用。如果你有N个核心,那么理论上你可以将你的代码加速N倍。然而,需要的是它实际上是CPU周期,这是代码中的约束。除非您执行计算代价昂贵的代码,否则通常情况并非如此。其他约束是硬盘的速度,网络连接,dbase服务器,在特定情况下是存储器总线的带宽。你只有其中一个,Parallel.For不能神奇地给你另一个磁盘。
测试Parallel.For是否会加速代码非常简单。只需运行代码而不进行并行化,并观察Taskmgr.exe或Perfmon中的CPU负载。如果一个核心没有以100%运行,那么您的代码不受计算限制。如果它以10%的速度运行,那么无论你拥有多少核心,你都只能希望它能在90%的时间内运行。通过将I / O等待时间与处理时间重叠,您将得到两个线程将完成的工作。
答案 1 :(得分:5)
您应该考虑的问题是:
最后一点是你最重要的考虑因素。例如,如果你正在最大化你的i / o频道,那么世界上所有的线程都不会蹲下。你的任务是CPU绑定还是I / O绑定?
答案 2 :(得分:1)
我认为你是对的,它确实看起来有点太短,不值得使用并行foreach。只有当我知道在foreach中会发生一些重要的事情时才会使用并行foreach,这需要花费时间,或者需要时间,比如数据库连接或者我要向Web服务发送大量数据。如果它只是处理服务器上的信息,那么就像从已经加载到内存中的集合中获取ID那么它真的不值得。
答案 3 :(得分:1)
如果您没有可用的核心,并行性将不会更快。所以,当我看到这样的代码时,我首先想到的是你有其他线程在运行。
也可能是工作量。同步逻辑不是免费的,每次迭代都没有做太多。考虑查看Parallel.ForEach的其他重载,您可以调整选项。
也尝试使用Parallel.For。您无法以并行方式从IEnumerable中读取,但可以使用索引从IList中读取。
答案 4 :(得分:0)
首先,1550并不多。例如,排序这么多元素的数组通常比顺序完成时更快。这一切都取决于操作。
其次,GetCategoryID
做了什么?它是否使用锁?就此而言,是Regelengine.Booking
构造函数吗?
7秒的总运行时间表示操作足够慢,应该从并行化中受益。另一方面,您的代码似乎表明实际上并没有进行大量处理。您最有可能从磁盘或数据库加载数据。在这两种情况下,这都是并行化可以(几乎)没有反对的瓶颈。如果计算绑定,并发处理会使代码更快 。
但是你没有给出足够的信息来确定它。