有可能加速python IO吗?
考虑一下这个python程序:有可能加速python IO吗?,python,linux,performance,text-files,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 所以,我怀疑我的问题的答案只是一个简单的“不” 还要注意,我真正的程序所做的事情比仅仅计算行数更有趣,因此请给出一个一般性的答案,而不是行数技巧(
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特定的答案感兴趣。如果你有操作系统不可知论,或者其他操作系统的答案,请随意给出
另请参见普通的“否”。
您几乎已经达到了最大磁盘速度
我的意思是,您可以读取文件,或者读取二进制块,然后使用
.count('\n')
或其他方法。但这不太可能带来重大改进。如果假设磁盘可以读取60MB/s,则需要6000/60=100秒,即1分40秒。我不认为您可以更快,因为磁盘是瓶颈。正如其他人所说:“不”
你几乎所有的时间都在等待IO。如果这是您需要多次执行的操作,并且您有一台具有大量ram的机器,那么您可以将该文件保存在内存中。如果您的机器有16GB的ram,那么在/dev/shm上可以使用8GB
另一种选择:
如果您有多台机器,这个问题对于并行化来说是微不足道的。在多台机器之间拆分it,每台机器都计算其换行数,并添加结果。您的磁盘读取速度不能超过最大磁盘读取速度 为了达到最大磁盘速度,您可以使用以下两个技巧:
请注意,Python I/O是在C中实现的,因此没有多少运气可以进一步加快它的速度。用硬件解决这个问题。 正如gs指出的,您的瓶颈是硬盘传输速率。所以,不,你不能用更好的算法来提高你的时间,但你可以买一个更快的硬盘 编辑:gs的另一个优点;您还可以使用配置来提高速度。这可以使用或软件(例如,等)来完成
控制方程
(转账金额)/(转账利率)=(转账时间)
(6000 MB)/(60 MB/s)=100秒
(6000 MB)/(125 MB/s)=48秒
硬件解决方案
被认为是企业环境中最快的解决方案,“将于2009年4月推出”
或者您也可以查看WD Velociraptor硬盘(10000 rpm)
另外,我听说希捷是一个不错的选择(15000转/分,持续125MB/s的传输速率)。诀窍不是让电子移动得更快(这很难做到),而是让每单位时间做更多的工作
首先,确保您的6GB文件读取是I/O绑定的,而不是CPU绑定的
如果是I/O绑定,请考虑“扇出”设计模式。
- 父进程产生一堆子进程
- 父级读取6Gb文件,并通过写入子级的STDIN管道将行输出给子级。6GB的读取时间将保持不变。行处理应尽可能少地涉及父处理。应使用非常简单的过滤器或计数
管道是内存中用于通信的通道。它是一个与读写器共享的缓冲区
- 每个孩子从STDIN中读取一行,并做适当的工作。每个孩子可能都应该编写一个简单的磁盘文件,其中包含最终(总结、减少)结果。稍后,可以合并这些文件中的结果
2分钟听起来可以读取整个6gb文件。对于算法或操作系统来说,没有什么可以加快速度的。我认为你有两个选择:
花钱解决这个问题,得到更好的硬件。如果这个项目适合你的工作,可能是最好的选择
不要读取整个文件。我不知道你想用这些数据做什么,所以也许你别无选择,只能阅读整件事。另一方面,如果您正在扫描整个文件以查找某个特定的内容,那么在开始时在其中放入一些元数据可能会有所帮助
这里有一个非常类似的讨论:这里的大部分时间可能都花在等待磁盘上。请参阅关于使用posix_fadvise(2)
来回答您的后续问题。我来晚了,但是对于大文件,“sed-n'$=”filename”比“wc-l”快-我不知道在另一个线程中如何加快换行计数。这只会让事情变慢。等待线程不会让你等待得更快。通常你是对的。但是,在这种情况下,从文件读取的线程将等待I/O,而另一个线程则解析换行符。这样,读线程就不会等待解析器线程在后续读取之间解析换行符。我接受这个答案,即使在这种情况下,它不值得付出努力,因为每行的作业量非常低,而且我已经在以hw最大速度运行。更多细节请参见后续问题。我同意nosklo的观点。我认为增量如此之快以至于与此无关,而另一个线程甚至可以使这样的事情变慢。此外,默认情况下,for循环已经在python中进行了缓冲。我怀疑使用BufferedReader使缓冲区变大会有帮助。你计算中的20是从哪里来的?你是说6000/60=100?60不是20,对吗?我首先想用20MB/s计算,但后来我想