1

我知道他们说过早的优化是万恶之源……但就是那个时候。

我有一个缓慢但可以执行以下操作的工作程序:

  1. 从 file.input 读取块(顺序)
  2. 变换块
  3. 将转换后的块写入(附加)到 file.output

file.input 和 file.output 最终处于相同大小的范围内(10-100+ GB)。一个块通常约为 10K。转换步骤只是专有格式之间的转换。为了便于讨论,我们可以认为它在计算上与实时压缩算法相当。

这些步骤目前在单个线程中完成。

我的问题:如何让这个表现更好?

我意识到基于正在处理的纯数据量,这永远不会变得“快”,但我必须相信有一些相对简单和标准的技术可以让这个更快。

我尝试在读取步骤 (1) 中添加缓冲。也就是说,读取比块大小大得多的块并从缓冲区中读取。这有帮助。但是,对于转换步骤 (2) 和附加 (3) 是否可以做任何事情,我有点坚持。

根据 Resource Monitor,我的 CPU 使用率在 30-45% 之间波动,磁盘 I/O 有一些持续的低使用率。

我将 C# 与一堆 P/invoke 互操作与本机库一起使用。

4

5 回答 5

2

首先,不要在这种情况下添加线程,它们不会提高你的性能。(当然,如果您的应用程序有 UI 界面,您可以添加一个线程来执行您的密集工作并让用户继续执行其他任务)

其次,尽量减少磁盘上的 IO。尽可能多地读取字节并一起写入。第三,您最好的选择可能是优化您的转型工作。

于 2012-04-17T21:39:39.740 回答
2

首先,您应该验证所有步骤都占用了大部分时间——如果瓶颈只是一个步骤,那么我们在这里看错了图片。

磁盘 I/O 可能需要一些时间,在此期间 CPU 可用于其他任务,因此多线程解决方案可以提高性能。也许您可以使用一个线程来不断填充缓冲区,最多可处理 10 个可处理数据块,一个处理第一个加载的任何块,另一个简单地写入已完成处理的任何块。然后一对AutoResetEvents可以通知每个线程前一个线程已完成处理一个或多个块。

于 2012-04-17T21:37:08.597 回答
1

措施

  • 1(简单的顺序读取无处),
  • 3(随机字节的简单顺序写入)
  • 1+3(读取并立即复制到大小合理的块 16K-64k-512k-1Mb)
  • 2(只是计算)

比看看你的数字,看看重叠是否能带来任何可观的好处。45% 的 CPU 负载并不算太糟糕,所以你最好保持原样。

您可以获得的最佳结果是 Max(1, 2, 3),因此请相应地计划优化。

于 2012-04-17T21:40:31.433 回答
1

如果您使用的是 .NET 4,则可以尝试MemoryMappedFileMemoryMappedViewAccessor

于 2012-04-17T21:34:53.757 回答
1

您的主要问题将是 I/O。您在 2 个文件之间交替的事实使事情变得更糟。

  • 缓冲读取和写入。大动作更好,在这种情况下,更少的动作也更好。

由于还有一个 CPU 密集型部分,我会尝试使用线程。为了尽量减少等待,我会使用管道:ReaderThread -> Queue -> ProcescessingThread -> Queue -> WriterThread

于 2012-04-17T21:48:45.773 回答