2

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

该程序执行以下操作:

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

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

然而,转换需要 1 小时而不是传统的 foreach 1.5 小时Parallel.Foreach(我尝试过的服务器有 2 x Intel Xeon Procs)。

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

4

3 回答 3

1

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

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

于 2012-09-03T14:18:16.533 回答
1

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

  1. 运行的线程多于处理器。
  2. Aspose 库不支持多线程。
  3. GUI线程的多种方法是线程安全的,不能同时从不同的线程访问。

我还建议您阅读我之前关于任务并行库的答案 - 单核并行

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

于 2012-09-03T14:05:42.943 回答
0

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

但是您的方法假设转换本身并没有很好地利用多个内核。如果确实如此,并且它受 CPU 限制,那么它已经在对您尝试引入的内核进行某种并行使用,并且您可能会因此而降低整个事情的效率。

编辑:根据 svick 的评论,想法变得更加清晰。如果库不支持多线程使用,那么它不太可能在不出错的情况下走到这一步,但它对多线程的支持可能涉及大量内部锁定,当偶尔有并发调用时可能会很好,但非常昂贵如果你有长期的重并发。

于 2012-09-03T14:07:53.377 回答