में भारी, ब्रूट फोर्स अधिकतमकरण के कुशल मल्टीप्रोसेसिंग यह मेरे हालिया प्रश्न Avoiding race conditions in Python 3's multiprocessing Queues का विस्तार है। उम्मीद है कि प्रश्न का यह संस्करण अधिक विशिष्ट है।पाइथन 3
टीएल; डीआर: एक मल्टीप्रोसेसिंग मॉडल में जहां multiprocessing.Queue
का उपयोग कर कार्यकर्ता प्रक्रियाओं को कतार से खिलाया जाता है, तो मेरे कार्यकर्ता इतने निष्क्रिय क्यों होते हैं? प्रत्येक प्रक्रिया में अपनी स्वयं की इनपुट कतार होती है ताकि वे एक साझा कतार के लॉक के लिए एक-दूसरे से लड़ नहीं रहे हों, लेकिन कतार वास्तव में बहुत खाली समय बिताती हैं। मुख्य प्रक्रिया आई/ओ-बाउंड थ्रेड चला रही है - क्या यह इनपुट कतारों के सीपीयू-बाउंड भरने को धीमा कर रहा है?
मैं एक निश्चित बाधा के तहत एम_आई तत्वों (= i < एन) के साथ प्रत्येक सेट के कार्टेशियन उत्पाद का अधिकतम तत्व खोजने की कोशिश कर रहा हूं। याद रखें कि कार्टेशियन उत्पाद के तत्व लंबाई-एन tuples हैं जिनके तत्व एन सेट के तत्व हैं। मैं इन tuples 'संयोजन' को इस तथ्य पर जोर देने के लिए बुलाऊंगा कि मैं मूल सेट के हर संयोजन पर लूप कर रहा हूं। जब मेरा फ़ंक्शन is_feasible
True
देता है तो एक संयोजन बाधा को पूरा करता है। मेरी समस्या में, मैं उस संयोजन को खोजने की कोशिश कर रहा हूं जिसके तत्वों का सबसे बड़ा वजन है: sum(element.weight for element in combination)
।
मेरी समस्या का आकार बड़ा है, लेकिन मेरी कंपनी का सर्वर भी है। मैं समांतर एल्गोरिदम के रूप में निम्नलिखित सीरियल एल्गोरिदम को फिर से लिखने की कोशिश कर रहा हूं।
from operator import itemgetter
from itertools import product # Cartesian product function from the std lib
def optimize(sets):
"""Return the largest (total-weight, combination) tuple from all
possible combinations of the elements in the several sets, subject
to the constraint that is_feasible(combo) returns True."""
return max(
map(
lambda combination: (
sum(element.weight for element in combination),
combination
),
filter(
is_feasible, # Returns True if combo meets constraint
product(*sets)
)
),
key=itemgetter(0) # Only maximize based on sum of weight
)
मेरे वर्तमान बहु दृष्टिकोण कार्यकर्ता प्रक्रियाओं बनाने और उन्हें एक इनपुट कतार के साथ संयोजन को खिलाने के लिए है। जब श्रमिक poison pill प्राप्त करते हैं तो वे आउटपुट कतार और बाहर निकलने पर सबसे अच्छा संयोजन डालते हैं। मैं मुख्य प्रक्रिया के मुख्य धागे से इनपुट कतार भरता हूं। इस तकनीक का एक फायदा यह है कि मैं मुख्य प्रक्रिया से एक माध्यमिक थ्रेड को एक निगरानी उपकरण चलाने के लिए प्रेरित कर सकता हूं (केवल एक आरपीएल मैं यह देखने के लिए उपयोग कर सकता हूं कि अब तक कितने संयोजन संसाधित किए गए हैं और कतार कितनी पूर्ण हैं)।
+-----------+
in_q0 | worker0 |----\
/-------+-----------+ \
+-----------+ in_q1 +-----------+ \ out_q +-----------+
| main |-----------| worker1 |-----------| main |
+-----------+ +-----------+/ +-----------+
\-------+-----------+ /
in_q2 | worker2 |----/
+-----------+
मैं मूल रूप से सभी कर्मचारियों को एक इनपुट कतार से पढ़ने था, लेकिन पाया गया कि उनमें से कोई भी सीपीयू मार रहे थे। यह पता लगाना कि वे अपने पूरे समय queue.get() को अनवरोधित करने के लिए इंतजार कर रहे थे, मैंने उन्हें अपनी कतार दी। उस सीपीयू पर दबाव बढ़ गया, इसलिए मैंने पाया कि मजदूर अक्सर सक्रिय थे। हालांकि, कतारें अपना अधिकांश समय खाली खर्च करती हैं! (मैं इसे उल्लिखित निगरानी आरपीएल से जानता हूं)। यह मुझे बताता है कि कतार भरने वाला मुख्य पाश धीमा है।
from itertools import cycle
main():
# (Create workers, each with its own input queue)
# Cycle through each worker's queue and add a combination to that queue
for combo, worker in zip(product(*sets), cycle(workers)):
worker.in_q.put(combo)
# (Collect results and return)
मेरा अनुमान है कि टोंटी worker.in_q.put()
है: यहाँ है कि पाश है। मैं इसे तेज़ी से कैसे बना सकता हूं? मेरा पहला वृत्ति श्रमिकों को धीमा करना था, लेकिन यह समझ में नहीं आता ... क्या समस्या है कि मॉनिटर थ्रेड लूप को अक्सर रोक रहा है? मैं कैसे बताने में सक्षम होगा?
वैकल्पिक रूप से, क्या इसे लागू करने का एक और तरीका है जिसमें ताले पर इतनी प्रतीक्षा नहीं है?
मैं _think_ मैं देख रहा हूं कि आप क्या कह रहे हैं और यदि ऐसा है तो बहुत सारी पुनर्लेखन की आवश्यकता होगी। आपके पास निश्चित रूप से मेरे लगातार 'डंपिंग' और तत्वों को लोड करने के बारे में एक बिंदु है (जो 'संग्रह। काउंटर' के उप-वर्ग के उदाहरण हैं)। अगर मैं _pre_-pickled उन्हें मदद मिलेगी? उदाहरण के लिए, 'मुख्य' में 'लूप' से पहले, 'set_of_pickles = map (lambda s: map (डंप, एस), सेट) की एक पंक्ति है,' – wkschwartz
जो शायद कुछ हद तक मदद करेगी: यह पिकलिंग लागतों पर बचत करेगी , लेकिन आप अभी भी प्रति कर्मचारी केवल एक बार के बजाय आईपीसी के माध्यम से मसालेदार तारों को प्रसारित कर रहे होंगे। – Dougal