आप अपनी मेमोरी पदचिह्न को कम करने के लिए keys()
पर फिर से शुरू कर सकते हैं। आपको हटाए जाने वाले कुंजियों के खिलाफ सावधान रहना होगा।
अन्यथा, यहां दो अलग-अलग तरीकों से एक उदाहरण दिया गया है जो आपको एक ताना में वस्तुओं के माध्यम से फिर से शुरू करने देगा। इस उदाहरण में iteritems()
विधि केवल उस प्रक्रिया से कार्य करती है जो प्रबंधक ऑब्जेक्ट और प्रबंधक प्रक्रिया बनाता है जो कि बाल ऑब्जेक्ट बनाता है। ऐसा इसलिए है क्योंकि नए प्रॉक्सी बनाने के लिए प्रबंधक ऑब्जेक्ट की आवश्यकता होती है, और अन्य प्रक्रियाओं तक इसका उपयोग नहीं होता है। iteritems2()
विधि अन्य प्रक्रियाओं से काम करती है, क्योंकि यह उन प्रक्रियाओं में एक नई प्रॉक्सी बनाने पर भरोसा नहीं करती है।
import multiprocessing as mp
import multiprocessing.managers
class mydict(dict):
def __init__(self, *args, **kwargs):
dict.__init__(self, *args, **kwargs)
self.iters = {}
def iteritems(self):
print "iteritems", mp.current_process()
return dict.iteritems(self)
def _iteritems_start(self):
print "_iteritems_start", mp.current_process()
i = dict.iteritems(self)
self.iters[id(i)] = i
return id(i)
def _iteritems_next(self, iter_id):
try:
return self.iters[iter_id].next()
except StopIteration:
del self.iters[iter_id]
return None
class mydict_proxy(mp.managers.DictProxy):
def iteritems(self):
print "iteritems proxy", mp.current_process()
return self._callmethod("iteritems")
def iteritems2(self):
print "iteritems2 proxy", mp.current_process()
iter_id = self._callmethod("_iteritems_start")
def generator():
while True:
a = self._callmethod("_iteritems_next",
(iter_id,))
if a == None:
return
yield a
return generator()
_method_to_typeid_ = { "iteritems": "Iterator" }
_exposed_ = mp.managers.DictProxy._exposed_
_exposed_ += ("iteritems", "_iteritems_start", "_iteritems_next")
class mymanager(mp.managers.BaseManager):
pass
mymanager.register("mydict", mydict, mydict_proxy)
mymanager.register("Iterator", proxytype = mp.managers.IteratorProxy,
create_method = False)
def other(d):
for k, v in d.iteritems2():
d[k] = v.lower()
for k, v in d.iteritems():
d[k] = ord(v)
def main():
manager = mymanager()
manager.start()
d = manager.mydict(list(enumerate("ABCDEFGHIJKLMNOP")))
for (k, v) in d.iteritems():
print k, v
proc = mp.Process(target = other, args = (d,))
proc.start()
proc.join()
for (k, v) in d.iteritems():
print k, v
if __name__ == "__main__":
main()
ध्यान दें कि जब इस कोड को अधिक स्मृति कुशल हो सकता है, यह शायद बहुत धीमी की एक बिल्ली हो जा रहा है।
स्रोत
2014-07-14 04:00:03
क्या आपने 'SyncManager' का उपयोग करने के लिए विचार किया था और 'iteritems' के साथ अपनी खुद की प्रॉक्सी पंजीकृत की थी? – oleg
@oleg आप आसानी से iteritems का पर्दाफाश नहीं कर सकते हैं, क्योंकि यह निर्देश देने वाले निर्देशक नहीं हैं। यही कारण है कि डिफ़ॉल्ट dict प्रॉक्सी इसका खुलासा नहीं करता है और इसलिए सवाल है। – otus
मैंने "बस" खुलासा नहीं किया। :) क्या हम 'iteritems' का पर्दाफाश करने के लिए' IteratorProxy' का उपयोग कर सकते हैं? – oleg