可以加速Python的IO吗?

15 投票
9 回答
21502 浏览
提问于 2025-04-15 11:31

考虑一下这个Python程序:

import sys

lc = 0
for line in open(sys.argv[1]):
    lc = lc + 1

print lc, sys.argv[1]

在我的6GB文本文件上运行它,大约需要2分钟完成。

问题是:有没有可能更快呢?

注意,下面这个程序所需的时间也是一样的:

wc -l myfile.txt

所以,我怀疑我的问题的答案就是简单的“没有”。

另外,我的真实程序做的事情比单纯数行要有趣得多,所以请给一个通用的答案,不要是关于计数行数的小技巧(比如在文件中保存行数的元数据)。

顺便说一下,我把这个问题标记为“linux”,因为我只对Linux特定的答案感兴趣。如果你有其他操作系统的答案,或者是与操作系统无关的答案,也可以随便给我。

另请参见这个后续问题

9 个回答

10

关键在于不是让电子移动得更快(这很难做到),而是让每单位时间内完成更多的工作。

首先,确保你的6GB文件读取是受I/O限制的,而不是受CPU限制的。

如果是受I/O限制的,可以考虑使用“扇出”设计模式。

  • 一个父进程会生成很多子进程。

  • 父进程读取6GB的文件,然后把数据行分发给子进程,通过写入它们的标准输入管道来实现。读取6GB文件的时间会保持不变。分发数据行时,父进程的处理应该尽量少。可以使用非常简单的过滤或计数。

    管道是一种内存中的通信通道。它是一个共享的缓冲区,有一个读取者和一个写入者。

  • 每个子进程从标准输入读取一行数据,并进行相应的处理。每个子进程可能会写一个简单的磁盘文件,保存最终的(汇总、减少)结果。稍后,这些文件中的结果可以进行合并。

13

用硬件解决问题。

正如gs提到的,你的问题主要是硬盘的传输速度。所以,换个更好的算法是没用的,但你可以买个更快的硬盘。

补充:gs还提到一个好点子;你也可以使用RAID配置来提升速度。这可以通过硬件或软件来实现(例如OS XLinuxWindows Server等)。


计算公式

(要传输的量) / (传输速度) = (传输时间)

(6000 MB) / (60 MB/s) = 100秒

(6000 MB) / (125 MB/s) = 48秒


硬件解决方案

ioDrive Duo据说是企业环境中最快的解决方案,"将在2009年4月上市"。

你也可以看看WD Velociraptor硬盘(转速10,000转/分钟)。

另外,我听说Seagate的Cheetah也是个不错的选择(转速15,000转/分钟,持续传输速度125MB/s)。

7

你无法超过硬盘的最大读取速度。

为了达到硬盘的最大速度,你可以使用以下两个小技巧:

  1. 用一个大一点的缓冲区来读取文件。你可以手动编写代码来实现,或者直接使用 io.BufferedReader(在 python2.6 及以上版本中可用)。
  2. 在另一个线程中并行进行换行符的计数。

撰写回答