अवलोकन
यह मार्गदर्शिका आपको बताएगी कि अपने GPU में अंतर्दृष्टि प्राप्त करने और अधिकतम प्रदर्शन प्राप्त करने के लिए TensorBoard के साथ TensorFlow Profiler का उपयोग कैसे करें, और जब आपके एक या अधिक GPU का उपयोग कम हो जाए तो डीबग करें।
यदि आप प्रोफाइलर के लिए नए हैं:
- TensorFlow Profiler के साथ आरंभ करें: एक Keras उदाहरण और TensorBoard के साथ प्रोफ़ाइल मॉडल प्रदर्शन नोटबुक।
- प्रोइलर गाइड का उपयोग करके ऑप्टिमाइज़ टेंसरफ्लो प्रदर्शन के साथ होस्ट (सीपीयू) पर TensorFlow प्रदर्शन को अनुकूलित करने के लिए उपलब्ध विभिन्न प्रोफाइलिंग टूल और विधियों के बारे में जानें।
ध्यान रखें कि GPU को ऑफ़लोडिंग कंप्यूटेशंस हमेशा फायदेमंद नहीं हो सकता है, खासकर छोटे मॉडल के लिए। इसके कारण ओवरहेड हो सकता है:
- होस्ट (सीपीयू) और डिवाइस (जीपीयू) के बीच डेटा ट्रांसफर; तथा
- विलंबता शामिल होने के कारण जब होस्ट GPU कर्नेल लॉन्च करता है।
प्रदर्शन अनुकूलन कार्यप्रवाह
यह मार्गदर्शिका बताती है कि एकल GPU से शुरू होने वाली प्रदर्शन समस्याओं को कैसे डिबग करना है, फिर एकाधिक GPU के साथ एकल होस्ट पर जाना है।
निम्नलिखित क्रम में प्रदर्शन समस्याओं को डीबग करने की अनुशंसा की जाती है:
- एक GPU पर प्रदर्शन को ऑप्टिमाइज़ और डीबग करें:
- जांचें कि क्या इनपुट पाइपलाइन एक अड़चन है।
- एक GPU के प्रदर्शन को डीबग करें।
- मिश्रित परिशुद्धता सक्षम करें (
fp16
(float16) के साथ) और वैकल्पिक रूप से XLA सक्षम करें।
- मल्टी-जीपीयू सिंगल होस्ट पर प्रदर्शन को ऑप्टिमाइज़ और डीबग करें।
उदाहरण के लिए, यदि आप कई GPU के साथ एकल होस्ट पर एक मॉडल को प्रशिक्षित करने के लिए TensorFlow वितरण रणनीति का उपयोग कर रहे हैं और उप-अनुकूल GPU उपयोग को नोटिस करते हैं, तो आपको पहले मल्टी-GPU सिस्टम को डीबग करने से पहले एक GPU के प्रदर्शन को अनुकूलित और डीबग करना चाहिए।
GPU पर निष्पादक कोड प्राप्त करने के लिए आधार रेखा के रूप में, यह मार्गदर्शिका मानती है कि आप पहले से ही tf.function
का उपयोग कर रहे हैं। Model.compile
और Model.fit
API स्वचालित रूप से हुड के तहत tf.function
का उपयोग करेंगे। tf.GradientTape
के साथ एक कस्टम प्रशिक्षण लूप लिखते समय, tf.function
s को सक्षम करने के तरीके पर tf.function के साथ बेहतर प्रदर्शन देखें।
अगले खंड प्रदर्शन बाधाओं को पहचानने और ठीक करने में मदद करने के लिए उपरोक्त प्रत्येक परिदृश्य के लिए सुझाए गए दृष्टिकोणों पर चर्चा करते हैं।
1. एक GPU पर प्रदर्शन का अनुकूलन करें
एक आदर्श मामले में, आपके प्रोग्राम में उच्च GPU उपयोग, न्यूनतम CPU (होस्ट) से GPU (डिवाइस) संचार होना चाहिए, और इनपुट पाइपलाइन से कोई ओवरहेड नहीं होना चाहिए।
प्रदर्शन का विश्लेषण करने में पहला कदम एक GPU के साथ चलने वाले मॉडल के लिए एक प्रोफ़ाइल प्राप्त करना है।
TensorBoard का Profiler सिंहावलोकन पृष्ठ - जो एक शीर्ष स्तर का दृश्य दिखाता है कि आपके मॉडल ने प्रोफ़ाइल चलाने के दौरान कैसा प्रदर्शन किया है - यह एक विचार प्रदान कर सकता है कि आपका प्रोग्राम आदर्श परिदृश्य से कितनी दूर है।
सिंहावलोकन पृष्ठ पर ध्यान देने के लिए प्रमुख संख्याएँ हैं:
- वास्तविक डिवाइस निष्पादन से कितना चरण समय है
- डिवाइस बनाम होस्ट पर रखे गए ऑप्स का प्रतिशत
- कितने गुठली
fp16
का उपयोग करते हैं
इष्टतम प्रदर्शन प्राप्त करने का अर्थ है इन तीनों मामलों में इन संख्याओं को अधिकतम करना। अपने प्रोग्राम को गहराई से समझने के लिए, आपको TensorBoard के Profiler ट्रेस व्यूअर से परिचित होना होगा। नीचे दिए गए अनुभाग कुछ सामान्य ट्रेस व्यूअर पैटर्न दिखाते हैं जिन्हें आपको प्रदर्शन बाधाओं का निदान करते समय देखना चाहिए।
नीचे एक GPU पर चल रहे मॉडल ट्रेस व्यू की एक छवि है। TensorFlow Name Scope और TensorFlow Ops सेक्शन से, आप मॉडल के विभिन्न हिस्सों की पहचान कर सकते हैं, जैसे फॉरवर्ड पास, लॉस फंक्शन, बैकवर्ड पास/ग्रेडिएंट कैलकुलेशन और ऑप्टिमाइज़र वेट अपडेट। आप प्रत्येक स्ट्रीम के आगे GPU पर भी ऑप्स चला सकते हैं, जो CUDA स्ट्रीम को संदर्भित करता है। प्रत्येक स्ट्रीम का उपयोग विशिष्ट कार्यों के लिए किया जाता है। इस ट्रेस में, Stream#118 का उपयोग कंप्यूट कर्नेल और डिवाइस-टू-डिवाइस कॉपी लॉन्च करने के लिए किया जाता है। स्ट्रीम#119 का उपयोग होस्ट-टू-डिवाइस कॉपी के लिए और स्ट्रीम#120 डिवाइस से होस्ट कॉपी के लिए किया जाता है।
नीचे दिया गया ट्रेस एक निष्पादक मॉडल की सामान्य विशेषताओं को दर्शाता है।
उदाहरण के लिए, GPU कंप्यूट टाइमलाइन ( Stream#118 ) बहुत कम अंतराल के साथ "व्यस्त" दिखता है। होस्ट से डिवाइस ( स्ट्रीम #119 ) और डिवाइस से होस्ट ( स्ट्रीम #120 ) तक न्यूनतम प्रतियां हैं, साथ ही चरणों के बीच न्यूनतम अंतराल भी हैं। जब आप अपने प्रोग्राम के लिए प्रोफाइलर चलाते हैं, तो हो सकता है कि आप अपने ट्रेस व्यू में इन आदर्श विशेषताओं की पहचान करने में सक्षम न हों। इस गाइड के बाकी हिस्सों में सामान्य परिदृश्य शामिल हैं और उन्हें कैसे ठीक किया जाए।
1. इनपुट पाइपलाइन डीबग करें
GPU प्रदर्शन डिबगिंग में पहला कदम यह निर्धारित करना है कि आपका प्रोग्राम इनपुट-बाउंड है या नहीं। इसका पता लगाने का सबसे आसान तरीका टेंसरबोर्ड पर प्रोफाइलर के इनपुट-पाइपलाइन विश्लेषक का उपयोग करना है, जो इनपुट पाइपलाइन में बिताए गए समय का अवलोकन प्रदान करता है।
यदि आपकी इनपुट-पाइपलाइन चरणबद्ध समय में महत्वपूर्ण योगदान देती है तो आप निम्नलिखित संभावित कार्रवाई कर सकते हैं:
- अपनी इनपुट पाइपलाइन को डीबग करने का तरीका जानने के लिए आप
tf.data
-विशिष्ट मार्गदर्शिका का उपयोग कर सकते हैं। - यह जांचने का एक और त्वरित तरीका है कि क्या इनपुट पाइपलाइन अड़चन है, बेतरतीब ढंग से उत्पन्न इनपुट डेटा का उपयोग करना है जिसे किसी पूर्व-प्रसंस्करण की आवश्यकता नहीं है। यहाँ एक ResNet मॉडल के लिए इस तकनीक का उपयोग करने का एक उदाहरण दिया गया है। यदि इनपुट पाइपलाइन इष्टतम है, तो आपको वास्तविक डेटा और जेनरेट किए गए यादृच्छिक/सिंथेटिक डेटा के साथ समान प्रदर्शन का अनुभव करना चाहिए। सिंथेटिक डेटा मामले में एकमात्र ओवरहेड इनपुट डेटा कॉपी के कारण होगा जिसे फिर से प्रीफ़ेच और अनुकूलित किया जा सकता है।
इसके अलावा, इनपुट डेटा पाइपलाइन के अनुकूलन के लिए सर्वोत्तम प्रथाओं का संदर्भ लें।
2. एक GPU के प्रदर्शन को डीबग करें
ऐसे कई कारक हैं जो कम GPU उपयोग में योगदान कर सकते हैं। ट्रेस व्यूअर और संभावित समाधानों को देखते समय आमतौर पर देखे जाने वाले कुछ परिदृश्य नीचे दिए गए हैं।
1. चरणों के बीच अंतराल का विश्लेषण करें
जब आपका प्रोग्राम बेहतर तरीके से नहीं चल रहा होता है तो एक सामान्य अवलोकन प्रशिक्षण चरणों के बीच अंतराल होता है। नीचे दिए गए ट्रेस दृश्य की छवि में, चरण 8 और 9 के बीच एक बड़ा अंतर है, जिसका अर्थ है कि उस समय के दौरान GPU निष्क्रिय है।
यदि आपका ट्रेस व्यूअर चरणों के बीच बड़े अंतराल दिखाता है, तो यह इस बात का संकेत हो सकता है कि आपका प्रोग्राम इनपुट बाउंड है। उस स्थिति में यदि आपने पहले से ऐसा नहीं किया है तो आपको अपनी इनपुट पाइपलाइन डीबग करने पर पिछले अनुभाग का संदर्भ लेना चाहिए।
हालांकि, एक अनुकूलित इनपुट पाइपलाइन के साथ भी, सीपीयू थ्रेड विवाद के कारण आप अभी भी एक चरण के अंत और दूसरे की शुरुआत के बीच अंतराल प्राप्त कर सकते हैं। tf.data
पाइपलाइन प्रोसेसिंग को समानांतर करने के लिए बैकग्राउंड थ्रेड्स का उपयोग करता है। ये थ्रेड प्रत्येक चरण की शुरुआत में होने वाली GPU होस्ट-साइड गतिविधि में हस्तक्षेप कर सकते हैं, जैसे डेटा की प्रतिलिपि बनाना या GPU संचालन शेड्यूल करना।
यदि आप मेजबान पक्ष पर बड़े अंतराल देखते हैं, जो GPU पर इन ऑप्स को शेड्यूल करता है, तो आप पर्यावरण चर TF_GPU_THREAD_MODE=gpu_private
सेट कर सकते हैं। यह सुनिश्चित करता है कि GPU कर्नेल अपने स्वयं के समर्पित थ्रेड्स से लॉन्च किए गए हैं, और tf.data
कार्य के पीछे कतारबद्ध नहीं हैं।
चरणों के बीच अंतराल मीट्रिक गणना, केरस कॉलबैक, या होस्ट पर चलने वाले tf.function
के बाहर के ऑप्स के कारण भी हो सकता है। इन ऑप्स का प्रदर्शन उतना अच्छा नहीं है जितना कि TensorFlow ग्राफ़ के अंदर ऑप्स का। इसके अतिरिक्त, इनमें से कुछ ऑप सीपीयू पर चलते हैं और जीपीयू से आगे और पीछे टेंसर कॉपी करते हैं।
यदि अपनी इनपुट पाइपलाइन को ऑप्टिमाइज़ करने के बाद भी आपको ट्रेस व्यूअर में चरणों के बीच अंतराल दिखाई देता है, तो आपको चरणों के बीच मॉडल कोड को देखना चाहिए और जांचना चाहिए कि क्या कॉलबैक/मेट्रिक्स को अक्षम करने से प्रदर्शन में सुधार होता है। इन ऑप्स के कुछ विवरण ट्रेस व्यूअर (डिवाइस और होस्ट साइड दोनों) पर भी हैं। इस परिदृश्य में सिफारिश प्रत्येक चरण के बजाय निश्चित संख्या में चरणों के बाद निष्पादित करके इन ऑप्स के ओवरहेड को परिशोधित करना है। tf.keras
API में Model.compile
विधि का उपयोग करते समय, steps_per_execution
ध्वज सेट करना यह स्वचालित रूप से करता है। कस्टम प्रशिक्षण लूप के लिए, tf. tf.while_loop
का उपयोग करें।
2. उच्च उपकरण उपयोग प्राप्त करें
1. छोटे GPU कर्नेल और होस्ट कर्नेल लॉन्च में देरी
होस्ट GPU पर चलाने के लिए कर्नेल को कतारबद्ध करता है, लेकिन GPU पर वास्तव में कर्नेल निष्पादित होने से पहले एक विलंबता (लगभग 20-40 μs) शामिल होती है। एक आदर्श स्थिति में, होस्ट GPU पर पर्याप्त कर्नेल इस तरह से लगाता है कि GPU अपना अधिकांश समय निष्पादित करने में व्यतीत करता है, बजाय इसके कि होस्ट पर अधिक कर्नेल लगाने के लिए प्रतीक्षा की जाए।
TensorBoard पर Profiler का अवलोकन पृष्ठ दिखाता है कि कर्नेल लॉन्च करने के लिए होस्ट पर प्रतीक्षा करने के कारण GPU कितना समय निष्क्रिय था। नीचे दी गई छवि में, GPU कर्नेल के लॉन्च होने की प्रतीक्षा में लगभग 10% चरण समय के लिए निष्क्रिय है।
इसी प्रोग्राम के लिए ट्रेस व्यूअर कर्नेल के बीच छोटे अंतराल दिखाता है जहां होस्ट GPU पर कर्नेल लॉन्च करने में व्यस्त है।
GPU पर बहुत सारे छोटे ऑप्स लॉन्च करके (उदाहरण के लिए, स्केलर ऐड की तरह), हो सकता है कि होस्ट GPU के साथ तालमेल न बिठाए। उसी प्रोफ़ाइल के लिए TensorBoard में TensorFlow Stats टूल 126,224 Mul संचालन दिखाता है जिसमें 2.77 सेकंड लगते हैं। इस प्रकार, प्रत्येक कर्नेल लगभग 21.9 μs है, जो बहुत छोटा है (लगभग उसी समय के रूप में लॉन्च विलंबता के रूप में) और संभावित रूप से होस्ट कर्नेल लॉन्च विलंब में परिणाम हो सकता है।
यदि आपका ट्रेस व्यूअर ऊपर की छवि की तरह GPU पर ऑप्स के बीच कई छोटे अंतराल दिखाता है, तो आप यह कर सकते हैं:
- छोटे टेंसरों को संयोजित करें और वेक्टरकृत ऑप्स का उपयोग करें या प्रत्येक लॉन्च किए गए कर्नेल को अधिक काम करने के लिए बड़े बैच आकार का उपयोग करें, जो GPU को अधिक समय तक व्यस्त रखेगा।
- सुनिश्चित करें कि आप TensorFlow ग्राफ़ बनाने के लिए
tf.function
का उपयोग कर रहे हैं, ताकि आप शुद्ध उत्सुक मोड में ops नहीं चला रहे हों। यदि आपModel.fit
(tf.GradientTape के साथ एक कस्टम प्रशिक्षण लूप केtf.GradientTape
) का उपयोग कर रहे हैं, तोtf.keras.Model.compile
स्वचालित रूप से आपके लिए ऐसा करेगा। -
tf.function(jit_compile=True)
या ऑटो-क्लस्टरिंग के साथ XLA का उपयोग करके फ्यूज कर्नेल। अधिक विवरण के लिए, उच्च प्रदर्शन प्राप्त करने के लिए XLA को सक्षम करने का तरीका जानने के लिए नीचे मिश्रित परिशुद्धता और XLA सक्षम करें अनुभाग पर जाएं। यह सुविधा उच्च डिवाइस उपयोग को जन्म दे सकती है।
2. TensorFlow op प्लेसमेंट
प्रोफाइलर अवलोकन पृष्ठ आपको होस्ट बनाम डिवाइस पर रखे गए ऑप्स का प्रतिशत दिखाता है (आप ट्रेस व्यूअर को देखकर भी विशिष्ट ऑप्स के प्लेसमेंट को सत्यापित कर सकते हैं। जैसे नीचे दी गई छवि में, आप होस्ट पर ऑप्स का प्रतिशत चाहते हैं डिवाइस की तुलना में बहुत छोटा होना।
आदर्श रूप से, अधिकांश कंप्यूट इंटेंसिव ऑप्स को GPU पर रखा जाना चाहिए।
यह पता लगाने के लिए कि आपके मॉडल में कौन से उपकरण संचालन और टेंसर को असाइन किया गया है, tf.debugging.set_log_device_placement(True)
को अपने प्रोग्राम के पहले स्टेटमेंट के रूप में सेट करें।
ध्यान दें कि कुछ मामलों में, भले ही आप किसी विशेष डिवाइस पर रखा जाने वाला ऑप निर्दिष्ट करते हों, इसका कार्यान्वयन इस शर्त को ओवरराइड कर सकता है (उदाहरण: tf.unique
)। यहां तक कि एकल GPU प्रशिक्षण के लिए, tf.distribute.OneDeviceStrategy
जैसी वितरण रणनीति निर्दिष्ट करने से आपके डिवाइस पर ऑप्स का अधिक नियतात्मक प्लेसमेंट हो सकता है।
GPU पर अधिकांश ऑप्स रखने का एक कारण होस्ट और डिवाइस के बीच अत्यधिक मेमोरी कॉपी को रोकना है (होस्ट और डिवाइस के बीच मॉडल इनपुट/आउटपुट डेटा के लिए मेमोरी कॉपी अपेक्षित हैं)। अत्यधिक नकल का एक उदाहरण नीचे दिए गए GPU स्ट्रीम #167 , #168 , और #169 पर ट्रेस दृश्य में प्रदर्शित किया गया है।
ये प्रतियां कभी-कभी प्रदर्शन को नुकसान पहुंचा सकती हैं यदि वे GPU कर्नेल को निष्पादित करने से रोकती हैं। ट्रेस व्यूअर में मेमोरी कॉपी ऑपरेशंस में ऑप्स के बारे में अधिक जानकारी होती है जो इन कॉपी किए गए टेंसर के स्रोत होते हैं, लेकिन मेमकॉपी को ऑप के साथ जोड़ना हमेशा आसान नहीं हो सकता है। इन मामलों में, यह जांचने के लिए आस-पास के ऑप्स को देखना मददगार होता है कि मेमोरी कॉपी हर चरण में एक ही स्थान पर होती है या नहीं।
3. GPU पर अधिक कुशल गुठली
एक बार जब आपके प्रोग्राम का GPU उपयोग स्वीकार्य हो जाता है, तो अगला कदम Tensor Cores या फ़्यूज़िंग ऑप्स का उपयोग करके GPU कर्नेल की दक्षता बढ़ाने पर विचार करना है।
1. टेंसर कोर का उपयोग करें
आधुनिक NVIDIA® GPU में विशेष Tensor Core हैं जो पात्र कर्नेल के प्रदर्शन में उल्लेखनीय सुधार कर सकते हैं।
आप TensorBoard के GPU कर्नेल आँकड़ों का उपयोग करके कल्पना कर सकते हैं कि कौन से GPU कर्नेल Tensor Core-योग्य हैं, और कौन से कर्नेल Tensor Core का उपयोग कर रहे हैं। fp16
को सक्षम करना (नीचे मिश्रित प्रेसिजन सक्षम करना अनुभाग देखें) आपके प्रोग्राम के जनरल मैट्रिक्स मल्टीप्ली (GEMM) कर्नेल (matmul ops) को Tensor Core का उपयोग करने का एक तरीका है। जब सटीकता fp16 होती है और इनपुट/आउटपुट टेंसर आयाम 8 या 16 ( int8
के लिए) से विभाज्य होते हैं, तो GPU कर्नेल टेंसर कोर का कुशलता से उपयोग करते हैं।
GPU के लिए गुठली को कुशल बनाने के तरीके के बारे में अन्य विस्तृत अनुशंसाओं के लिए, NVIDIA® डीप लर्निंग परफॉर्मेंस गाइड देखें।
2. फ्यूज ऑप्स
tf.function(jit_compile=True)
का उपयोग छोटे ऑप्स को बड़े कर्नेल बनाने के लिए फ्यूज करने के लिए करें जिससे महत्वपूर्ण प्रदर्शन लाभ प्राप्त होता है। अधिक जानने के लिए, XLA मार्गदर्शिका देखें।
3. मिश्रित परिशुद्धता और XLA सक्षम करें
उपरोक्त चरणों का पालन करने के बाद, मिश्रित परिशुद्धता और XLA सक्षम करना दो वैकल्पिक कदम हैं जिन्हें आप प्रदर्शन को और बेहतर बनाने के लिए उठा सकते हैं। सुझाया गया दृष्टिकोण उन्हें एक-एक करके सक्षम करना और यह सत्यापित करना है कि प्रदर्शन लाभ अपेक्षित हैं।
1. मिश्रित परिशुद्धता सक्षम करें
TensorFlow मिश्रित सटीक गाइड दिखाता है कि GPU पर fp16
परिशुद्धता को कैसे सक्षम किया जाए। NVIDIA® GPU पर AMP को Tensor Cores का उपयोग करने के लिए सक्षम करें और वोल्टा और नए GPU आर्किटेक्चर पर केवल fp32
(float32) परिशुद्धता का उपयोग करने की तुलना में 3x समग्र स्पीडअप का एहसास करें।
सुनिश्चित करें कि मैट्रिक्स/टेंसर आयाम टेन्सर कोर का उपयोग करने वाले कर्नेल को कॉल करने के लिए आवश्यकताओं को पूरा करते हैं। जब सटीकता fp16 होती है और इनपुट/आउटपुट आयाम 8 या 16 (int8 के लिए) से विभाज्य होते हैं तो GPU कर्नेल टेंसर कोर का कुशलता से उपयोग करते हैं।
ध्यान दें कि cuDNN v7.6.3 और बाद के संस्करण के साथ, जहाँ आवश्यक हो, Tensor Cores का लाभ उठाने के लिए कनवल्शन आयामों को स्वचालित रूप से गद्देदार किया जाएगा।
fp16
परिशुद्धता के प्रदर्शन लाभों को अधिकतम करने के लिए नीचे दी गई सर्वोत्तम प्रथाओं का पालन करें।
1. इष्टतम fp16 कर्नेल का प्रयोग करें
fp16
सक्षम होने पर, आपके प्रोग्राम के मैट्रिक्स गुणन (GEMM) कर्नेल को संबंधित fp16
संस्करण का उपयोग करना चाहिए जो Tensor Cores का उपयोग करता है। हालाँकि, कुछ मामलों में, ऐसा नहीं होता है और आप fp16
को सक्षम करने से अपेक्षित गति का अनुभव नहीं करते हैं, क्योंकि आपका प्रोग्राम इसके बजाय अक्षम कार्यान्वयन पर वापस आ जाता है।
GPU कर्नेल आँकड़े पृष्ठ दिखाता है कि कौन से ऑप्स Tensor Core योग्य हैं और कौन से कर्नेल वास्तव में कुशल Tensor Core का उपयोग कर रहे हैं। गहन शिक्षण प्रदर्शन पर NVIDIA® गाइड में Tensor Cores का लाभ उठाने के बारे में अतिरिक्त सुझाव शामिल हैं। इसके अतिरिक्त, fp16
का उपयोग करने के लाभ उन कर्नेल में भी दिखाई देंगे जो पहले मेमोरी बाउंड थे, क्योंकि अब ऑप्स में आधा समय लगेगा।
2. गतिशील बनाम स्थिर हानि स्केलिंग
कम परिशुद्धता के कारण अंडरफ्लो को रोकने के लिए fp16
का उपयोग करते समय हानि स्केलिंग आवश्यक है। लॉस स्केलिंग दो प्रकार की होती है, डायनेमिक और स्टैटिक, दोनों को मिक्स्ड प्रिसिजन गाइड में अधिक विस्तार से समझाया गया है। आप केरस अनुकूलक के भीतर हानि स्केलिंग को स्वचालित रूप से सक्षम करने के लिए mixed_float16
नीति का उपयोग कर सकते हैं।
प्रदर्शन को अनुकूलित करने का प्रयास करते समय, यह याद रखना महत्वपूर्ण है कि डायनेमिक लॉस स्केलिंग अतिरिक्त सशर्त ऑप्स पेश कर सकता है जो होस्ट पर चलता है, और अंतराल की ओर ले जाता है जो ट्रेस व्यूअर में चरणों के बीच दिखाई देगा। दूसरी ओर, स्टैटिक लॉस स्केलिंग में इस तरह के ओवरहेड्स नहीं होते हैं और कैच के साथ प्रदर्शन के मामले में एक बेहतर विकल्प हो सकता है जिसे आपको सही स्टैटिक-लॉस स्केल मान निर्दिष्ट करने की आवश्यकता होती है।
2. XLA को tf.function(jit_compile=True) या ऑटो-क्लस्टरिंग के साथ सक्षम करें
एकल GPU के साथ सर्वश्रेष्ठ प्रदर्शन प्राप्त करने के अंतिम चरण के रूप में, आप XLA को सक्षम करने के साथ प्रयोग कर सकते हैं, जो ऑप्स को जोड़ देगा और बेहतर डिवाइस उपयोग और कम मेमोरी फ़ुटप्रिंट की ओर ले जाएगा। tf.function(jit_compile=True)
या ऑटो-क्लस्टरिंग के साथ अपने प्रोग्राम में XLA को सक्षम करने के तरीके के विवरण के लिए, XLA गाइड देखें।
आप वैश्विक JIT स्तर को -1
(बंद), 1
, या 2
पर सेट कर सकते हैं। एक उच्च स्तर अधिक आक्रामक होता है और समानता को कम कर सकता है और अधिक स्मृति का उपयोग कर सकता है। यदि आपके पास स्मृति प्रतिबंध हैं, तो मान को 1
पर सेट करें। ध्यान दें कि XLA चर इनपुट टेंसर आकार वाले मॉडल के लिए अच्छा प्रदर्शन नहीं करता है क्योंकि XLA कंपाइलर को जब भी नई आकृतियों का सामना करना पड़ता है, तो उसे कर्नेल को संकलित करते रहना होगा।
2. मल्टी-जीपीयू सिंगल होस्ट पर प्रदर्शन का अनुकूलन करें
tf.distribute.MirroredStrategy
API का उपयोग एक ही होस्ट पर एक GPU से कई GPU तक मॉडल प्रशिक्षण को स्केल करने के लिए किया जा सकता है। (टेन्सरफ्लो के साथ वितरित प्रशिक्षण कैसे करें, इसके बारे में अधिक जानने के लिए, टेंसरफ्लो के साथ वितरित प्रशिक्षण देखें, जीपीयू का उपयोग करें, और टीपीयू गाइड का उपयोग करें और केरस ट्यूटोरियल के साथ वितरित प्रशिक्षण ।)
हालांकि एक जीपीयू से कई जीपीयू में संक्रमण आदर्श रूप से बॉक्स से बाहर स्केलेबल होना चाहिए, आप कभी-कभी प्रदर्शन के मुद्दों का सामना कर सकते हैं।
एक ही होस्ट पर एक ही GPU के साथ कई GPU के साथ प्रशिक्षण से जाते समय, आदर्श रूप से आपको केवल ग्रेडिएंट संचार के अतिरिक्त ओवरहेड और होस्ट थ्रेड उपयोग में वृद्धि के साथ प्रदर्शन स्केलिंग का अनुभव करना चाहिए। इस ओवरहेड के कारण, उदाहरण के लिए, यदि आप 1 से 2 GPU तक ले जाते हैं, तो आपके पास सटीक 2x स्पीडअप नहीं होगा।
नीचे दिया गया ट्रेस दृश्य एकाधिक GPU पर प्रशिक्षण के दौरान अतिरिक्त संचार ओवरहेड का एक उदाहरण दिखाता है। ग्रेडिएंट्स को जोड़ने, उन्हें प्रतिकृतियों में संप्रेषित करने और वज़न अपडेट करने से पहले उन्हें विभाजित करने के लिए कुछ ओवरहेड है।
मल्टी-जीपीयू परिदृश्य में प्रदर्शन को अनुकूलित करते समय निम्नलिखित चेकलिस्ट आपको बेहतर प्रदर्शन प्राप्त करने में मदद करेगी:
- बैच आकार को अधिकतम करने का प्रयास करें, जिससे डिवाइस का अधिक उपयोग होगा और कई GPU में संचार की लागत का परिशोधन होगा। मेमोरी प्रोफाइलर का उपयोग करने से यह समझने में मदद मिलती है कि आपका प्रोग्राम मेमोरी उपयोग के चरम पर कितना करीब है। ध्यान दें कि उच्च बैच आकार अभिसरण को प्रभावित कर सकता है, यह आमतौर पर प्रदर्शन लाभों से अधिक होता है।
- एकल GPU से कई GPU में जाने पर, उसी होस्ट को अब बहुत अधिक इनपुट डेटा संसाधित करना होगा। इसलिए, (1) के बाद, इनपुट पाइपलाइन के प्रदर्शन की फिर से जाँच करने और यह सुनिश्चित करने की सिफारिश की जाती है कि यह एक अड़चन नहीं है।
- किसी भी अनावश्यक AllReduce कॉल के लिए अपने प्रोग्राम के ट्रेस व्यू में GPU टाइमलाइन की जाँच करें, क्योंकि इससे सभी डिवाइस में एक सिंक्रोनाइज़ेशन होता है। ऊपर दिखाए गए ट्रेस दृश्य में, AllReduce NCCL कर्नेल के माध्यम से किया जाता है, और प्रत्येक चरण पर ग्रेडिएंट के लिए प्रत्येक GPU पर केवल एक NCCL कॉल होता है।
- अनावश्यक D2H, H2D और D2D प्रतिलिपि संचालनों की जाँच करें जिन्हें कम किया जा सकता है।
- यह सुनिश्चित करने के लिए चरण समय की जाँच करें कि प्रत्येक प्रतिकृति समान कार्य कर रही है। उदाहरण के लिए, ऐसा हो सकता है कि एक GPU (आमतौर पर,
GPU0
) ओवरसब्सक्राइब हो जाता है क्योंकि होस्ट गलती से उस पर अधिक काम कर देता है। - अंत में, क्रमिक रूप से निष्पादित होने वाले किसी भी ऑप्स के लिए अपने ट्रेस व्यू में सभी GPU के प्रशिक्षण चरण की जाँच करें। यह आमतौर पर तब होता है जब आपके प्रोग्राम में एक GPU से दूसरे GPU पर नियंत्रण निर्भरताएँ शामिल होती हैं। अतीत में, इस स्थिति में प्रदर्शन को डीबग करना मामला-दर-मामला आधार पर हल किया गया है। यदि आप अपने प्रोग्राम में इस व्यवहार को देखते हैं, तो अपने ट्रेस व्यू की छवियों के साथ एक गिटहब समस्या दर्ज करें।
1. ऑप्टिमाइज़ ग्रेडिएंट AllReduce
एक तुल्यकालिक रणनीति के साथ प्रशिक्षण के दौरान, प्रत्येक डिवाइस को इनपुट डेटा का एक हिस्सा प्राप्त होता है।
आगे और पीछे की गणना मॉडल के माध्यम से गुजरती है, प्रत्येक डिवाइस पर गणना किए गए ग्रेडिएंट को एकत्रित और कम करने की आवश्यकता होती है। यह ग्रेडिएंट AllReduce प्रत्येक डिवाइस पर ग्रेडिएंट गणना के बाद होता है, और इससे पहले कि ऑप्टिमाइज़र मॉडल वज़न को अपडेट करता है।
प्रत्येक GPU पहले मॉडल परतों में ग्रेडिएंट्स को संयोजित करता है, उन्हें tf.distribute.CrossDeviceOps
( tf.distribute.NcclAllReduce
डिफ़ॉल्ट है) का उपयोग करके GPU में संचार करता है, और फिर प्रति परत कमी के बाद ग्रेडिएंट लौटाता है।
ऑप्टिमाइज़र आपके मॉडल के वज़न को अपडेट करने के लिए इन घटे हुए ग्रेडिएंट्स का उपयोग करेगा। आदर्श रूप से, यह प्रक्रिया किसी भी ओवरहेड को रोकने के लिए सभी GPU पर एक ही समय में होनी चाहिए।
AllReduce का समय लगभग समान होना चाहिए:
(number of parameters * 4bytes)/ (communication bandwidth)
यह गणना यह समझने के लिए एक त्वरित जांच के रूप में उपयोगी है कि वितरित प्रशिक्षण कार्य चलाते समय आपका प्रदर्शन अपेक्षित है, या यदि आपको आगे प्रदर्शन डिबगिंग करने की आवश्यकता है। आप Model.summary
से अपने मॉडल में पैरामीटर्स की संख्या प्राप्त कर सकते हैं।
ध्यान दें कि प्रत्येक मॉडल पैरामीटर आकार में 4 बाइट्स है क्योंकि TensorFlow ग्रेडिएंट को संप्रेषित करने के लिए fp32 ( fp32
) का उपयोग करता है। यहां तक कि जब आपके पास fp16
सक्षम है, तब भी NCCL fp32
पैरामीटर का उपयोग करता है।
स्केलिंग के लाभ प्राप्त करने के लिए, इन ओवरहेड्स की तुलना में स्टेप-टाइम बहुत अधिक होना चाहिए। इसे प्राप्त करने का एक तरीका उच्च बैच आकार का उपयोग करना है क्योंकि बैच आकार चरण समय को प्रभावित करता है, लेकिन संचार ओवरहेड को प्रभावित नहीं करता है।
2. GPU होस्ट थ्रेड विवाद
कई GPU चलाते समय, CPU का काम सभी उपकरणों को कुशलतापूर्वक GPU कर्नेल लॉन्च करके सभी उपकरणों को व्यस्त रखना है।
हालाँकि, जब बहुत सारे स्वतंत्र संचालन होते हैं जो CPU एक GPU पर शेड्यूल कर सकता है, तो CPU एक GPU को व्यस्त रखने के लिए अपने बहुत सारे होस्ट थ्रेड्स का उपयोग करने का निर्णय ले सकता है, और फिर गैर-निर्धारक क्रम में दूसरे GPU पर कर्नेल लॉन्च कर सकता है। . यह एक तिरछा या नकारात्मक स्केलिंग का कारण बन सकता है, जो प्रदर्शन को नकारात्मक रूप से प्रभावित कर सकता है।
नीचे दिया गया ट्रेस व्यूअर ओवरहेड दिखाता है जब सीपीयू जीपीयू कर्नेल को अक्षम रूप से लॉन्च करता है, क्योंकि GPU1
निष्क्रिय है और फिर GPU2
शुरू होने के बाद ऑप्स चलाना शुरू कर देता है।
होस्ट के लिए ट्रेस व्यू से पता चलता है कि होस्ट GPU2
पर कर्नेल लॉन्च करने से पहले उन्हें GPU1
पर लॉन्च कर रहा है (ध्यान दें कि नीचे tf_Compute*
ops CPU थ्रेड्स का संकेत नहीं है)।
यदि आप अपने प्रोग्राम के ट्रेस व्यू में GPU कर्नेल के इस तरह के चौंका देने वाले अनुभव का अनुभव करते हैं, तो अनुशंसित कार्रवाई है:
- TensorFlow पर्यावरण चर
TF_GPU_THREAD_MODE
कोgpu_private
पर सेट करें। यह पर्यावरण चर मेजबान को एक GPU निजी के लिए थ्रेड रखने के लिए कहेगा। - डिफ़ॉल्ट रूप से,
TF_GPU_THREAD_MODE=gpu_private
थ्रेड्स की संख्या 2 पर सेट करता है, जो कि ज्यादातर मामलों में पर्याप्त है। हालाँकि, TensorFlow पर्यावरण चरTF_GPU_THREAD_COUNT
को वांछित संख्या में थ्रेड्स पर सेट करके उस संख्या को बदला जा सकता है।