是否有可能加速python IO?

Dav*_*ide 12 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]
Run Code Online (Sandbox Code Playgroud)

在我的6GB文本文件上运行它,它在~2分钟内完成.

问题:是否有可能加快速度?

请注意,同一时间需要:

wc -l myfile.txt
Run Code Online (Sandbox Code Playgroud)

所以,我怀疑对我的问题的回答只是一个简单的"不".

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

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

另见后续问题

tgr*_*ray 12

抛出硬件问题.

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

编辑: gs的另一个好点; 您还可以使用RAID配置来提高速度.这可以通过硬件或软件(例如OS X,Linux,Windows Server等)完成.


控制方程

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

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

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


硬件方案

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

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

此外,我听说Seagate Cheetah是一个不错的选择(15,000 rpm,持续125 MB/s的传输速率).

  • RAID可能会快得多. (3认同)

S.L*_*ott 8

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

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

如果它受I/O限制,请考虑"扇出"设计模式.

  • 父进程产生了一堆孩子.

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

    管道是用于通信的内存中通道.它是一个带有阅读器和写入器的共享缓冲区.

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

  • 当然,扇出仅在您受单个 CPU 核心约束但有更多可用核心时才有用。如果您受 I/O 限制,则不会产生任何影响。 (2认同)

nos*_*klo 5

简单的"不".

你几乎达到了最大磁盘速度.

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


Geo*_*lly 5

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


Bar*_*ndo 5

您无法获得比最大磁盘读取速度更快的速度。

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

  1. 用大缓冲区读入文件。这可以“手动”编码,也可以简单地使用 io.BufferedReader (在 python2.6+ 中可用)。
  2. 在另一个线程中并行计算换行符。

  • 通常你会是对的。但是,在这种情况下,从文件读取的线程将等待 I/O,而另一个线程解析换行符。这样 - 读取器线程不会等待解析器线程解析后续读取之间的换行符。 (5认同)
  • -1 不知道如何在另一个线程中进行换行计数可能会加速。它只会减慢速度。等待线程不会让您等待更快。 (4认同)
  • 我同意 nosklo。我认为增量是如此之快以至于无关紧要,另一个线程甚至可以使这样的事情变慢。此外,默认情况下 for 循环已经在 python 中缓冲。我怀疑使用 BufferedReader 使缓冲区更大会有所帮助。 (2认同)