7

摘要:我从 System.Threading.Tasks.Parallel.ForEach 和并发数据结构更改为简单的 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 与 Parallel.ForEach 是否加快了速度?
  2. 是不是简单地删除了并发数据结构(ConcurrentDictionary)?(因为它不需要同步线程)。
  3. 根据这个相关问题的答案

尽管 PLINQ 主要基于没有副作用的函数式编程风格,但副作用正是 TPL 的用途。如果您想实际并行工作而不是并行搜索/选择事物,则使用 TPL。

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

我正在寻找我的假设是否正确的验证,或者是我遗漏了什么的迹象。

4

2 回答 2

4

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

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

于 2011-03-04T16:12:23.813 回答
2

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

于 2011-03-04T22:21:29.787 回答