Parallel.ForEach比ForEach慢

Mik*_*iaz 30 .net c# parallel.foreach

这是代码:

using (var context = new AventureWorksDataContext())
{
    IEnumerable<Customer> _customerQuery = from c in context.Customers
                                           where c.FirstName.StartsWith("A")
                                           select c;

    var watch = new Stopwatch();
    watch.Start();

    var result = Parallel.ForEach(_customerQuery, c => Console.WriteLine(c.FirstName));

    watch.Stop();
    Debug.WriteLine(watch.ElapsedMilliseconds);

    watch = new Stopwatch();
    watch.Start();

    foreach (var customer in _customerQuery)
    {
        Console.WriteLine(customer.FirstName);
    }

    watch.Stop();
    Debug.WriteLine(watch.ElapsedMilliseconds);
}
Run Code Online (Sandbox Code Playgroud)

问题是,Parallel.ForEach与常规相比需要大约400ms ,大约foreach需要40ms.我究竟做错了什么,为什么这不能像我期望的那样工作?

Eri*_*ert 157

假设您有一项任务要执行.假设你是一名数学老师,你有二十篇论文要评分.你需要花两分钟来评分一张纸,所以它需要大约四十分钟.

现在让我们假设您决定聘请一些助理来帮助您评分论文.找一个四个助手需要一个小时.你们各自拿了四篇论文,你们都在八分钟内完成了.你已经交易了40分钟的工作,总共68分钟的工作,包括额外的时间来找到助手,所以这不是节省.找到助手的开销大于自己完成工作的成本.

现在假设你有两万篇论文要评分,所以你需要大约40000分钟.现在,如果你花一个小时寻找助手,那就是胜利.你们各自拿走了4000篇论文,共计8060分钟而不是40000分钟,节省了近5倍.找到助手的开销基本上是无关紧要的.

并行化不是免费的.与每个线程完成的工作量相比,在不同线程之间拆分工作的成本需要很小.

进一步阅读:

https://en.wikipedia.org/wiki/Amdahl%27s_law

https://en.wikipedia.org/wiki/Gustafson%27s_law

  • 您是否能够指出一些阅读材料,讨论如何尝试计算完成任务的开销可行性的点? (12认同)
  • 在成为一名优秀的开发人员之前,你必须先成为一名优秀的作家。 (4认同)

ska*_*kaz 10

你应该意识到的第一件事是并非所有的并行都是有益的.并行性存在大量开销,并且这种开销可能会或可能不会很大,这取决于并行化的复杂性.由于并行功能中的工作量非常小,因此并行性管理所需的管理开销变得很大,从而减慢了整体工作.


Tej*_*ejs 9

为可枚举的VS创建所有线程只是执行可数的额外开销很可能是减速的原因.Parallel.ForEach不是一揽子业绩增长的举措; 无论是否可能阻止要为每个元素完成的操作,都需要对其进行权衡.

例如,如果您要创建Web请求或其他内容而不是简单地写入控制台,则并行版本可能会更快.实际上,简单地写入控制台是一个非常快速的操作,因此创建线程并启动它们的开销会变慢.


sal*_*ons 5

正如之前的作者所说,有一些与 相关的开销Parallel.ForEach,但这不是您看不到性能改进的原因。Console.WriteLine是一个同步操作,所以一次只有一个线程在工作。尝试将 body 改为非阻塞的东西,你会看到性能提升(只要 body 的工作量足够大以超过开销)。