是否有可能加速python IO?

时间:2009-05-11 17:06:47

标签: python linux performance text-files

考虑这个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

所以,我怀疑对我的问题的回答只是一个简单的“不”。

另请注意,我的真实程序正在做一些比计算线条更有趣的事情,所以请给出一个通用的答案,行计数技巧(比如在文件中保留行数元数据) )

PS:我在这个问题上标记了“linux”,因为我只对linux特定的答案感兴趣。如果有的话,请随意提供与操作系统无关的内容,甚至是其他操作系统的答案。

另请参阅follow-up question

8 个答案:

答案 0 :(得分:12)

在问题上抛出硬件。

正如gs所指出的,你的瓶颈是硬盘传输率。所以,不,你不能使用更好的算法来改善你的时间,但你可以购买更快的硬盘。

编辑: gs的另一个好处;您还可以使用RAID配置来提高速度。这可以使用hardware或软件(例如OS XLinuxWindows Server等)来完成。


管理公式

(Amount to transfer) / (transfer rate) = (time to transfer)

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

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


硬件解决方案

The ioDrive Duo被认为是企业环境中最快的解决方案,“将于2009年4月上市”。

或者您可以查看WD Velociraptor硬盘(10,000 rpm)。

另外,我听说Seagate Cheetah是一个不错的选择(转速为15,000 rpm,传输速率为125MB / s)。

答案 1 :(得分:8)

诀窍不是让电子移动得更快(这很难),而是每单位时间完成更多的工作。

首先,确保您的6GB文件读取是I / O绑定,而不是CPU绑定。

如果它受I / O限制,请考虑“扇出”设计模式。

  • 父进程会产生一群孩子。

  • 父级读取6Gb文件,并通过写入STDIN管道将子行传递给子级。 6GB的读取时间将保持不变。行处理应尽可能少地处理父处理。应该使用非常简单的过滤器或计数。

    管道是用于通信的内存中通道。它是一个带读者和作者的共享缓冲区。

  • 每个孩子从STDIN中读取一行,并做适当的工作。每个孩子应该写一个简单的磁盘文件,其中包含最终(汇总,减少)结果。稍后,可以合并这些文件中的结果。

答案 2 :(得分:5)

简单“不”。

你几乎达到了最高磁盘速度。

我的意思是,您可以mmap该文件,或者以二进制块读取它,并使用.count('\n')或其他内容。但这不太可能带来重大改进。

答案 3 :(得分:4)

如果您认为磁盘可以读取60MB / s,则需要6000/60 = 100秒,即1分40秒。我不认为你可以更快,因为磁盘是瓶颈。

答案 4 :(得分:4)

您的速度不能超过最大磁盘读取速度。

为了达到最大磁盘速度,您可以使用以下两个提示:

  1. 使用大缓冲区读取文件。这可以“手动”编码,也可以使用io.BufferedReader(在python2.6 +中提供)进行编码。
  2. 新行在另一个线程中并行计数。

答案 5 :(得分:1)

正如其他人所说 - “不”

几乎所有的时间都花在等待IO上。如果这是您需要多次执行的操作,您拥有一台有大量内存的计算机,您可以将该文件保留在内存中。如果你的机器有16GB的内存,你可以在/ dev / shm下使用8GB。

另一种选择: 如果您有多台计算机,这个问题在并行化方面是微不足道的。在多台机器之间拆分它,每台机器都计算它们的换行符,并添加结果。

答案 6 :(得分:1)

2分钟听起来有权阅读整个6gb文件。你可以对算法或操作系统做些什么来加快速度。我认为你有两个选择:

  1. 为问题投入资金并获得更好的硬件。如果这个项目适合你的工作,可能是最好的选择。

  2. 不要读取整个文件。我不知道你要对数据做什么,所以也许你没有任何选择,只能阅读整个事情。另一方面,如果您正在扫描整个文件中的某个特定内容,那么在开始时将一些元数据放在那里会有所帮助。

答案 7 :(得分:0)

请注意,Python I / O是用C实现的,所以没有太多运气可以进一步加快它的速度。