खोज…


परिचय

यह विषय समानांतर कंप्यूटिंग के कुछ अंतर्निहित मुख्य यांत्रिकी का परिचय देता है जिन्हें ओपनसीएल को पूरी तरह से समझने और उपयोग करने की आवश्यकता होती है।

धागे और निष्पादन

समानता की कुंजी एक समस्या (डुह) को हल करने के लिए कई थ्रेड्स का उपयोग करना है, लेकिन थ्रेड्स कैसे व्यवस्थित किए जाते हैं, इसमें शास्त्रीय मल्टीथ्रेडेड प्रोग्रामिंग में कुछ अंतर हैं।

पहले अपने विशिष्ट GPU के बारे में बात करते हैं, सरलता के लिए मैं इस पर ध्यान केंद्रित करूंगा

एक GPU में कई प्रसंस्करण कोर होते हैं, जो समानांतर में कई थ्रेड्स निष्पादित करने के लिए आदर्श बनाते हैं। उन कोर को स्ट्रीमिंग प्रोसेसर्स (एसएम, एनवीडिया टर्म) में आयोजित किया जाता है, जिनमें से एक जीपीयू की दी गई संख्या होती है।

एसएम के अंदर चलने वाले सभी थ्रेड्स को 'थ्रेड ब्लॉक' कहा जाता है। किसी SM पर इससे अधिक धागे हो सकते हैं जैसे कि इसमें कोर है। कोर की संख्या तथाकथित 'ताना आकार' (NVidia शब्द) को परिभाषित करती है। थ्रेड ब्लॉक के अंदर थ्रेड्स को 'वॉरप्स' में शेड किया जाता है।

एक त्वरित उदाहरण का अनुसरण करने के लिए: एक विशिष्ट एनवीडीआईए एसएम में 32 प्रोसेसिंग कोर हैं, इस प्रकार इसका ताना आकार 32 है। यदि मेरे थ्रेड ब्लॉक में अब चलाने के लिए 128 थ्रेड हैं, तो उन्हें 4 वॉरपेड में शेड किया जाएगा (4 वॉरप्लस * 32 डीपी आकार = 128 धागे)।

बाद में थ्रेड्स की संख्या का चयन करते समय ताना आकार महत्वपूर्ण है।

एक ही ताना के अंदर सभी सूत्र एक ही निर्देश काउंटर को साझा करते हैं। इसका मतलब है कि उन 32 धागे वास्तव में सिंक्रनाइज़ किए जाते हैं कि प्रत्येक थ्रेड एक ही समय में प्रत्येक कमांड को निष्पादित करता है। यहाँ एक प्रदर्शन ख़राब है: यह आपके कर्नेल में शाखाओं के विवरण पर भी लागू होता है!

उदाहरण: मेरे पास एक कर्नेल है जिसमें एक if स्टेटमेंट और दो शाखाएँ हैं। एक ताना के अंदर मेरे धागे में से 16 शाखा एक, अन्य 16 शाखा दो निष्पादित करेगा। यदि कथन तक, ताना के अंदर सभी धागे सिंक में हैं। अब उनमें से आधे एक अलग शाखा का चयन करते हैं। क्या होता है कि अन्य आधा तब तक निष्क्रिय रहेगा, जब तक कि गलत कथन पहले 16 धागे पर निष्पादित नहीं हो जाता। तब तक वे धागे निष्क्रिय हो जाएंगे जब तक कि अन्य 16 धागे अपनी शाखा समाप्त नहीं कर लेते।

जैसा कि आप देख सकते हैं, बुरी शाखाएं आपके समानांतर कोड को गंभीर रूप से धीमा कर सकती हैं, क्योंकि दोनों बयान सबसे खराब स्थिति में निष्पादित होते हैं। अगर एक ताना के अंदर सभी धागे तय करते हैं कि उन्हें केवल एक बयान की आवश्यकता है, तो दूसरा पूरी तरह से छोड़ दिया जाता है और कोई देरी नहीं होती है।

