2013-02-18 20 views
0

我想同時寫入大量文件(比如10000個文件)。我發現我可以使用多處理。我任意選擇使用100個進程來寫這些文件。我需要知道是否有辦法找到最佳使用的進程數量?此代碼之後還需要做任何清理或所有進程自動終止?同時寫入大量文件的最佳進程數

我也想知道是否有更有效的方法來同時寫入大量的文件。

from multiprocessing import Pool 

def write(x): 
    fopen=open('file_'+str(x),'w') 
    fopen.write('anything') 
    fopen.close() 

if __name__ == '__main__': 
    pool = Pool(processes=100)    
    pool.map(write, range(10000))   
+2

爲什麼不用不同的值進行測試並比較結果?我認爲這將高度依賴於你運行它的硬件。 – ellak 2013-02-18 18:54:49

+0

這就是爲什麼我要問,我試了幾個值,而100似乎給出了最好的結果,但我不知道是否有可能根據硬件規格說明什麼是最佳使用數量 – hmghaly 2013-02-18 18:59:35

+1

大多數硬件,對於合理大小的文件,由於您只能以最大速率將數據打包到磁盤上,因此您可能不會注意到您是否一次只能寫入10個或100個進程,從而無法提高速度。 – mgilson 2013-02-18 19:00:06

回答

1

首先,對於純粹的I/O,threading很可能是因爲multiprocessing一樣好,而且往往更好。它也沒有關於「我需要任何清理」的奧祕。所以,你可能想要測試一下。其次,如果你想知道最快的方法來做到這一點,唯一真正的選擇是測試,使用timeit,或者你的shell的time或等效。聽起來你已經這麼做了。如果您正在尋找一種方式,以編程方式根據您可以讀取的系統信息確定理想池大小(SSD vs. 10K HD vs. 5200 HD vs.遠程共享,局域網與廣域網,快速局域網與慢速局域網,SMB與NFS,Windows與POSIX等),您可能需要在各種機器上進行測試並進行一些統計分析。而其中一些信息並不是靜態可用的,因此您確實需要啓動該過程,然後隨時調整池大小。這將會非常複雜 - 我猜測所有這些工作在大多數情況下只能讓你獲得10%的收益。

如果您確實需要從文件I/O中擠出最後幾個百分點,則可能需要降低一個或兩個百分點。

至少,您可能希望從等式中刪除Python和/或stdio緩衝區(假設文件真的很小)並使用os.openos.write。創建字節的原始緩衝區而不是字符串甚至會有所幫助(尤其是如果這是Python 3的話)。如果你實際上對每個文件都寫同樣的東西,甚至對許多文件都寫同樣的東西,那麼使用相同的緩衝區可能會讓操作系統認識到你對多個文件寫了同樣的東西,這意味着緩存可以是完美的接近完美。

您甚至可能想要下載到平臺特定的API。例如,在Windows上,使用重疊的I/O允許操作系統儘可能高效地調度寫入操作,並且圍繞IOCP創建本地線程池以處理完成操作,還會消除寫入調度之上的所有開銷。 (您可以通過​​或win32api訪問CreateFileWriteFileEx等。或Google for「IOCP Python的」示例代碼,這都將是不完整的或部分不相關的,尤其是因爲大部分是專做C10K插槽服務器,但它將至少證明足以讓其他人自己放在一起,在MSDN的幫助和試驗和錯誤。)我想不出任何等效的POSIX(嗯,aio_write是相當於WriteFileEx,但它不會幫助性能在任何真實世界的* nix平臺上,據我所知)。

或者,您可能需要將向上移動一步。如果你真的要爲所有文件或只是很多文件寫入相同的數據,爲什麼不把它寫入一個文件,然後讓操作系統複製該文件?它可能能夠做得更好。

或者,甚至更簡單 - 而且速度更快 - 將其寫入一個文件,然後將其餘部分創建爲硬鏈接或符號鏈接。


既然你問到最後一個選項:

背後創建鏈接的想法是,你只能創建一個文件,但創造10000個不同的名稱來訪問它之下。

這意味着如果你編輯一個文件,所有的10000都被編輯。如果這不是你想要的,鏈接是不合適的。

但是,如果它是你想要的,有兩種基本類型的鏈接:硬鏈接和符號鏈接。

現代文件系統允許多個目錄條目指向同一個文件。創建一個hard link是一種創建另一個指向與現有文件相同的文件的目錄條目的方法。在Python中,你可以用os.link來做到這一點。所以:

with open('file_0', 'w') as f: 
    f.write('anything') 
for i in range(1, 10000): 
    os.link('file_0', 'file_{}'.format(i)) 

現在你的文件系統中有一個名爲file_0通過file_9999 10000項,但他們在磁盤上相同的實際數據的所有名稱。編輯一個,其他9999全部改變。刪除一個,其他9999仍然存在。

硬鏈接有一些小問題,並且有一個主要問題。小問題是,除了普通文件之外,每個平臺都有關於硬鏈接的不同規則,並且通常不能跨文件系統進行硬鏈接。主要問題是Windows。首先,你需要一些類似於Vista和NTFS 6的全面支持,Win2000和NTFS 4支持部分支持。但更重要的是,os.link在Windows上不存在。因此,您必須使用​​或win32api調用底層CreateHardLink函數(或subprocess運行mklinkfsutil命令)。

A symbolic link是更高層次的想法。這是一種特殊的文件,通過路徑引用另一個文件。這意味着您可以閱讀有關符號鏈接本身的信息(請參閱statlstat),創建保留鏈接信息的tarball等。這也意味着,如果刪除file_0,則其他鏈接都將變爲斷開的鏈接,指向文件isn在那裏。無論如何,在Python中,您使用os.symlink來創建它們(使用與上面完全相同的代碼)。

符號鏈接沒有硬鏈接的大多數限制,但它們對於Windows更糟 - 在Vista之前沒有任何符號鏈接,純文本與目錄的不同規則,對可以遍歷的鏈接數量的限制,需要非管理員用戶沒有的特殊權限等。當然,您不能使用Python中的os.symlink

還有一些平臺特定的東西,如Windows快捷鍵和Mac別名,它們與符號鏈接具有相似但不完全相同的特徵。

+0

這看起來都非常有用,並開闢了幾個可能的方向......其中我有興趣寫入一個單獨的文件,並創建其餘的硬鏈接或符號鏈接的可能性,你怎麼做? – hmghaly 2013-02-18 20:59:14

+0

@hmghaly:我會編輯答案以包含更多信息。但是如果你提到了你關心的平臺,這將會有所幫助。只是POSIX? POSIX和Windows,但只有Vista和更高版本?一切? – abarnert 2013-02-18 21:04:51

+0

我主要使用Windows,但一些應用程序應該也運行在我的linux服務器 – hmghaly 2013-02-18 21:22:08

相關問題