2012-04-14 54 views
7

這個(大大簡化的例子)工作正常(的Python 2.6.6,Debian的擠壓):python多處理避免全球狀態擴散的替代使用模式?

from multiprocessing import Pool 
import numpy as np 

src=None 

def process(row): 
    return np.sum(src[row]) 

def main(): 
    global src 
    src=np.ones((100,100)) 

    pool=Pool(processes=16) 
    rows=pool.map(process,range(100)) 
    print rows 

if __name__ == "__main__": 
    main() 

然而,經過多年的被教導全局狀態不好的!,我所有的直覺告訴我,我真的寧願寫的東西更接近:

from multiprocessing import Pool 
import numpy as np 

def main(): 
    src=np.ones((100,100)) 

    def process(row): 
     return np.sum(src[row]) 

    pool=Pool(processes=16) 
    rows=pool.map(process,range(100)) 
    print rows 

if __name__ == "__main__": 
    main() 

當然,這並不工作,但(掛斷無法醃製的東西)。

這裏的例子很簡單,但是當你添加多個「進程」函數,並且每個函數都依賴於多個附加輸入......好吧,這一切都變得有點讓人聯想到30年前BASIC寫的東西。試圖使用類來至少聚合具有適當功能的狀態似乎是明顯的解決方案,但是在實踐中是doesn't seem to be that easy

是否有一些推薦的模式或風格使用multiprocessing.pool,這將避免全球狀態的擴散,以支持我想平行映射的每個功能?

經驗豐富的「多處理專業人員」如何處理這個問題?

更新:請注意,我在處理更大的陣列真正感興趣的,所以上述這些變化鹹菜src每個呼叫/迭代還不能像那些該叉入池的工作進程良好。

+0

我不是一個有經驗的多處理器Pro或什麼,但讓我問你你爲什麼不能只需執行pool.map(process,product([src],range(100)))並更改進程函數以接受兩個變量作爲參數?這是非常低效嗎? – luke14free 2012-04-14 09:36:03

+0

@ luke14free:是的,它會爲每次調用醃製src數組,而我實際上對比上面示例代碼中的數據/數組更大的數據/數組感興趣,所以不理想。通過進程池,無論在創建池時設置的任何狀態都被分入工作進程,並可供他們免費閱讀。這個想法有助於避免將更多次要的「控制變量」(例如標誌)狀態變爲全局變量,謝謝。 – timday 2012-04-14 09:48:52

回答

5

你總是可以傳遞一個可調用對象是這樣,那麼該對象可以containe共享狀態:

from multiprocessing import Pool 
import numpy as np 

class RowProcessor(object): 
    def __init__(self, src): 
     self.__src = src 
    def __call__(self, row): 
     return np.sum(self.__src[row]) 

def main(): 
    src=np.ones((100,100)) 
    p = RowProcessor(src) 

    pool=Pool(processes=16) 
    rows = pool.map(p, range(100)) 
    print rows 

if __name__ == "__main__": 
    main() 
+0

看起來有趣...會給這種風格嘗試並報告回... – timday 2012-04-14 09:54:57

+0

Yup非常好地工作,謝謝;再見全球。通常我會在接受解決方案之前等待更長的時間,看看是否有其他事情出現,但這是完美的。我曾經爲這個問題嘗試過課程,但沒有取得任何成功;似乎可調用使所有區別。 – timday 2012-04-14 10:31:59

+2

它不會醃製可調用的,你又回到了原點? – 2015-07-15 23:48:40