Python 并行文件写入是否有效?
我想知道并行文件写入是否有效。实际上,硬盘一次只有一个可用的读磁头。因此,硬盘驱动器一次只能执行一项任务。 但下面的测试(python)与我的预期相矛盾: 要复制的文件大约为1 Gb 脚本1(//对同一文件逐行读写10次的任务): 脚本2(对同一文件逐行读写10次的任务): 脚本3(//将同一文件复制10次的任务): 脚本4(将同一文件复制10次的任务): 结果:Python 并行文件写入是否有效?,python,io,parallel-processing,Python,Io,Parallel Processing,我想知道并行文件写入是否有效。实际上,硬盘一次只有一个可用的读磁头。因此,硬盘驱动器一次只能执行一项任务。 但下面的测试(python)与我的预期相矛盾: 要复制的文件大约为1 Gb 脚本1(//对同一文件逐行读写10次的任务): 脚本2(对同一文件逐行读写10次的任务): 脚本3(//将同一文件复制10次的任务): 脚本4(将同一文件复制10次的任务): 结果: $ # // task to read and write line by line 10 times a same file $
$ # // task to read and write line by line 10 times a same file
$ time python read_write_1.py
real 1m46.484s
user 3m40.865s
sys 0m29.455s
$ rm test_jm*
$ # task to read and write line by line 10 times a same file
$ time python read_write_2.py
real 4m16.530s
user 3m41.303s
sys 0m24.032s
$ rm test_jm*
$ # // task to copy 10 times a same file
$ time python read_write_3.py
real 1m35.890s
user 0m10.615s
sys 0m36.361s
$ rm test_jm*
$ # task to copy 10 times a same file
$ time python read_write_4.py
real 1m40.660s
user 0m7.322s
sys 0m25.020s
$ rm test_jm*
这些基本结果似乎表明//io读写效率更高
谢谢你的光
我想知道并行文件写入是否有效
简短回答:同时从多个线程物理写入同一磁盘的速度永远不会比从一个线程写入该磁盘的速度快(这里讨论的是普通硬盘)。在某些情况下,它甚至可以慢得多
但是,一如既往,这取决于许多因素:
- 操作系统磁盘缓存:写操作通常由操作系统保存在缓存中,然后分块写入磁盘。因此,多个线程可以毫无问题地同时写入该缓存,并且这样做具有速度优势。尤其是当数据的处理/准备时间超过磁盘的写入速度时
- 在某些情况下,即使从多个线程直接写入物理磁盘,操作系统也会对此进行优化,并且只向每个文件写入大数据块
- 然而,在最坏的情况下,每次都可能将较小的块写入磁盘,导致每个文件交换机都需要进行硬盘寻道(在普通hdd上为±10ms!)(在SSD上进行相同操作不会太糟糕,因为有更多的直接访问,不需要寻道)
- 写入一个50MB的连续块需要1秒(在理想情况下)
- 在1MB的块中执行同样的操作,并在文件切换和结果之间进行磁盘寻道将给出:20ms写入1MB+10ms寻道时间。写入50MB需要1.5秒。这在时间上增加了50%,只是在两者之间做了一个快速搜索(从磁盘读取也一样——考虑到更快的读取速度,差异甚至会更大)
虽然我们希望操作系统能够很好地处理所有这些问题(或者通过使用示例),情况并非总是如此。你有什么证据证明硬盘只有一个读头?你写入文件的任何数据都会存储在你的计算机RAM中,直到你的计算机操作系统开始整理并很快将其写入磁盘。你期望得到什么样的结果?你所接受的答案是这样的//io不应该更高效。似乎我的结果显示//io比efficient@ScottHunter我的意思是,一个硬盘驱动器在给定的时间只能有一个磁头读写硬盘。正如在这里解释->谢谢@danny\u ds为您提供了真正完整的答案。这就是我的想法:目前,我不知道如何解释复制10倍的1GB文件的//io更快。也许正如你解释的那样,我的硬盘有一个大的缓存。@bioinformnatics-我将仔细查看你的代码和数据,但一个好的测量方法是,测量的总写入速度应该等于硬盘的物理写入速度(即复制相同大小的文件所需的时间)。如果您在使用多线程时感觉更好,这几乎肯定意味着处理时间要比写入时间长。另外,在测量(总)物理写入速度时,请确保所有数据都已刷新到磁盘。@bioinformnatics-请参阅我的更新答案。我看到,在测试中,您在循环中使用相同的文件,因此所有内容都可以在缓存中。该测试还使用了readline和writeline,这不是将数据写入磁盘的最快方式(可能比磁盘写入速度慢,不确定)。另一个(复制)测试可能是:复制磁盘上的文件(比可用内存大10倍)并计时。然后在1和多个线程中执行相同的操作。在这两种情况下,请尝试获得与te手动复制相同的时间。具体取决于
#!/usr/bin/env python
def read_and_write( copy_filename ):
with open( "/env/cns/bigtmp1/ERR000916_2.fastq", "r") as fori:
with open( "/env/cns/bigtmp1/{}.fastq".format( copy_filename) , "w" ) as fout:
for line in fori:
fout.write( line + "\n" )
return copy_filename
def main():
f_names = [ "test_jm_{}".format(i) for i in range( 0, 10 ) ]
for n in f_names:
result = read_and_write( n )
if __name__ == "__main__":
main()
#!/usr/bin/env python
from shutil import copyfile
from multiprocessing import Pool
def read_and_write( copy_filename ):
copyfile( "/env/cns/bigtmp1/ERR000916_2.fastq", "/env/cns/bigtmp1/{}.fastq".format( copy_filename) )
return copy_filename
def main():
f_names = [ "test_jm_{}".format(i) for i in range( 0, 10 ) ]
pool = Pool(processes=4)
results = pool.map( read_and_write, f_names )
if __name__ == "__main__":
main()
#!/usr/bin/env python
from shutil import copyfile
def read_and_write( copy_filename ):
copyfile( "/env/cns/bigtmp1/ERR000916_2.fastq", "/env/cns/bigtmp1/{}.fastq".format( copy_filename) )
return copy_filename
def main():
f_names = [ "test_jm_{}".format(i) for i in range( 0, 10 ) ]
for n in f_names:
result = read_and_write( n )
if __name__ == "__main__":
main()
$ # // task to read and write line by line 10 times a same file
$ time python read_write_1.py
real 1m46.484s
user 3m40.865s
sys 0m29.455s
$ rm test_jm*
$ # task to read and write line by line 10 times a same file
$ time python read_write_2.py
real 4m16.530s
user 3m41.303s
sys 0m24.032s
$ rm test_jm*
$ # // task to copy 10 times a same file
$ time python read_write_3.py
real 1m35.890s
user 0m10.615s
sys 0m36.361s
$ rm test_jm*
$ # task to copy 10 times a same file
$ time python read_write_4.py
real 1m40.660s
user 0m7.322s
sys 0m25.020s
$ rm test_jm*