Parallel.ForEach表现不佳

时间:2012-09-03 14:01:24

标签: c# .net performance parallel-processing parallel.foreach

我写了一个小程序,将一堆文件转换为pdf。

该计划执行以下操作:

  • 从文件夹中获取FileInfo个对象数组(10'000个文档)
  • 每个FileInfo
    • 使用FileInfo.CopyTo()
    • 创建备份副本
    • 使用一些Aspose Libraries将文档转换为PDF
    • 转换后,将PDF复制到新目的地
    • 在foreach中,由WinForm UI引发并处理事件以显示一些进展

根据文档的大小,文档的转换可能需要0-3秒。 我认为那将是Parallel.ForEach的完美候选者,所以我修改了程序。

然而,使用Parallel.Foreach的传统foreach 1.5小时转换时间为1小时(服务器我已经尝试过它有2个Intel Xeon Procs)。

我做错了什么或者我需要考虑什么才能获得更好的表现?

3 个答案:

答案 0 :(得分:1)

我可以考虑几个可能导致Parallel.Foreach变慢的问题:

  1. 运行比处理器更多的线程。
  2. Aspose Libraries不支持多线程。
  3. GUI线程的多种方法是线程安全的,不能同时从不同的线程到达。
  4. 我还建议您阅读我之前关于Task parallel library - Parallelism on single core

    的回答

    它谈论单核,但它可以反映你的问题。

答案 1 :(得分:1)

我建议通过查看任务管理器中的CPU和资源监视器中的磁盘I / O响应时间/队列长度和/或查看各种可用的性能计数器来检查您的操作是否受CPU限制或I / O限制。

我怀疑您的问题很可能是您现在正在同时执行多个文件副本(用于创建备份和写入转换后的文件)。与随机访问相比,硬盘的顺序访问速度要快得多(如果一次只能写/读一个文件)。

答案 2 :(得分:0)

这取决于很多事情。我当然会尝试将MaxDegreeOfParallelism设置为2,希望如果转换是CPU绑定的和单线程的,那么每个核心有一个应该接近理想,但肯定会进一步实验。

但是你的方法假设转换本身并不能很好地利用多个核心。如果它确实存在,并且它受CPU限制,那么它已经在尝试引入你想要引入的核心的并行使用,并且你可能只是因为这个原因而使整个事情效率降低。

编辑:根据svick的评论,思想更加清晰。如果库不支持多线程使用,那么它不可能在没有错误的情况下实现这一点,但是它对多线程的支持可能涉及很多内部锁定,当偶尔有并发调用时可能会很好,但非常昂贵如果你有长期沉重的并发性。