2010-06-10 29 views
5

我不得不做大量的I/O綁定操作,即解析大文件並將其從一種格式轉換爲其他格式。最初我曾經連續做過,即一個接一個地解析。性能非常差(使用時間超過90秒)。所以我決定使用線程來提高性能。我爲每個文件創建了一個線程。 (4條)python線程和性能?

for file in file_list: 
      t=threading.Thread(target = self.convertfile,args = file) 
      t.start() 
      ts.append(t) 
for t in ts: 
      t.join() 

但是令我驚訝的是,沒有任何性能改善。現在也需要大約90多秒才能完成任務。由於這是I/O界限操作,我曾預計會提高性能。

回答

10

在通常的Python解釋器下,由於global interpreter lock(又名GIL),線程將不會爲您的程序分配更多CPU內核。

multiprocessing模塊可以幫助你在這裏。 (請注意,它是在Python 2.6中引入的,但Python 2.5中存在backports。)

正如MSalters所說,如果您的程序是I/O綁定,這是否值得商榷是值得商榷的。但它可能是值得一試:)

達到你想要使用的是什麼這個模塊:

import multiprocessing 

MAX_PARALLEL_TASKS = 8 # I have an Intel Core i7 :) 

pool = multiprocessing.Pool(MAX_PARALLEL_TASKS) 

pool.map_async(convertfile, filelist) 

pool.close() 
pool.join() 

重要!您傳遞給map_async的功能必須是可以刪除的。一般情況下,實例方法是不可pickleable,除非你設計它們是如此!請注意,convertfile以上是一項功能。

如果您確實需要從convertfile獲得結果,那麼也有辦法做到這一點。多處理文檔頁面上的例子應該澄清。

+0

感謝delty..But多處理模塊有它自己的問題。 1)我不得不重構我的代碼,因爲我不能使用實例方法.. 2)我有一個實例方法,它有很多文件處理程序..這些文件處理程序在子進程中被關閉是不可接受的。所以我需要再次打開它們。不幸的是,我沒有辦法知道它們,因爲它們是在實例化過程中傳遞的。 – kumar 2010-06-10 08:43:23

+0

它不一定是在單獨的進程中執行的轉換函數本身。有什麼辦法可以在單獨的進程中執行實例化部分?例如。編寫一個函數,甚至是一個單獨的腳本來完成單個實例化和轉換;然後編寫一個使用多處理模塊的「主腳本」來運行這些功能。單獨的腳本可以使用[subprocess](http://docs.python.org/library/subprocess.html)模塊運行。如果有很多共享數據,那麼是的,這就是多處理複雜化的地方。但是該模塊中有更多的工具:) – detly 2010-06-10 08:54:29

2

線程允許操作系統爲您的程序分配更多的CPU核心。如果它是I/O限制的,這意味着速度受I/O系統速度而不是CPU速度的限制。在這些情況下,分配更多CPU內核並不一定有幫助 - 您仍在等待I/O子系統。

+0

但我相信線程切換髮生在一個線程正在等待I/O subsyetm時,不是嗎?所以我現在正在做的事情,這意味着我可以期待一些性能改進? – kumar 2010-06-10 07:48:24

+5

Python中的線程不會爲程序分配更多的CPU內核。 – detly 2010-06-10 07:48:35

+0

@kumar:正如響應所述,如果您受I/O限制 - 您的I/O將盡其所能 - 更多的CPU時間或並行處理不會使I/O更早完成。 – Josh 2010-06-11 01:00:42