निम्नलिखित उत्तर शीर्षक में उल्लिखित 3 मुख्य पहलुओं को शामिल करता है - निष्पादकों की संख्या, निष्पादक मेमोरी और कोर की संख्या। ड्राइवर मेमोरी और अन्य जैसे अन्य पैरामीटर हो सकते हैं जिन्हें मैंने इस उत्तर के रूप में संबोधित नहीं किया था, लेकिन निकट भविष्य में जोड़ना चाहूंगा।
केस 1 हार्डवेयर - 6 नोड्स, और प्रत्येक नोड 16 कोर, 64 जीबी रैम
प्रत्येक निष्पादक एक JVM उदाहरण है। तो हम एक एकल नोड में कई निष्पादक रख सकते हैं
OS और Hadoop Daemons के लिए पहले 1 कोर और 1 GB की आवश्यकता है, इसलिए प्रत्येक नोड के लिए 15 कोर, 63 GB RAM उपलब्ध हैं
कोर की संख्या का चयन कैसे करें के साथ शुरू करें :
Number of cores = Concurrent tasks as executor can run
So we might think, more concurrent tasks for each executor will give better performance. But research shows that
any application with more than 5 concurrent tasks, would lead to bad show. So stick this to 5.
This number came from the ability of executor and not from how many cores a system has. So the number 5 stays same
even if you have double(32) cores in the CPU.
निष्पादकों की संख्या:
Coming back to next step, with 5 as cores per executor, and 15 as total available cores in one Node(CPU) - we come to
3 executors per node.
So with 6 nodes, and 3 executors per node - we get 18 executors. Out of 18 we need 1 executor (java process) for AM in YARN we get 17 executors
This 17 is the number we give to spark using --num-executors while running from spark-submit shell command
प्रत्येक निष्पादक के लिए मेमोरी:
From above step, we have 3 executors per node. And available RAM is 63 GB
So memory for each executor is 63/3 = 21GB.
However small overhead memory is also needed to determine the full memory request to YARN for each executor.
Formula for that over head is max(384, .07 * spark.executor.memory)
Calculating that overhead - .07 * 21 (Here 21 is calculated as above 63/3)
= 1.47
Since 1.47 GB > 384 MB, the over head is 1.47.
Take the above from each 21 above => 21 - 1.47 ~ 19 GB
So executor memory - 19 GB
अंतिम संख्या - अभियोजक - 17, कोर 5, निष्पादन मेमोरी - 19 जीबी
केस 2 हार्डवेयर: समान 6 नोड, 32 करोड़, 64 जीबी
5 अच्छी संगति के लिए समान है
प्रत्येक नोड = 32/5 ~ 6 के लिए निष्पादकों की संख्या
तो कुल निष्पादक = 6 * 6 नोड्स = 36. तब अंतिम संख्या 36 = 1 पूर्वाह्न = 35 के लिए होती है
निष्पादक मेमोरी है: प्रत्येक नोड के लिए 6 निष्पादक। 63/6 ~ 10। ओवर हेड .07 * 10 = 700 एमबी है। इसलिए सिर के ऊपर 1GB तक गोलाई में, हमें 10-1 = 9 GB मिलते हैं
अंतिम संख्या - एक्जिक्यूटर्स - 35, कोर्स 5, एक्ज़ीक्यूटर मेमोरी - 9 जीबी
केस 3
उपरोक्त परिदृश्य तय संख्या के अनुसार कोर को स्वीकार करने और निष्पादनकर्ताओं और स्मृति के # पर जाने के साथ शुरू होते हैं।
अब पहले मामले में, अगर हमें लगता है कि हमें 19 जीबी की आवश्यकता नहीं है, और सिर्फ 10 जीबी पर्याप्त है, तो निम्नलिखित नंबर हैं:
प्रत्येक नोड = 3 के लिए निष्पादनकर्ताओं के 5 # कोर
इस स्तर पर, यह हमारी पहली गणना के अनुसार 21 और फिर 19 हो जाएगा। लेकिन जब से हमने सोचा कि 10 ठीक है (थोड़ा उपरि मान लें), तो हम # निष्पादकों के प्रति नोड 6 (जैसे 63/10) पर स्विच नहीं कर सकते। प्रति नोडल 6 निष्पादक और 5 कोर के साथ बने, यह घटकर 30 कोर प्रति नोड हो जाता है, जब हमारे पास केवल 16 कोर होते हैं। इसलिए हमें प्रत्येक निष्पादक के लिए कोर की संख्या बदलने की भी आवश्यकता है।
तो फिर से गणना,
मैजिक नंबर 5 3 पर आता है (कोई भी संख्या 5 से कम या उसके बराबर)। तो 3 कोर और 15 उपलब्ध कोर के साथ - हमें प्रति नोड 5 निष्पादक मिलते हैं। तो (5 * 6 -1) = 29 निष्पादक
तो मेमोरी 63/5 ~ 12. ओवर हेड है 12 * .07 = .84 तो एग्जीक्यूटोर मेमोरी 12 है - 1 जीबी = 11 जीबी
अंतिम संख्या 29 निष्पादक, 3 कोर, निष्पादक मेमोरी 11 जीबी है
गतिशील आवंटन:
नोट: यदि गतिशील आवंटन सक्षम है, तो निष्पादकों की संख्या के लिए ऊपरी बाध्य है। तो यह कहता है कि स्पार्क एप्लिकेशन जरूरत पड़ने पर सभी संसाधनों को खा सकता है। ऐसे क्लस्टर में जहां आपके पास अन्य एप्लिकेशन चल रहे हैं और उन्हें कार्यों को चलाने के लिए कोर की भी आवश्यकता है, कृपया सुनिश्चित करें कि आप इसे क्लस्टर स्तर पर करते हैं। मेरा मतलब है कि आप उपयोगकर्ता की पहुंच के आधार पर यार्न के लिए विशिष्ट संख्या को आवंटित कर सकते हैं। तो आप बना सकते हैं spark_user हो सकता है और फिर उस उपयोगकर्ता के लिए कोर (न्यूनतम / अधिकतम) दे सकते हैं। ये सीमाएं चिंगारी और अन्य अनुप्रयोगों के बीच साझा करने के लिए हैं जो YARN पर चलती हैं।
spark.dynamicAllocation.enabled - जब यह सही पर सेट होता है - हमें निष्पादकों का उल्लेख नहीं करना चाहिए। कारण नीचे है:
स्पार्क-सबमिट में हम जो स्टैटिक पेराम नंबर देते हैं, वह पूरी जॉब अवधि के लिए होता है। हालाँकि यदि गतिशील आवंटन चित्र में आता है, तो अलग-अलग चरण होंगे
क्या से शुरू करें:
आरंभ करने के लिए निष्पादकों की संख्या ( स्पार्क .dynamicAllocation.initialExecutors )
कितने :
फिर लोड (कार्यों लंबित) के आधार पर कितने अनुरोध करने हैं। यह अंतत: वह संख्या होगी जो हम स्पार्क-सबमिट में स्थैतिक तरीके से देते हैं। एक बार प्रारंभिक निष्पादक संख्या निर्धारित हो जाने के बाद, हम न्यूनतम ( स्पार्क.डायनामिकऑलोकेशन.मिन एक्सक्यूटर्स ) और अधिकतम ( स्पार्क.डायनामिक ऑलोकेशन.मैक्स एक्जेक्यूटर्स ) नंबरों पर जाते हैं।
कब मांगना या देना है:
जब हम नए निष्पादकों ( स्पार्क.डायनामिक ऑलोकेशन.स्क्रिड्यूलर बकलॉग टाइमआउट ) का अनुरोध करते हैं - इस अवधि के लिए लंबित कार्य हुए हैं। इतना निवेदन। प्रत्येक राउंड में अनुरोध किए गए निष्पादकों की संख्या पिछले राउंड से तेजी से बढ़ जाती है। उदाहरण के लिए, एक एप्लिकेशन पहले राउंड में 1 एग्ज़ामिनर को जोड़ेगा, और उसके बाद 2, 4, 8 और इसके बाद के राउंड्स में एग्ज़क्यूटर्स को। एक विशिष्ट बिंदु पर, उपरोक्त अधिकतम चित्र में आता है
जब ऐसा हम एक निष्पादक दे देना ( spark.dynamicAllocation.executorIdleTimeout ) -
अगर मुझे कुछ याद आया तो कृपया मुझे सुधारें। उपरोक्त मेरी समझ प्रश्न और कुछ ऑनलाइन संसाधनों में साझा किए गए ब्लॉग पर आधारित है। धन्यवाद।
संदर्भ: