2017-09-05 77 views
5

有什麼區別ThreadPoolPool 模塊之間的區別是什麼。當我嘗試我的代碼了,這是我看到的主要區別:ThreadPool與Python之間的Python多處理模塊

from multiprocessing import Pool 
import os, time 

print("hi outside of main()") 

def hello(x): 
    print("inside hello()") 
    print("Proccess id: ", os.getpid()) 
    time.sleep(3) 
    return x*x 

if __name__ == "__main__": 
    p = Pool(5) 
    pool_output = p.map(hello, range(3)) 

    print(pool_output) 

我看到下面的輸出:

hi outside of main() 
hi outside of main() 
hi outside of main() 
hi outside of main() 
hi outside of main() 
hi outside of main() 
inside hello() 
Proccess id: 13268 
inside hello() 
Proccess id: 11104 
inside hello() 
Proccess id: 13064 
[0, 1, 4] 

隨着 「線程池」:

from multiprocessing.pool import ThreadPool 
import os, time 

print("hi outside of main()") 

def hello(x): 
    print("inside hello()") 
    print("Proccess id: ", os.getpid()) 
    time.sleep(3) 
    return x*x 

if __name__ == "__main__": 
    p = ThreadPool(5) 
    pool_output = p.map(hello, range(3)) 

    print(pool_output) 

我看到了以下的輸出:

hi outside of main() 
inside hello() 
inside hello() 
Proccess id: 15204 
Proccess id: 15204 
inside hello() 
Proccess id: 15204 
[0, 1, 4] 

我的疑問句系統蒸發散:

  • 爲什麼「外__main __()」運行在Pool每一次?

  • multiprocessing.pool.ThreadPool不產生新的進程?它只是創建新的線程?

  • 如果是這樣,使用multiprocessing.pool.ThreadPool而不僅僅是threading模塊之間的區別是什麼?

我沒有看到任何正式的文檔,隨時隨地ThreadPool,有人可以幫助我在哪裏可以找到它?

+0

據我所知,由於Python中的GIL,Python的多線程看起來像多線程,但它不是真實的。如果你想利用Python的多核心,你需要使用多處理。在現代計算機中,創建進程和創建線程的成本幾乎相同。 – Yves

+0

創建線程可能與創建進程的成本相似,但線程之間的通信與進程之間的通信的成本差別很大(除非可能使用共享內存)。此外,您對GIL的評論僅部分爲真:它在I/O操作期間以及由某些庫(例如numpy)發佈,即使在CPU限制操作期間也是如此。儘管如此,GIL最終是在Python中使用單獨進程的原因。 –

回答

5

multiprocessing.pool.ThreadPool的行爲與multiprocessing.Pool的行爲相同,唯一的區別是使用線程而不是進程來運行工作邏輯。

的原因,你看到

hi outside of main() 

被打印多次與multiprocessing.Pool是由於這樣的事實,游泳池將於spawn 5個獨立的進程。每個進程將初始化自己的Python解釋器並加載模塊,導致頂層print被再次執行。

請注意,只有在使用spawn進程創建方法(僅適用於Windows的方法)時纔會發生這種情況。如果你使用的是一個Unix(Unix),你會看到只有一個線程打印的消息。

multiprocessing.pool.ThreadPool沒有記錄,因爲它的實現從未完成。它缺少測試和文檔。你可以在source code看到它的實現。

我相信下一個自然的問題是:何時使用基於線程的池以及何時使用基於進程的池?

經驗法則是:

  • IO綁定作業 - >multiprocessing.pool.ThreadPool
  • CPU綁定作業 - >multiprocessing.Pool
  • 混合作業 - >取決於工作負載,我通常喜歡multiprocessing.Pool因在利益處理隔離帶來

在Python 3裏,你可能想看看concurrent.future.Executor池實現。

+0

感謝您的回答。我只是想了解這個聲明: 請注意,只有在使用產卵進程創建方法時纔會發生這種情況(只有在Windows上可用的方法)。如果您使用fork one(Unix),則會看到該消息僅針對線程打印一次。 我假設,當我調用「map()」或「Pool()」時,「spawn」和「fork」是隱含的?或者這是我可以控制的東西? – ozn

+0

解釋是在我提到[spawn](https://docs.python.org/3.6/library/multiprocessing.html#contexts-and-start-methods)啓動方法時,上面給出的鏈接。您可以控制它,但啓動方法的可用性取決於操作系統平臺。我假設你使用Windows作爲默認的開始策略是'spawn'。如果是這樣,由於Windows只支持'spawn',所以沒有什麼可做的。 – noxdafox