PLinq本质上比System.Threading.Tasks.Parallel.ForEach更快

Chr*_*ber 7 c# linq concurrency plinq task-parallel-library

简介:我从System.Threading.Tasks.Parallel.ForEach和Concurrent Data结构更改为简单的plinq(Parallel Linq)查询.加速是惊人的.

那么plinq固有地比Parallel.ForEach快吗?或者它是否特定于任务.

// Original Code
// concurrent dictionary to store results
var resultDict = new ConcurrentDictionary<string, MyResultType>();

Parallel.ForEach(items, item =>
        {
            resultDict.TryAdd(item.Name, PerformWork(source));
        });


// new code

var results =
            items
            .AsParallel()
            .Select(item => new { item.Name, queryResult = PerformWork(item) })
            .ToDictionary(kv => kv.SourceName, kv => kv.queryResult);
Run Code Online (Sandbox Code Playgroud)

注意:每个任务(PerformWork)现在运行0到200毫秒.在我优化它之前,它需要更长的时间.这就是我在第一时间使用Tasks.Parallel库的原因.所以我从总时间的2秒到大约100-200毫秒的总时间,执行大致相同的工作,只是使用不同的方法.(哇linq和plinq太棒了!)

问题:

  1. 是否因为使用plinq vs Parallel.ForEach而加速?
  2. 它只是简单地删除并发数据结构(ConcurrentDictionary)?(因为它不需要同步线程).
  3. 根据这个相关问题的答案

PLINQ主要基于功能风格的编程而没有副作用,而副作用正是TPL的用途.如果你想实际并行工作而不是仅仅并行搜索/选择事物,你可以使用TPL.

我可以假设,因为我的模式基本上是功能性的(给输入产生没有突变的新输出),plinq是正确使用的技术吗?

我正在寻找验证我的假设是正确的,或者表明我错过了什么.

Dre*_*rsh 2

根据您在示例中提供的有限信息(我在OP的评论中要求提供更多详细信息),我猜您肯定会看到由于使用的分区算法而导致的差异。您应该阅读这篇博客文章中的块分区与范围分区,其中讨论了它们的不同之处以及它们可能最适合哪种类型的工作。强烈建议您阅读该博客文章以及这篇文章,其中更详细地介绍了这两种类型以及可以使用的其他两种类型的分区(尽管不适用于您的示例),并为您提供了一些视觉帮助更好地理解分区。最后,这是另一篇博客文章,讨论工作分区以及当默认分区算法对您的特定工作负载没有意义时它如何影响您。这篇文章实际上提到了一个很棒的程序,可以帮助您可视化工作中的分区程序,该程序是PFX 团队的一组并行示例的一部分。