PLINQ没有改善性能

时间:2012-09-17 18:53:13

标签: c# linq plinq

我编写了一个LINQ,用于查找文本文件中唯一字符的频率。我还在select的帮助下将初始结果转换为对象。最终结果以List的形式出现。 以下是我使用过的查询。

charNodes = inputString.GroupBy(ch => ch)
            .Select((ch) => new TNode(ch.Key.ToString(),ch.Count()))
            .ToList<TNode>();

我有一台四核机器正在运行,上面的查询运行时间为15ms。但奇怪的是,当我PLINQ进行同样的查询时花了更多的时间。下面的一个花了大约40ms。

charNodes = inputString.GroupBy(ch => ch).AsParallel
            .Select((ch) => new TNode(ch.Key.ToString(),ch.Count()))
            .ToList<TNode>();

最糟糕的情况是下一个查询花了大约83毫秒

charNodes = inputString.AsParallel().GroupBy(ch => ch)
                               .Select((ch) => new TNode(ch.Key.ToString(), ch.Count()))
                               .ToList<TNode>();

这里出了什么问题?。

2 个答案:

答案 0 :(得分:2)

当出现这类问题时,答案总是一样的:PLINQ开销高于收益。

这是因为工作项非常小(通过char分组,或者从简单的输入创建新对象)。当它们更大时它会更好。

答案 1 :(得分:0)

根据您提供的代码严格判断那里发生的事情真的很难。

TPL使用线程池线程。线程池启动时有大约10个正在运行的线程。 如果您需要更多线程,那么只要需要新线程,线程池就会每秒创建一次新线程。如果您的循环导致超过10个并行操作,则需要花费时间来启动新线程。 更正:并行循环需要的线程数量从可用线程中消失线程池。线程池试图在该池中保持最小数量的可用线程,如果它注意到线程花费的时间太长,它将启动新的线程来补偿 - 这需要资源。框架的很多部分都使用线程池,因此有各种各样的机会可能会给线程池带来压力。启动一个线程相当昂贵。

另一个可能是,如果您的迭代次数超过可用 CPU的数量,则会产生大量的上下文切换。上下文切换很昂贵,会影响CPU的负载以及操作系统在线程之间切换的速度。

如果您提供更多详细信息,例如输入数据,我可以在答案中提供更多详细信息。