2012-02-13 13 views
7

बस प्रयोग और सीखना, और मुझे पता है कि एक साझा शब्दकोश कैसे बनाया जाए जिसे एकाधिक प्रोसेस के साथ एक्सेस किया जा सके लेकिन मुझे यकीन नहीं है कि कैसे निर्देशित किया जाए। defaultdict, मुझे विश्वास है, मेरी समस्या का वर्णन करता है।मल्टीप्रोसेसिंग के साथ डिफ़ॉल्ट डिक्ट का उपयोग करना?

from collections import defaultdict 
from multiprocessing import Pool, Manager, Process 

#test without multiprocessing 
s = 'mississippi' 
d = defaultdict(int) 
for k in s: 
    d[k] += 1 

print d.items() # Success! result: [('i', 4), ('p', 2), ('s', 4), ('m', 1)] 
print '*'*10, ' with multiprocessing ', '*'*10 

def test(k, multi_dict): 
    multi_dict[k] += 1 

if __name__ == '__main__': 
    pool = Pool(processes=4) 
    mgr = Manager() 
    multi_d = mgr.dict() 
    for k in s: 
     pool.apply_async(test, (k, multi_d)) 

    # Mark pool as closed -- no more tasks can be added. 
    pool.close() 

    # Wait for tasks to exit 
    pool.join() 

    # Output results 
    print multi_d.items() #FAIL 

print '*'*10, ' with multiprocessing and process module like on python site example', '*'*10 
def test2(k, multi_dict2): 
    multi_dict2[k] += 1 


if __name__ == '__main__': 
    manager = Manager() 

    multi_d2 = manager.dict() 
    for k in s: 
     p = Process(target=test2, args=(k, multi_d2)) 
    p.start() 
    p.join() 

    print multi_d2 #FAIL 

(क्योंकि इसके multiprocessing का उपयोग नहीं), लेकिन मैं समस्याओं इसे प्राप्त करने multiprocessing के साथ काम करने आ रही हैं पहला परिणाम काम करता है। मुझे यकीन नहीं है कि इसे कैसे हल किया जाए, लेकिन मुझे लगता है कि इसे सिंक नहीं किया जा सकता है (और बाद में परिणामों में शामिल हो रहा है) या शायद क्योंकि multiprocessing के भीतर मैं यह नहीं समझ सकता कि defaultdict(int) को शब्दकोश में कैसे सेट करें।

काम करने के तरीके के बारे में कोई मदद या सुझाव बहुत अच्छा होगा!

उत्तर

10

आप BaseManager उपवर्ग और साझा करने के लिए अतिरिक्त प्रकार रजिस्टर कर सकते हैं। आपको उन मामलों में उपयुक्त प्रॉक्सी प्रकार प्रदान करने की आवश्यकता है जहां डिफ़ॉल्ट AutoProxy-जनरेटेड प्रकार काम नहीं करता है। defaultdict के लिए, यदि आपको केवल उन गुणों तक पहुंचने की आवश्यकता है जो dict में पहले से मौजूद हैं, तो आप DictProxy का उपयोग कर सकते हैं।

from multiprocessing import Pool 
from multiprocessing.managers import BaseManager, DictProxy 
from collections import defaultdict 

class MyManager(BaseManager): 
    pass 

MyManager.register('defaultdict', defaultdict, DictProxy) 

def test(k, multi_dict): 
    multi_dict[k] += 1 

if __name__ == '__main__': 
    pool = Pool(processes=4) 
    mgr = MyManager() 
    mgr.start() 
    multi_d = mgr.defaultdict(int) 
    for k in 'mississippi': 
     pool.apply_async(test, (k, multi_d)) 
    pool.close() 
    pool.join() 
    print multi_d.items() 
+1

वाह, यह काम करता है, धन्यवाद। मैं वास्तव में आपके संशोधनों को समझ नहीं पा रहा हूं, क्लास माईमैनेजर (बेसमेनगर) का उद्देश्य क्या है? – Lostsoul

+0

@Lostsoul यह [दस्तावेज तरीका] है (http://docs.python.org/library/multiprocessing.html#customized-managers) जो प्रबंधक समर्थन करता है उससे अन्य प्रकारों को साझा करने के लिए समर्थन जोड़ने के लिए। –

+0

आपको बहुत बहुत धन्यवाद, मैं इसका अध्ययन करूंगा! – Lostsoul

2

ठीक है, Manager कक्षा केवल पूर्वनिर्धारित डेटा संरचनाओं की एक निश्चित संख्या की आपूर्ति करने लगती है जिसे प्रक्रियाओं के बीच साझा किया जा सकता है, और defaultdict उनमें से नहीं है। आप वास्तव में सिर्फ जरूरत है कि एक defaultdict, सबसे आसान समाधान अपने दम पर दोषी व्यवहार लागू करने के लिए होगा:

def test(k, multi_dict): 
    if k not in multi_dict: 
     multi_dict[k] = 0 
    multi_dict[k] += 1 
संबंधित मुद्दे