我想知道并行文件写入是否有效。确实,硬盘一次具有一个可用的读取头。因此,HDD可以一次执行一项任务。但是下面的测试(在python中)与我的期望相矛盾:
要复制的文件约为1 Gb
脚本1(//读取和写入同一文件10次的任务):
#!/usr/bin/env python from multiprocessing import Pool 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 ) ] pool = Pool(processes=4) results = pool.map( read_and_write, f_names ) if __name__ == "__main__": main()
脚本2(读取和写入同一文件的行10次的任务):
#!/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()
脚本3(//复制同一文件10次的任务):
#!/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()
脚本4(将同一文件复制10次的任务):
#!/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*
这些基本结果似乎表明// io读写更有效。
谢谢你的光
我想知道并行文件写入是否有效。
简短的答案:从多个线程 物理上同时 写入同一磁盘,永远不会比从一个线程中写入同一磁盘快(在此谈论 普通 硬盘)。在某些情况下,它甚至可能慢很多。
但是,与往常一样,它取决于许多因素:
操作系统磁盘缓存:写入通常由操作系统保存在缓存中,然后分块写入磁盘。因此,多个线程可以同时写入该高速缓存而不会出现问题,并且这样做具有速度优势。特别是如果数据的处理/准备时间比磁盘的写入速度长。
在某些情况下,即使从多个线程直接写入物理磁盘,操作系统也会对此进行优化,并且仅将大块写入每个文件。
但是,在最坏的情况下,每次都可能将较小的块写入磁盘,从而导致每个文件开关都需要进行硬盘寻道(在普通硬盘上为±10ms!)(在SSD上执行相同操作)太糟糕了,因为有更多直接访问权限,无需搜索)。
因此,通常,从多个线程同时写入磁盘时,最好在内存中准备(一些)数据,然后使用某种锁将最终数据以更大的块写入磁盘,或者从一个专用的磁盘中写入。 writer-thread 。如果文件在写入时不断增长(即,未设置文件大小),则将数据写入较大的块还可以防止磁盘碎片(至少尽可能多)。
在某些系统上,可能根本没有差异,但是在其他系统上,差异可能很大,并且变慢得多(甚至在具有不同硬盘的同一系统上)。
为了对使用单线程与多线程的写入速度的差异进行良好的测试,文件总大小必须大于可用内存- 或至少在测量结束时间之前将所有缓冲区刷新到磁盘。在这里,仅测量将数据写入OS磁盘缓存所需的时间并没有多大意义。
理想情况下,将所有数据写入磁盘的总时间应等于物理硬盘的写入速度。如果使用一个线程向磁盘写入速度慢于磁盘写入速度(这意味着处理数据要比写入数据花费更长的时间),则显然使用更多线程将加快处理速度。如果从多个线程进行的写入变得比磁盘的写入速度慢,则由于在不同文件(或同一大文件内的不同块)之间切换而导致的磁盘寻道时间将会浪费。
为了了解执行大量磁盘搜寻时所浪费的时间,让我们看一些数字:
假设我们有一个写入速度为50MB / s的硬盘:
编写一个连续的50MB块将花费1秒(在理想情况下)。
以1MB的块进行相同的操作,同时进行 文件切换, 并在两者之间进行磁盘寻道,将得到:20ms写入1MB + 10ms寻道时间。写入50MB需要1.5秒。时间增加了50%,只是在两者之间进行了 快速查找 (从磁盘读取也保持相同-考虑到更快的读取速度,差异甚至会更大)。
实际上,取决于系统,它将介于两者之间。
尽管我们希望操作系统能很好地处理所有这些问题(例如通过使用IOCP),但情况并非总是如此。