我遇到了python多處理Pool類的一些意外行爲。multiprocessing.pool上下文和負載平衡
這裏是我的問題:
1)Pool是什麼時候創建了它的上下文,後來用於序列化?
只要在Container定義之後創建Pool對象,下面的示例就會正常運行。如果您交換池初始化,則會發生序列化錯誤。在我的生產代碼中,我想在定義容器類之前初始化Pool方式。是否可以刷新池「上下文」或以另一種方式實現此目的。
2)池是否有自己的負載均衡機制,如果有的話它是如何工作的?
如果我在我的i7機器上運行一個類似的例子,其中包含8個進程的池,我會得到以下結果:
- 對於輕評估函數池支持僅使用一個進程進行計算。它按要求創建了8個進程,但在大多數情況下只有一個被使用(我從內部打印了pid,並在htop中看到了這一點)。
- 對於繁重的評估功能,行爲與預期相同。它同樣使用所有8個流程。
3)當使用池時,我總是看到4個更多的進程,我要求(即池(進程= 2),我看到6個新進程)。他們的角色是什麼?
我使用Linux與Python 2.7.2
from multiprocessing import Pool
from datetime import datetime
POWER = 10
def eval_power(container):
for power in xrange(2, POWER):
container.val **= power
return container
#processes = Pool(processes=2)
class Container(object):
def __init__(self, value):
self.val = value
processes = Pool(processes=2)
if __name__ == "__main__":
cont = [Container(foo) for foo in xrange(20)]
then = datetime.now()
processes.map(eval_power, cont)
now = datetime.now()
print "Eval time:", now - then
編輯 - BAKURIU
1)我怕是這種情況。
2)我不明白什麼Linux調度程序必須做與python分配計算進程。我的情況可以通過下面的例子ilustrated:
from multiprocessing import Pool
from os import getpid
from collections import Counter
def light_func(ind):
return getpid()
def heavy_func(ind):
for foo in xrange(1000000):
ind += foo
return getpid()
if __name__ == "__main__":
list_ = range(100)
pool = Pool(4)
l_func = pool.map(light_func, list_)
h_func = pool.map(heavy_func, list_)
print "light func:", Counter(l_func)
print "heavy func:", Counter(h_func)
在我的酷睿i5的機器(4個線程)我得到以下結果:
光FUNC:計數器({2967:100})
重FUNC :計數器({2969:28,2967:28,2968:23,2970:21})
看來情況與我描述的一樣。但是我仍然不明白爲什麼python會這樣做。我的猜測是,它會盡量減少通信費用,但仍然不知道它用於負載平衡的機制。文檔也不是很有幫助,多處理模塊記錄很差。
3)如果我運行上面的代碼,我得到4個更多的過程,如前所述。屏幕來自HTOP:http://i.stack.imgur.com/PldmM.png
我已在編輯部分回答了您的問題。 – Michal 2013-04-21 14:43:52
@Michal我已經擴大了我對第2點的回答。關於第3點,我不知道。你是否試圖殺死其中一個子流程並看看會發生什麼?也許從你得到的錯誤中我們可以猜出它的用途(即使我的機器上沒有額外的進程,正如我所說的)。 – Bakuriu 2013-04-21 15:37:14