धागे को सिंक करना भी कोई साधारण बात नहीं है। आप केवल एक एसएम के साथ थ्रेड्स को सिंक कर सकते हैं। एसएम के बाहर सब कुछ कर्नेल के अंदर से अपरिहार्य है। आपको अलग-अलग कर्नेल लिखना होगा और उन्हें एक के बाद एक लॉन्च करना होगा।

GPU मेमोरी

GPU छह अलग-अलग मेमोरी क्षेत्र प्रदान करता है। वे अलग-अलग धागों से अपनी विलंबता, आकार और पहुंच में भिन्न होते हैं।

  • ग्लोबल मेमोरी: उपलब्ध सबसे बड़ी मेमोरी और मेजबान के साथ डेटा का आदान-प्रदान करने वाले कुछ लोगों में से एक। इस मेमोरी में उच्चतम विलंबता है और सभी थ्रेड्स के लिए उपलब्ध है।
  • लगातार मेमोरी: एक वैश्विक मेमोरी का केवल एक हिस्सा है, जिसे केवल अन्य थ्रेड्स द्वारा पढ़ा जा सकता है। इसका लाभ वैश्विक मेमोरी की तुलना में कम विलंबता है
  • बनावट मेमोरी: निरंतर मेमोरी का एक हिस्सा, विशेष रूप से बनावट के लिए डिज़ाइन किया गया
  • साझा मेमोरी: यह मेमोरी क्षेत्र एसएम के करीब रखा गया है और केवल एक ही थ्रेड ब्लॉक द्वारा एक्सेस किया जा सकता है। यह वैश्विक मेमोरी की तुलना में कम विलंबता और निरंतर मेमोरी की तुलना में थोड़ा कम विलंबता प्रदान करता है।
  • रजिस्टर: केवल एक ही धागे और उन सभी की सबसे तेज़ स्मृति द्वारा सुलभ। लेकिन अगर कंपाइलर यह पता लगाता है कि कर्नेल की ज़रूरत के लिए पर्याप्त रजिस्टर नहीं हैं, तो यह चर को स्थानीय मेमोरी में आउटसोर्स कर देगा।
  • स्थानीय मेमोरी: वैश्विक स्मृति क्षेत्र में स्मृति का केवल थ्रेड योग्य भाग। रजिस्टरों के लिए बैकअप के रूप में उपयोग किया जाता है, यदि संभव हो तो टाला जा सकता है।

मेमोरी एक्सेस

आपकी मेमोरी उपयोग के लिए विशिष्ट परिदृश्य स्रोत डेटा और संसाधित डेटा को वैश्विक मेमोरी में संग्रहीत करना है। जब एक थ्रेडब्लॉक शुरू होता है, तो यह पहले सभी संबंधित भागों को रजिस्टरों में उनके भागों को प्राप्त करने से पहले साझा मेमोरी में कॉपी करता है।

मेमोरी एक्सेस विलंबता आपकी मेमोरी रणनीति पर भी निर्भर करती है। यदि आप आँख बंद करके डेटा का उपयोग करते हैं तो आपको सबसे खराब प्रदर्शन संभव होगा।

विभिन्न यादें तथाकथित 'बैंकों' में आयोजित की जाती हैं। बैंक के लिए प्रत्येक मेमोरी अनुरोध को एक एकल घड़ी चक्र में संभाला जा सकता है। साझा मेमोरी में बैंकों की संख्या ताना आकार के बराबर होती है। एक ताना के अंदर परस्पर विरोधी बैंक पहुंच से बचकर स्मृति की गति को बढ़ाया जा सकता है।

साझा मेमोरी से या वैश्विक मेमोरी में सबसे तेज़ तरीके से कॉपी करने के लिए अपनी मेमोरी कॉल को 'संरेखित' करना है। इसका मतलब यह है कि एक ताना में पहला धागा साझा और वैश्विक मेमोरी दोनों के बैंक में पहले तत्व तक पहुंचना चाहिए। दूसरा धागा दूसरा तत्व वगैरह। इस कॉल को एक एकल मेमोरी ट्रांसफर इंस्ट्रक्शन में ऑप्टिमाइज़ किया जाएगा जो पूरे बैंक को एक बार में लक्ष्य मेमोरी में कॉपी कर देता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow