Parallel.Foreach与正常ForEach一样快/慢

时间:2011-02-04 15:58:56

标签: c# multithreading foreach parallel-processing

更新:我使用线程在内核数量中分割循环(在我的情况下为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操作并不会节省任何时间。

5 个答案:

答案 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秒的总运行时间表示操作足够慢,应该从并行化中受益。另一方面,您的代码似乎表明实际上并没有进行大量处理。您最有可能从磁盘或数据库加载数据。在这两种情况下,这都是并行化可以(几乎)没有反对的瓶颈。如果计算绑定,并发处理会使代码更快

但是你没有给出足够的信息来确定它。