कैसे चिंगारी निष्पादक संख्या, कोर और निष्पादक मेमोरी ट्यून करें?


84

आप उपर्युक्त पारामों की धुन कहाँ से शुरू करते हैं। क्या हम निष्पादक मेमोरी से शुरू करते हैं और निष्पादक की संख्या प्राप्त करते हैं, या हम कोर से शुरू करते हैं और निष्पादक संख्या प्राप्त करते हैं। मैंने लिंक का अनुसरण किया । हालांकि एक उच्च स्तरीय विचार मिला, लेकिन अभी भी यह सुनिश्चित नहीं है कि अंतिम निष्कर्ष पर कैसे और कहां से शुरू करें और कहां पहुंचें।

जवाबों:


209

निम्नलिखित उत्तर शीर्षक में उल्लिखित 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 ) -

अगर मुझे कुछ याद आया तो कृपया मुझे सुधारें। उपरोक्त मेरी समझ प्रश्न और कुछ ऑनलाइन संसाधनों में साझा किए गए ब्लॉग पर आधारित है। धन्यवाद।

संदर्भ:


2
मैंने कहीं पढ़ा कि स्टैंडअलोन मोड में प्रति नोड केवल एक निष्पादक है, उस पर कोई विचार? मैं इसे आपके उत्तर में शामिल नहीं देखता।
जंगोरकी

2
एक स्टैंडअलोन क्लस्टर में, डिफ़ॉल्ट रूप से हमें प्रति कार्यकर्ता एक निष्पादक मिलता है। हमें spark.executor.cores के साथ खेलने की आवश्यकता है और एक कार्यकर्ता के पास एक से अधिक निष्पादक प्राप्त करने के लिए पर्याप्त कोर है।
रामजी

मैंने पाया कि मेरे कार्यकर्ता को स्थापित किए बिना सभी 32 कोर का उपयोग करना है spark.executor.cores, इसलिए यह डिफ़ॉल्ट रूप से सभी उपलब्ध का उपयोग कर सकता है।
१२:१

हां, कोर के लिए डिफ़ॉल्ट अनंत है जैसा कि वे कहते हैं। जब तक आप निर्दिष्ट नहीं करते हैं तो स्पार्क सभी उपलब्ध कोर का उपयोग कर सकता है।
रामजी

2
@ रामजी मुझे लगता है कि यह भी ध्यान दिया जाना चाहिए कि गतिशील आवंटन के साथ, आपको अभी भी स्पार्क.सेक्स अभियोजक को निर्दिष्ट करना चाहिए। प्रत्येक निष्पादक का आकार निर्धारित करने के लिए जिसे स्पार्क आवंटित करने जा रहा है। अन्यथा, जब भी स्पार्क आपके एप्लिकेशन को एक नया निष्पादक आवंटित करने जा रहा है, यह एक संपूर्ण नोड (यदि उपलब्ध हो) आवंटित करने जा रहा है, भले ही आपको केवल पांच और कोर की आवश्यकता हो।
दान मार्शासिन

6

इसके अलावा, यह आपके उपयोग के मामले पर निर्भर करता है, एक महत्वपूर्ण कॉन्फ़िगरेशन पैरामीटर है:

spark.memory.fraction( Http://spark.apache.org/docs/latest/configuration.html#memory-management से (ढेर स्थान - 300 एमबी) निष्पादन और भंडारण के लिए उपयोग किया जाता है) ।

यदि आप कैश का उपयोग नहीं करते / करते हैं, तो इसे 0.1 पर सेट करें, ताकि आपके पास अपने प्रोग्राम की सभी मेमोरी हो।

यदि आप कैश का उपयोग करते हैं / जारी रखते हैं, तो आप द्वारा ली गई मेमोरी की जांच कर सकते हैं:

sc.getExecutorMemoryStatus.map(a => (a._2._1 - a._2._2)/(1024.0*1024*1024)).sum

क्या आप एचडीएफएस या HTTP से डेटा पढ़ते हैं?

फिर, एक ट्यूनिंग आपके उपयोग के मामले पर निर्भर करता है।


क्या आप जानते हैं कि pyspark का उपयोग करते समय मैप कमांड क्या दिखता है? मैं निष्पादक का दर्जा पाने के लिए sc._jsc.sc ()। GetExecutorMemoryStatus () का उपयोग करता हूं, लेकिन जो भी देता है उसके साथ कुछ नहीं कर सकता ...
थॉमस

1
क्षमा करें @Thomas Decaux , लेकिन क्या आपका मतलब सेटिंग है spark.memory.storageFraction=0.1? क्योंकि AFAIK निष्पादन और भंडारण दोनों के लिए spark.memory.fractionउपयोग की जाने वाली मेमोरी की मात्रा तय करता है (आपने पहले ही उल्लेख किया है) और केवल मेमोरी (जो स्टोरेज + निष्पादन के लिए उपलब्ध है) कैश बेदखली से प्रतिरक्षा है । कृपया इस लिंक को देखेंSparkspark.memory.storageFraction
y2k-shubham

@Thomas यदि मेरे आवेदन पर मेरे पास केवल इस विकल्प के साथ ही (StorageLevel.DISK_ONLY) मौजूद है तो क्या यह विकल्प लागू होगा? यह केवल स्मृति अंश को प्रभावित करता है, लेकिन किसी डिस्क स्पिल को प्रभावित नहीं करता है?
jk1
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.