के बजाय एमपीपी का उपयोग करते समय पाइथन में समांतर अनुप्रयोग बहुत धीमा हो जाता है, मैंने हाल ही में एक अजीब प्रभाव देखा है जब मैंने मल्टीप्रोसेसिंग मॉड्यूल और mpi4py संचार उपकरण के रूप में अपने समांतर अनुप्रयोग के प्रदर्शन को माप लिया है।मल्टीप्रोसेसिंग मॉड्यूल
एप्लिकेशन डेटा के सेट पर विकासवादी एल्गोरिदम करता है। अधिकांश संचालन मूल्यांकन के अपवाद के साथ क्रमशः किया जाता है। सभी विकासवादी ऑपरेटरों को लागू करने के बाद सभी व्यक्तियों को नए फिटनेस मूल्य प्राप्त करने की आवश्यकता होती है, जो मूल्यांकन के दौरान किया जाता है। असल में यह केवल एक गणितीय गणना है जो फ्लोट्स (पायथन वाले) की सूची में किया जाता है। मूल्यांकन से पहले एक डेटा सेट एमपीआई के स्कैटर या पायथन के पूल.मैप द्वारा बिखरा हुआ है, फिर समांतर मूल्यांकन आता है और बाद में डेटा एमपीआई के इकट्ठा या फिर पूल.मैप तंत्र के माध्यम से वापस आता है।
मेरा बेंचमार्क प्लेटफार्म एक वर्चुअल मशीन (वर्चुअलबॉक्स) है जो कोर i7 (4/8 कोर), 8 जीबी रैम और एक एसएसडी ड्राइव पर ओपन एमपीआई 1.4.3 के साथ उबंटू 11.10 चला रहा है।
मुझे वास्तव में आश्चर्य की बात यह है कि मैं एक अच्छी गति प्राप्त करता हूं, हालांकि प्रक्रियाओं के एक निश्चित सीमा के बाद, एक संचार उपकरण के आधार पर, प्रदर्शन खराब हो जाता है। इसे नीचे दी गई तस्वीरों से सचित्र किया जा सकता है।
y अक्ष - प्रसंस्करण समय
एक्स अक्ष - (तैरता की एन.आर.) प्रत्येक व्यक्ति के आकार
1) बहु मॉड्यूल का उपयोग करना - - प्रक्रियाओं की एन.आर.
रंग Pool.map
2) एमपीआई का उपयोग करना - स्कैटर/इकट्ठा
3) एक दूसरे को
के शीर्ष पर दोनों चित्रों पहले मैं सोच रहा था कि यह हाइपरथ्रेडिंग की गलती है, क्योंकि बड़े डेटा सेट के लिए यह 4 प्रक्रियाओं (4 शारीरिक कोर) तक पहुंचने के बाद धीमी हो जाता है पर। हालांकि यह मल्टीप्रोसेसिंग मामले में भी दिखाना चाहिए और यह नहीं है। मेरा एक और अनुमान यह है कि एमपीआई संचार विधियां पाइथन की तुलना में बहुत कम प्रभावी हैं, हालांकि मुझे विश्वास करना मुश्किल लगता है।
क्या किसी के पास इन परिणामों के लिए कोई स्पष्टीकरण है?
जोड़ा:
मुझे विश्वास है कि यह सब के बाद Hyperthreading गलती है शुरू कर रहा हूँ। मैंने कोर i5 (2/4 कोर) वाली मशीन पर अपने कोड का परीक्षण किया और प्रदर्शन 3 या अधिक प्रक्रियाओं के साथ खराब है। मेरे दिमाग में आने वाला एकमात्र स्पष्टीकरण यह है कि i7 जिसका उपयोग मैं कर रहा हूं उसके पास हाइपरथ्रेडिंग के साथ समवर्ती रूप से मूल्यांकन की गणना करने के लिए पर्याप्त संसाधन (कैश?) नहीं हैं और 4 भौतिक कोरों पर चलाने के लिए 4 से अधिक प्रक्रियाओं को शेड्यूल करने की आवश्यकता है।
हालांकि दिलचस्प बात यह है कि, जब मैं mpi htop का उपयोग करता हूं तो सभी 8 लॉजिकल कोरों का पूर्ण उपयोग दिखाता है, जो सुझाव देना चाहिए कि उपर्युक्त कथन गलत है। दूसरी तरफ, जब मैं पूल.मैप का उपयोग करता हूं तो यह पूरी तरह से सभी कोर का उपयोग नहीं करता है। यह अधिकतम में एक या 2 का उपयोग करता है और बाकी केवल आंशिक रूप से, फिर से कोई विचार नहीं कि यह इस तरह से क्यों व्यवहार करता है। कल मैं इस व्यवहार को दिखाते हुए एक स्क्रीनशॉट संलग्न करूंगा।
मैं कुछ भी कोड में पसंद नहीं कर रहा हूँ, यह वास्तव में (नहीं है क्योंकि यह रहस्य है मैं पूरी कोड दे रही है नहीं कर रहा हूँ, लेकिन क्योंकि यह DEAP की तरह अतिरिक्त लाइब्रेरी की जरूरत है स्थापित होने के लिए। अगर किसी ने सच में रुचि रखता है सीधा है समस्या और डीईएपी स्थापित करने के लिए तैयार मैं एक छोटा उदाहरण तैयार कर सकते हैं)। एमपीआई के लिए कोड थोड़ा अलग है, क्योंकि यह जनसंख्या कंटेनर से निपट नहीं सकता है (जो सूची से प्राप्त होता है)। निश्चित रूप से कुछ ओवरहेड है, लेकिन कुछ भी बड़ा नहीं है। कोड के अलावा मैं नीचे दिखाता हूं, बाकी सब वही है।
Pool.map:
def eval_population(func, pop):
for ind in pop:
ind.fitness.values = func(ind)
return pop
# ...
self.pool = Pool(8)
# ...
for iter_ in xrange(nr_of_generations):
# ...
self.pool.map(evaluate, pop) # evaluate is really an eval_population alias with a certain function assigned to its first argument.
# ...
एमपीआई - स्कैटर/इकट्ठा
def divide_list(lst, n):
return [lst[i::n] for i in xrange(n)]
def chain_list(lst):
return list(chain.from_iterable(lst))
def evaluate_individuals_in_groups(func, rank, individuals):
comm = MPI.COMM_WORLD
size = MPI.COMM_WORLD.Get_size()
packages = None
if not rank:
packages = divide_list(individuals, size)
ind_for_eval = comm.scatter(packages)
eval_population(func, ind_for_eval)
pop_with_fit = comm.gather(ind_for_eval)
if not rank:
pop_with_fit = chain_list(pop_with_fit)
for index, elem in enumerate(pop_with_fit):
individuals[index] = elem
for iter_ in xrange(nr_of_generations):
# ...
evaluate_individuals_in_groups(self.func, self.rank, pop)
# ...
जोड़ा 2: कि मैंने पहले बताया मैं अपने i5 मशीन पर कुछ परीक्षण किए गए के रूप में (2/4 कोर) और यहां परिणाम है:
मैं भी 2 Xeons (2x 6/12 कोर) के साथ एक मशीन मिल गया है और बेंचमार्क दोहराया:
अब मैं एक ही व्यवहार के 3 उदाहरण है। जब मैं भौतिक कोर की तुलना में अधिक प्रक्रियाओं में अपनी गणना चलाता हूं तो यह और भी खराब हो जाता है। मेरा मानना है कि ऐसा इसलिए है क्योंकि संसाधनों की कमी के कारण एक ही भौतिक कोर की प्रक्रियाओं को समवर्ती रूप से निष्पादित नहीं किया जा सकता है।
एमपीआई कार्यान्वयन में आम तौर पर स्कैटर और इकट्ठा सामूहिक संचालन के लिए कई अलग-अलग एल्गोरिदम होते हैं। अधिकांश पुस्तकालयों में सर्वश्रेष्ठ एल्गोरिदम का चयन करने के लिए स्वयं का हेरिस्टिक्स होता है लेकिन कभी-कभी यह विफल हो जाता है। कुछ पुस्तकालय इन एल्गोरिदम को मजबूर करने की अनुमति देते हैं, उदा। ओपन एमपीआई में यह एमसीए तर्कों को 'mpiexec' में पास करके हासिल किया जा सकता है। यदि आप हमें बताएंगे कि आप किस एमपीआई कार्यान्वयन का उपयोग करते हैं तो इससे मदद मिलेगी। –
मैं ओपन एमपीआई का उपयोग करता हूं, प्रश्न में जोड़ा गया। – Michal
यदि आप अधिक संदर्भ प्रदान कर सकते हैं तो यह बहुत अच्छा होगा, उदाहरण के लिए कोड के उन हिस्सों को दिखाएं जहां डेटा वितरित किया जा रहा है (दोनों कार्यान्वयन)। आम तौर पर स्कैटर और ओपन एमपीआई स्केल में प्रक्रियाओं की संख्या के साथ बहुत अच्छी तरह से इकट्ठा होते हैं जब वे सभी एक नोड पर चल रहे होते हैं। –