2016-01-08 91 views
5

我想知道,如果並行寫入文件是有效的。實際上,硬盤一次只有一個可用的讀取頭。因此,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讀寫爲更高效。

感謝你照亮

+2

對於具有單個讀取頭的硬盤,您有什麼證據? –

+1

您寫入文件的任何數據都將存儲在您計算機的RAM中,直到您的計算機的操作系統開始對其進行整理並實際將其快速寫入磁盤。 – kindall

+0

你期待什麼結果? – AChampion

回答

9

我想知道,如果並行寫入文件是有效的。

簡短的回答:物理同時寫入多個線程在同一磁盤,決不會比從一個線程(這裏談論正常硬盤)寫入到磁盤速度更快。在某些情況下,它甚至會慢很多。

但是,一如既往,這取決於很多因素:

  • OS磁盤緩存:寫入通常由操作系統保存在緩存中,然後寫入到塊磁盤。因此,多個線程可以同時寫入到緩存中沒有問題,並且有速度上的優勢這樣做。特別是如果數據的處理/準備花費比磁盤的寫入速度更長的時間。

  • 在某些情況下,直接寫從多個線程的物理磁盤,即使,操作系統將優化這一點,只寫大塊每個文件。

  • 但是,在最壞的情況下,每次都可以將更小的數據塊寫入磁盤,從而導致每個文件切換器都需要硬盤查找(正常硬盤上的±10ms!一個SSD就不會那麼糟糕,因爲有更多的直接訪問,並沒有尋道需要)。

因此,在一般情況下,同時寫入多個線程磁盤時,它可能是一個好主意,使用某種準備(一些)數據在內存中,並寫入最後的數據到磁盤的更大的塊鎖定,或者由一個專用作家線程。如果文件在寫入時正在增長(即沒有設置文件大小),將數據寫入較大的塊也可以防止磁盤碎片(至少儘可能)。

在某些系統上可能根本沒有任何差別,但在其他系統上可能會產生很大的差異,並且會變得很慢(甚至在具有不同硬盤的同一系統上)。

要使用單線程vs多線程對寫入速度的差異進行良好測試,總文件大小必須大於可用內存 - 或者在測量結束之前至少應將所有緩衝區刷新到磁盤時間。只測量將數據寫入OS磁盤高速緩存所需的時間在這裏沒有多大意義。

理想情況下,將所有數據寫入磁盤的測量總時間應等於物理硬盤寫入速度。如果使用一個線程寫入磁盤比磁盤寫入速度慢(這意味着處理數據需要比寫入更多的時間),顯然使用更多線程會加快速度。如果從多個線程寫入的速度慢於磁盤寫入速度,則由不同文件(或同一個大文件內的不同塊)之間的切換導致的磁盤搜索時間會丟失。

要進行大量的磁盤時查找,讓我們來看看一些數字及時得到損失的想法:

說,我們與50MB/s的寫入速度的硬盤:

  • 寫一個50MB的連續塊需要1秒(理想情況下)。

  • 否則在1MB的塊是相同的,與文件開關和所得盤尋求之間將使:20ms的寫1MB + 10ms的尋道時間。寫入50MB需要1.5秒。這是一個50%的時間增加,只是做快速尋求之間(從磁盤讀取相同的持有 - 考慮到更快的閱讀速度差距甚至更大)。

實際上,它會在兩者之間,取決於系統。

儘管我們希望OS能夠好好照顧所有這些(或者通過使用例如IOCP),但情況並非總是如此。

+0

感謝@danny_ds爲您的真正完整答案。這是我雖然:目前,我不知道如何解釋1/10複製1GB文件的速度更快。也許正如你解釋我的硬盤有一個很大的緩存。 – bioinfornatics

+0

@bioinfornatics - 我會仔細看看你的代碼和數據,但一個好的方法是測得的總寫速度應該等於你硬盤的物理寫入速度(即不要再複製一個相同的文件尺寸)。如果你使用多線程的時間更長,這幾乎肯定意味着處理時間比寫入時間要長。測量(總)物理寫入速度時,還要確保將所有數據刷新到磁盤。 –

+0

@bioinfornatics - 查看我更新的答案。我發現在你的測試中,你正在循環中使用相同的文件 - 所以一切都可能在緩存中。測試還使用了readline和writeline - 這些並不是將數據寫入磁盤的最快方法(並且可能比磁盤寫入速度慢 - 不確定)。另一個(複製)測試可以是:將文件複製到磁盤上(大於可用內存的10倍)並計時。然後在1和多個線程中執行相同的操作。在這兩種情況下都儘量和手動拷貝一樣。 –