一尘不染

并行ForEach比ForEach慢

c#

这是代码:

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);
}

问题是,Parallel.ForEach大约foreach需要400毫秒,而常规大约需要40毫秒。我到底在做错什么,为什么这不能按我预期的那样工作?


阅读 197

收藏
2020-05-19

共1个答案

一尘不染

假设您有一项任务要执行。假设您是一位数学老师,并且有20篇论文要评分。一篇论文要花两分钟,所以大约要花40分钟。

现在,假设您决定雇用一些助手来帮助您对论文进行评分。找到四个助手需要一个小时。你们每个人要写四篇论文,而且八分钟之内就完成了。您已经将40分钟的工作时间换成了68分钟的工作时间,包括寻找助手的额外时间,所以这不是节省。寻找助手的开销大于自己完成工作的成本。

现在假设您有两万篇论文要评分,因此大约需要40000分钟。现在,如果您花一个小时寻找助手,那就是胜利。你们每个人要拿出4000篇论文,总共需要8060分钟而不是40000分钟,而节省的时间几乎是5倍。寻找助手的开销基本上是无关紧要的。

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

进一步阅读:

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

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

2020-05-19