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

时间:2011-03-04 16:09:06

标签: c# linq concurrency task-parallel-library plinq

摘要:我从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);

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

问题

  1. 由于使用plinq vs Parallel.ForEach?
  2. ,速度是否正常?
  3. 它只是简单地删除并发数据结构(ConcurrentDictionary)? (因为它不需要同步线程)。
  4. 基于此related question
  5. 的回答
      

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

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

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

2 个答案:

答案 0 :(得分:4)

不可能使用这两个代码示例在Parallel.ForEach和PLINQ之间进行明确的比较。代码示例太不相同了。

向我跳出的第一个项目是第一个使用ConcurrentDictionary的示例,第二个使用Dictionary。这两种类型具有非常不同的用途和性能特征。为了在两种技术之间进行准确比较,您需要在这里与类型保持一致。

答案 1 :(得分:2)

根据您在样本中提供的有限信息(我在OP的评论中询问了更多详细信息),我猜你肯定会看到由于使用的分区算法而产生的差异。您应该在这篇博客文章中阅读Chunk Partitioning vs. Range Partitioning,其中讨论了它们的不同之处以及它们最适合的工作类型。强烈建议您阅读该博客文章以及this one,其中详细介绍了这两种类型以及可以使用的其他两种类型的分区,但不适用于您的样本,并提供一些视觉辅助工具可以更好地理解分区。最后,here's yet another blog post讨论了工作分区以及当默认分区算法对您的特定工作负载没有意义时它会如何影响您。该帖子实际上指的是一个很棒的程序,它可以帮助您在a set of parallel samples from the PFX team的工作中可视化分区工作。