2012-04-04 39 views
11

我們需要處理的各種目錄中有大約500GB的圖像。每個圖像的大小約爲4MB,我們有一個python腳本來處理每個圖像(它讀取元數據並將其存儲在數據庫中)。根據大小,每個目錄可能需要1-4小時才能處理。在Python中處理大文件的最快方法

在GNU/Linux操作系統上,我們擁有2.2Ghz四核處理器和16GB RAM。當前腳本只使用一個處理器。利用其他內核和RAM更快處理圖像的最佳方式是什麼?啓動多個Python進程來運行腳本會利用其他內核嗎?

另一種選擇是使用像Gearman或Beanstalk這樣的工具將作業排除到其他機器上。我看了一下多處理庫,但不知道如何使用它。

+0

可能重複的[如何使用Windows 7中的所有核心?](http://stackoverflow.com/questions/3055696/how-to-use-all-the-cores-in-windows-7) – 2012-04-04 14:22:10

+1

如果你已經有了一個工作腳本,你可以指向任何你想要的文件/目錄,可以考慮編寫一個shell腳本來啓動儘可能多的實例。 – 2012-04-04 14:23:51

+4

我首先看看瓶頸在哪裏。如果你花大量的時間來執行IO,那麼你將無法做得更快。例如,如果一個進程設法以一定的速度從磁盤加載數據,那麼當多個進程正在咀嚼磁盤時,你很難保持這個速度。 – 2012-04-04 14:24:28

回答

6

將啓動多個Python進程來運行該腳本利用其他核心?

是的,它會,如果任務是CPU限制的。這可能是最簡單的選擇。但是,不要爲每個文件或每個目錄產生一個進程;考慮使用諸如parallel(1)之類的工具,並讓它產生類似於每個核心兩個進程的東西。

另一種選擇是使用像Gearman或Beanstalk這樣的工具將作業排除到其他機器上。

這可能工作。另外,請看Python binding for ZeroMQ,它使分佈式處理非常簡單。

我看過了多處理庫,但不知道如何使用它。

定義一個函數,說process,在一個單一的目錄讀取圖像,連接到數據庫和存儲元數據。讓它返回一個指示成功或失敗的布爾值。假設directories是要處理的目錄列表。然後

import multiprocessing 
pool = multiprocessing.Pool(multiprocessing.cpu_count()) 
success = all(pool.imap_unordered(process, directories)) 

將並行處理所有目錄。如果你願意,你也可以在文件級別進行並行處理;這需要更多的修補。

請注意,這將停止在第一次失敗;使其容錯需要更多的工作。

4

啓動獨立的Python進程非常理想。進程之間不會發生鎖定爭用,操作系統會安排它們同時運行。

您可能想要試驗看實例的理想數量 - 它可能多於或少於核心數量。會有磁盤和高速緩存存儲器的爭用,但另一方面,當另一個進程正在等待I/O時,您可能會運行一個進程。

2

查看answer到這個question

如果應用程序能夠處理輸入數據的範圍,那麼你就可以啓動應用程序的4種 情況下,輸入數據的不同範圍來處理 ,他們都完成後的結果結合起來。

即使該問題看起來是Windows特定的,它適用於所有操作系統上的單線程程序。

警告:當心你的硬盤驅動器實際上將導致進程爲一組,這個過程將是I/O密集型,太多的併發訪問執行不是因爲爭用我的順序處理慢/O資源。

4

您可以使用多處理池來創建用於提高性能的進程。比方說,你有一個處理圖像的函數handle_file。如果你使用迭代,它最多隻能使用一個核心的100%。爲了利用多個內核,池多處理爲您創建子進程,並將任務分配給它們。下面是一個例子:

import os 
import multiprocessing 

def handle_file(path): 
    print 'Do something to handle file ...', path 

def run_multiprocess(): 
    tasks = [] 

    for filename in os.listdir('.'): 
     tasks.append(filename) 
     print 'Create task', filename 

    pool = multiprocessing.Pool(8) 
    result = all(list(pool.imap_unordered(handle_file, tasks))) 
    print 'Finished, result=', result 

def run_one_process(): 
    for filename in os.listdir('.'): 
     handle_file(filename) 

if __name__ == '__main__': 
    run_one_process 
    run_multiprocess() 

run_one_process是處理數據的單核心方式,很簡單,但速度很慢。另一方面,run_multiprocess創建8個工作進程,並將任務分配給它們。如果您擁有8個內核,速度將提高8倍。我建議你將工號設置爲核心數的兩倍或者核心數。你可以試試看看哪種配置更快。

對於高級分佈式計算,您可以使用ZeroMQ作爲larsmans提到的。起初很難理解。但是一旦你理解了它,你可以設計一個非常高效的分佈式系統來處理你的數據。就你而言,我認爲有多個REP的REQ會足夠好。

enter image description here

希望這將是有益的。

0

如果您正在讀取大量文件並將元數據保存到數據庫,則您的程序不需要更多內核。

您的進程可能IO綁定不受CPU綁定。使用扭曲的適當的防禦和回調可能會超越任何試圖爭奪4核心的解決方案。

0

我認爲在這種情況下,使用Celery會很有意義。

相關問題