GPU त्वरण सक्षम करें. जीपीयू पर कंप्यूटिंग जीपीयू से सीपीयू तक गणना

💖क्या आपको यह पसंद है?लिंक को अपने दोस्तों के साथ साझा करें

C++ AMP के साथ GPU कंप्यूटिंग का उपयोग करना

अब तक, समानांतर प्रोग्रामिंग तकनीकों पर चर्चा में, हमने केवल प्रोसेसर कोर पर विचार किया है। हमने कई प्रोसेसरों में प्रोग्राम को समानांतर करने, साझा संसाधनों तक पहुंच को सिंक्रनाइज़ करने और लॉक का उपयोग किए बिना हाई-स्पीड सिंक्रोनाइज़ेशन प्रिमिटिव का उपयोग करने में कुछ कौशल हासिल किए हैं।

हालाँकि, कार्यक्रमों को समानांतर करने का एक और तरीका है - ग्राफ़िक्स प्रोसेसिंग यूनिट (जीपीयू), होना एक लंबी संख्यायहां तक ​​कि उच्च-प्रदर्शन प्रोसेसर से भी अधिक कोर। जीपीयू कोर समानांतर डेटा प्रोसेसिंग एल्गोरिदम को लागू करने के लिए उत्कृष्ट हैं, और उनकी बड़ी संख्या उन पर प्रोग्राम चलाने की असुविधा के लिए भुगतान करती है। इस लेख में हम C++ भाषा एक्सटेंशन के एक सेट का उपयोग करके GPU पर प्रोग्राम चलाने के तरीकों में से एक से परिचित होंगे जिसे कहा जाता है सी++एएमपी.

C++ AMP एक्सटेंशन C++ भाषा पर आधारित हैं, यही कारण है कि यह आलेख C++ में उदाहरण प्रदर्शित करेगा। हालाँकि, इंटरेक्शन तंत्र के मध्यम उपयोग के साथ। NET, आप अपने .NET प्रोग्राम में C++ AMP एल्गोरिदम का उपयोग कर सकते हैं। लेकिन हम इस बारे में लेख के अंत में बात करेंगे।

सी++ एएमपी का परिचय

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

    आधुनिक जीपीयू में बहुत छोटा निर्देश सेट होता है। इसका तात्पर्य कुछ सीमाओं से है: फ़ंक्शंस को कॉल करने की क्षमता की कमी, समर्थित डेटा प्रकारों का सीमित सेट, लाइब्रेरी फ़ंक्शंस की कमी, और अन्य। कुछ ऑपरेशन, जैसे सशर्त शाखाएं, पारंपरिक प्रोसेसर पर किए गए समान ऑपरेशन की तुलना में काफी अधिक लागत वाली हो सकती हैं। जाहिर है, ऐसी परिस्थितियों में बड़ी मात्रा में कोड को सीपीयू से जीपीयू तक ले जाने के लिए महत्वपूर्ण प्रयास की आवश्यकता होती है।

    औसत GPU में कोर की संख्या औसत पारंपरिक प्रोसेसर की तुलना में काफी अधिक है। हालाँकि, कुछ कार्य बहुत छोटे हैं या उन्हें GPU से लाभ उठाने के लिए पर्याप्त बड़े भागों में विभाजित नहीं किया जा सकता है।

    समान कार्य करने वाले GPU कोर के बीच सिंक्रनाइज़ेशन समर्थन बहुत खराब है, और विभिन्न कार्य करने वाले GPU कोर के बीच पूरी तरह से अनुपस्थित है। इस परिस्थिति में पारंपरिक प्रोसेसर के साथ ग्राफिक्स प्रोसेसर के सिंक्रनाइज़ेशन की आवश्यकता होती है।

प्रश्न तुरंत उठता है: GPU पर हल करने के लिए कौन से कार्य उपयुक्त हैं? ध्यान रखें कि प्रत्येक एल्गोरिदम GPU पर निष्पादन के लिए उपयुक्त नहीं है। उदाहरण के लिए, GPU के पास I/O डिवाइस तक पहुंच नहीं है, इसलिए आप GPU का उपयोग करके इंटरनेट से RSS फ़ीड्स को स्क्रैप करने वाले प्रोग्राम के प्रदर्शन में सुधार नहीं कर पाएंगे। हालाँकि, कई कम्प्यूटेशनल एल्गोरिदम को GPU में स्थानांतरित किया जा सकता है और बड़े पैमाने पर समानांतर किया जा सकता है। नीचे ऐसे एल्गोरिदम के कुछ उदाहरण दिए गए हैं (यह सूची किसी भी तरह से पूर्ण नहीं है):

    छवियों को तीक्ष्ण बनाना और चमकाना, और अन्य परिवर्तन;

    फास्ट फूरियर ट्रांसफॉर्म;

    मैट्रिक्स स्थानान्तरण और गुणन;

    संख्या छँटाई;

    प्रत्यक्ष हैश उलटा।

अतिरिक्त उदाहरणों के लिए एक उत्कृष्ट स्रोत Microsoft Native Concurrency ब्लॉग है, जो C++ AMP में कार्यान्वित विभिन्न एल्गोरिदम के लिए कोड स्निपेट और स्पष्टीकरण प्रदान करता है।

C++ AMP विज़ुअल स्टूडियो 2012 में शामिल एक फ्रेमवर्क है जो C++ डेवलपर्स को GPU पर गणना करने का एक आसान तरीका देता है, जिसके लिए केवल DirectX 11 ड्राइवर की आवश्यकता होती है। Microsoft ने C++ AMP को एक ओपन स्पेसिफिकेशन के रूप में जारी किया है जिसे किसी भी कंपाइलर विक्रेता द्वारा कार्यान्वित किया जा सकता है।

C++ AMP फ्रेमवर्क आपको कोड चलाने की अनुमति देता है ग्राफ़िक्स त्वरकत्वरक, जो कंप्यूटिंग डिवाइस हैं। DirectX 11 ड्राइवर का उपयोग करते हुए, C++ AMP फ्रेमवर्क गतिशील रूप से सभी एक्सेलेरेटर का पता लगाता है। C++ AMP भी शामिल है सॉफ्टवेयर एम्यूलेटरएक पारंपरिक प्रोसेसर, WARP पर आधारित एक्सेलेरेटर और एमुलेटर, जो बिना GPU या GPU के साथ लेकिन DirectX 11 ड्राइवर की कमी वाले सिस्टम पर फ़ॉलबैक के रूप में कार्य करता है, और कई कोर और SIMD निर्देशों का उपयोग करता है।

आइए अब एक ऐसे एल्गोरिदम की खोज शुरू करें जिसे आसानी से GPU पर निष्पादन के लिए समानांतर किया जा सके। नीचे दिया गया कार्यान्वयन समान लंबाई के दो वैक्टर लेता है और बिंदुवार परिणाम की गणना करता है। इससे अधिक सीधी किसी चीज़ की कल्पना करना कठिन है:

Void वेक्टरAddExpबिंदुवार(फ्लोट* प्रथम, फ्लोट* दूसरा, फ्लोट* परिणाम, int लंबाई) (for (int i = 0; i)< length; ++i) { result[i] = first[i] + exp(second[i]); } }

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

GPU के लिए, इन चेतावनियों की आवश्यकता नहीं है. जीपीयू में कई कोर होते हैं जो थ्रेड को बहुत तेज़ी से निष्पादित करते हैं, और संदर्भ स्विचिंग की लागत पारंपरिक प्रोसेसर की तुलना में काफी कम है। नीचे फ़ंक्शन का उपयोग करने का प्रयास करने वाला एक स्निपेट है प्रत्येक के लिए समानांतर C++ AMP फ्रेमवर्क से:

#शामिल करना #शामिल करना नेमस्पेस समवर्ती का उपयोग करना; शून्य वेक्टरऐडएक्सपीप्वाइंटवाइज(फ्लोट* प्रथम, फ्लोट* दूसरा, फ्लोट* परिणाम, पूर्णांक लंबाई) (array_view avFirst(लंबाई, प्रथम); array_view एवीसेकंड(लंबाई, दूसरा); array_view avResult(लंबाई, परिणाम); avResult.discard_data(); Parallel_for_each(avResult.extent, [=](index<1>i) प्रतिबंधित(amp) ( avResult[i] = avFirst[i] + fast_math::exp(avSecond[i]); )); avResult.synchronize(); )

आइए अब कोड के प्रत्येक भाग की अलग से जाँच करें। आइए तुरंत ध्यान दें कि मुख्य लूप का सामान्य रूप संरक्षित किया गया है, लेकिन मूल रूप से लूप के लिए उपयोग किए जाने वाले को समानान्तर_for_each फ़ंक्शन पर कॉल द्वारा बदल दिया गया है। वास्तव में, लूप को फ़ंक्शन या विधि कॉल में परिवर्तित करने का सिद्धांत हमारे लिए नया नहीं है - ऐसी तकनीक को पहले टीपीएल लाइब्रेरी से Parallel.For() और Parallel.ForEach() विधियों का उपयोग करके प्रदर्शित किया गया है।

इसके बाद, इनपुट डेटा (पैरामीटर पहले, दूसरे और परिणाम) को उदाहरणों के साथ लपेटा जाता है array_view. Array_view वर्ग का उपयोग GPU (त्वरक) को भेजे गए डेटा को लपेटने के लिए किया जाता है। इसका टेम्प्लेट पैरामीटर डेटा प्रकार और उसके आयाम को निर्दिष्ट करता है। जीपीयू पर निर्देशों को निष्पादित करने के लिए जो मूल रूप से पारंपरिक सीपीयू पर संसाधित डेटा तक पहुंचते हैं, किसी को या किसी चीज़ को जीपीयू में डेटा की प्रतिलिपि बनाने का ध्यान रखना होगा क्योंकि अधिकांश आधुनिक ग्राफिक्स कार्ड अपनी मेमोरी के साथ अलग डिवाइस हैं। array_view उदाहरण इस समस्या को हल करते हैं - वे मांग पर डेटा कॉपी प्रदान करते हैं और केवल तभी जब इसकी वास्तव में आवश्यकता होती है।

जब GPU कार्य पूरा कर लेता है, तो डेटा वापस कॉपी हो जाता है। const तर्क के साथ array_view को इंस्टेंट करके, हम यह सुनिश्चित करते हैं कि पहले और दूसरे को GPU मेमोरी में कॉपी किया गया है, लेकिन वापस कॉपी नहीं किया गया है। इसी तरह, कॉलिंग त्याग_डेटा(), हम नियमित प्रोसेसर की मेमोरी से एक्सेलेरेटर मेमोरी में कॉपी करने के परिणाम को बाहर कर देते हैं, लेकिन यह डेटा विपरीत दिशा में कॉपी किया जाएगा।

Parallel_for_each फ़ंक्शन एक हद ऑब्जेक्ट लेता है जो संसाधित किए जाने वाले डेटा के रूप को निर्दिष्ट करता है और हद ऑब्जेक्ट में प्रत्येक तत्व पर लागू होने वाला एक फ़ंक्शन निर्दिष्ट करता है। उपरोक्त उदाहरण में, हमने एक लैम्ब्डा फ़ंक्शन का उपयोग किया, जिसके लिए समर्थन ISO C++2011 (C++11) मानक में दिखाई दिया। प्रतिबंधित (amp) कीवर्ड कंपाइलर को यह जांचने का निर्देश देता है कि क्या फ़ंक्शन बॉडी को GPU पर निष्पादित किया जा सकता है और अधिकांश C++ सिंटैक्स को अक्षम कर देता है जिन्हें GPU निर्देशों में संकलित नहीं किया जा सकता है।

लैम्ब्डा फ़ंक्शन पैरामीटर, सूचकांक<1>ऑब्जेक्ट, एक-आयामी सूचकांक का प्रतिनिधित्व करता है। इसे उपयोग की जा रही सीमा वस्तु से मेल खाना चाहिए - यदि हमें सीमा वस्तु को दो-आयामी घोषित करना है (उदाहरण के लिए, स्रोत डेटा के आकार को दो-आयामी मैट्रिक्स के रूप में परिभाषित करके), तो सूचकांक को भी दो होना होगा -आयामी. ऐसी स्थिति का एक उदाहरण नीचे दिया गया है.

अंत में, विधि कॉल सिंक्रनाइज़()वेक्टरऐडएक्सपीप्वाइंटवाइज विधि के अंत में, यह सुनिश्चित करता है कि GPU द्वारा उत्पादित array_view avResult से गणना परिणाम, परिणाम सरणी में वापस कॉपी किए जाते हैं।

यह C++ AMP की दुनिया में हमारा पहला परिचय समाप्त करता है, और अब हम अधिक विस्तृत शोध के लिए तैयार हैं, साथ ही GPU पर समानांतर कंप्यूटिंग के उपयोग के लाभों को प्रदर्शित करने वाले अधिक दिलचस्प उदाहरणों के लिए भी तैयार हैं। वेक्टर जोड़ एक अच्छा एल्गोरिदम नहीं है और डेटा की प्रतिलिपि बनाने के बड़े ओवरहेड के कारण जीपीयू उपयोग को प्रदर्शित करने के लिए सबसे अच्छा उम्मीदवार नहीं है। अगला उपखंड दो और दिलचस्प उदाहरण दिखाएगा।

मैट्रिक्स गुणन

पहला "वास्तविक" उदाहरण जिसे हम देखेंगे वह मैट्रिक्स गुणन है। कार्यान्वयन के लिए, हम एक साधारण क्यूबिक मैट्रिक्स गुणन एल्गोरिदम लेंगे, न कि स्ट्रैसेन एल्गोरिदम, जिसका निष्पादन समय क्यूबिक ~O(n 2.807) के करीब है। दो मैट्रिक्स दिए गए हैं, एक एमएक्सडब्ल्यू मैट्रिक्स ए और एक डब्ल्यूएक्सएन मैट्रिक्स बी, निम्नलिखित प्रोग्राम उन्हें गुणा करेगा और परिणाम लौटाएगा, एक एमएक्सएन मैट्रिक्स सी:

शून्य मैट्रिक्सगुणा(int* A, int m, int w, int* B, int n, int* C) (for (int i = 0; i)< m; ++i) { for (int j = 0; j < n; ++j) { int sum = 0; for (int k = 0; k < w; ++k) { sum += A * B; } C = sum; } } }

इस कार्यान्वयन को समानांतर करने के कई तरीके हैं, और यदि आप नियमित प्रोसेसर पर चलने के लिए इस कोड को समानांतर करना चाहते हैं, तो बाहरी लूप को समानांतर करना सही विकल्प होगा। हालाँकि, GPU में काफी बड़ी संख्या में कोर हैं, और केवल बाहरी लूप को समानांतर करके, हम सभी कोर को काम से लोड करने के लिए पर्याप्त संख्या में नौकरियां नहीं बना पाएंगे। इसलिए, आंतरिक लूप को अछूता छोड़कर, दो बाहरी लूपों को समानांतर करना समझ में आता है:

शून्य मैट्रिक्स गुणन (int* A, int m, int w, int* B, int n, int* C) ( array_view एवीए(एम, डब्ल्यू, ए); array_view एवीबी(डब्ल्यू, एन, बी); array_view एवीसी(एम, एन, सी); avC.discard_data(); Parallel_for_each(avC.extent, [=](index<2>आईडीएक्स) प्रतिबंधित (एम्प) ( पूर्णांक योग = 0; के लिए (पूर्णांक के = 0; के< w; ++k) { sum + = avA(idx*w, k) * avB(k*w, idx); } avC = sum; }); }

यह कार्यान्वयन अभी भी मैट्रिक्स गुणन के अनुक्रमिक कार्यान्वयन और ऊपर दिए गए वेक्टर जोड़ उदाहरण से मिलता-जुलता है, सूचकांक के अपवाद के साथ, जो अब दो-आयामी है और ऑपरेटर का उपयोग करके आंतरिक लूप में पहुंच योग्य है। नियमित प्रोसेसर पर चलने वाले अनुक्रमिक विकल्प की तुलना में यह संस्करण कितना तेज़ है? 1024 x 1024 आकार के दो मैट्रिक्स (पूर्णांक) को गुणा करने पर, नियमित सीपीयू पर अनुक्रमिक संस्करण औसतन 7350 मिलीसेकंड लेता है, जबकि जीपीयू संस्करण - कसकर पकड़ें - 50 मिलीसेकंड लेता है, 147 गुना तेज!

कण गति अनुकरण

ऊपर प्रस्तुत GPU पर समस्याओं को हल करने के उदाहरणों में आंतरिक लूप का बहुत ही सरल कार्यान्वयन है। यह स्पष्ट है कि हमेशा ऐसा नहीं होगा। ऊपर लिंक किया गया नेटिव कॉनकरेंसी ब्लॉग, कणों के बीच गुरुत्वाकर्षण संबंधी अंतःक्रियाओं के मॉडलिंग का एक उदाहरण प्रदर्शित करता है। सिमुलेशन में अनंत संख्या में चरण शामिल होते हैं; प्रत्येक चरण पर, प्रत्येक कण के लिए त्वरण वेक्टर के तत्वों के नए मूल्यों की गणना की जाती है और फिर उनके नए निर्देशांक निर्धारित किए जाते हैं। यहां, कण वेक्टर को समानांतर किया गया है - पर्याप्त बड़ी संख्या में कणों (कई हजार और ऊपर से) के साथ, आप सभी जीपीयू कोर को काम के साथ लोड करने के लिए पर्याप्त बड़ी संख्या में कार्य बना सकते हैं।

एल्गोरिदम का आधार दो कणों के बीच बातचीत के परिणाम को निर्धारित करने का कार्यान्वयन है, जैसा कि नीचे दिखाया गया है, जिसे आसानी से जीपीयू में स्थानांतरित किया जा सकता है:

// यहां फ्लोट4 चार तत्वों वाले वेक्टर हैं // ऑपरेशन में शामिल कणों का प्रतिनिधित्व करते हुए शून्य बॉडीबॉडी_इंटरेक्शन (फ्लोट4 और त्वरण, कॉन्स्ट फ्लोट4 पी1, कॉन्स्ट फ्लोट4 पी2) प्रतिबंधित (एम्प) (फ्लोट4 डिस्ट = पी2 - पी1; // यहां कोई डब्ल्यू का उपयोग नहीं किया गया है) फ़्लोट absDist = dist.x*dist.x + dist.y*dist.y + dist.z*dist.z; फ़्लोट invDist = 1.0f / sqrt(absDist); फ़्लोट invDistCube = invDist*invDist* = dist* PARTICLE_MASS*invDistCube )

प्रत्येक मॉडलिंग चरण में प्रारंभिक डेटा कणों के निर्देशांक और वेग के साथ एक सरणी है, और गणना के परिणामस्वरूप, कणों के निर्देशांक और वेग के साथ एक नई सरणी बनाई जाती है:

संरचना कण (फ्लोट4 स्थिति, वेग; // कंस्ट्रक्टर का कार्यान्वयन, कॉपी कंस्ट्रक्टर और // ऑपरेटर = स्थान बचाने के लिए प्रतिबंधित (एम्प) के साथ); शून्य सिमुलेशन_स्टेप(सरणी और पिछला, सरणी और अगला, पूर्णांक निकाय) (सीमा<1>ext(निकायों); Parallel_for_each (ext, [&](index<1>आईडीएक्स) प्रतिबंधित (एम्प) (कण पी = पिछला; फ्लोट4 त्वरण (0, 0, 0, 0); के लिए (इंट बॉडी = 0; बॉडी< bodies; ++body) { bodybody_interaction (acceleration, p.position, previous.position); } p.velocity + = acceleration*DELTA_TIME; p.position + = p.velocity*DELTA_TIME; next = p; }); }

उपयुक्त ग्राफ़िकल इंटरफ़ेस की सहायता से, मॉडलिंग बहुत दिलचस्प हो सकती है। C++ AMP टीम द्वारा प्रदान किया गया पूरा उदाहरण नेटिव कॉन्करेंसी ब्लॉग पर पाया जा सकता है। Intel Core i7 प्रोसेसर और Geforce GT 740M ग्राफिक्स कार्ड के साथ मेरे सिस्टम पर, 10,000 कणों का सिमुलेशन नियमित प्रोसेसर पर चलने वाले अनुक्रमिक संस्करण का उपयोग करके ~ 2.5 एफपीएस (प्रति सेकंड कदम) पर चलता है, और अनुकूलित संस्करण का उपयोग करके 160 एफपीएस पर चलता है। GPU पर - प्रदर्शन में भारी वृद्धि।

इससे पहले कि हम इस अनुभाग को समाप्त करें, C++ AMP फ्रेमवर्क की एक और महत्वपूर्ण विशेषता है जो GPU पर चलने वाले कोड के प्रदर्शन को और बेहतर बना सकती है। जीपीयू समर्थन करते हैं प्रोग्राम योग्य डेटा कैश(अक्सर कॉल किया गया शारेड मेमोरी). इस कैश में संग्रहीत मान एक ही टाइल में निष्पादन के सभी थ्रेड द्वारा साझा किए जाते हैं। मेमोरी टाइलिंग के लिए धन्यवाद, C++ AMP फ्रेमवर्क पर आधारित प्रोग्राम ग्राफिक्स कार्ड मेमोरी से डेटा को मोज़ेक की साझा मेमोरी में पढ़ सकते हैं और फिर ग्राफिक्स कार्ड मेमोरी से डेटा को दोबारा लाए बिना निष्पादन के कई थ्रेड्स से इसे एक्सेस कर सकते हैं। मोज़ेक साझा मेमोरी तक पहुंच ग्राफ़िक्स कार्ड मेमोरी की तुलना में लगभग 10 गुना तेज़ है। दूसरे शब्दों में, आपके पास पढ़ते रहने के कारण हैं।

समानांतर लूप का टाइलयुक्त संस्करण प्रदान करने के लिए, Parallel_for_each विधि पारित की गई है डोमेन टाइलयुक्त_विस्तार, जो बहुआयामी सीमा ऑब्जेक्ट को बहुआयामी टाइल्स में विभाजित करता है, और टाइल_इंडेक्स लैम्ब्डा पैरामीटर, जो टाइल के भीतर थ्रेड की वैश्विक और स्थानीय आईडी निर्दिष्ट करता है। उदाहरण के लिए, एक 16x16 मैट्रिक्स को 2x2 टाइल्स में विभाजित किया जा सकता है (जैसा कि नीचे दी गई छवि में दिखाया गया है) और फिर इसे Parallel_for_each फ़ंक्शन में पास किया जा सकता है:

क्षेत्र<2>मैट्रिक्स(16,16); टाइलयुक्त_विस्तार<2,2>टाइल्डमैट्रिक्स = मैट्रिक्स.टाइल<2,2>(); पैरेलल_फॉर_एच(टाइल्डमैट्रिक्स, [=](टाइल_इंडेक्स<2,2>idx) प्रतिबंधित(amp) (//... ));

एक ही मोज़ेक से संबंधित निष्पादन के चार थ्रेडों में से प्रत्येक ब्लॉक में संग्रहीत डेटा को साझा कर सकता है।

मैट्रिसेस के साथ संचालन करते समय, मानक सूचकांक के बजाय, GPU कोर में<2>, जैसा कि ऊपर दिए गए उदाहरणों में है, आप उपयोग कर सकते हैं idx.global. स्थानीय टाइल वाली मेमोरी और स्थानीय इंडेक्स का उचित उपयोग महत्वपूर्ण प्रदर्शन लाभ प्रदान कर सकता है। एक ही टाइल में निष्पादन के सभी थ्रेड्स द्वारा साझा की गई टाइल मेमोरी को घोषित करने के लिए, स्थानीय चर को टाइल_स्टैटिक विनिर्देशक के साथ घोषित किया जा सकता है।

व्यवहार में, साझा मेमोरी को घोषित करने और निष्पादन के विभिन्न धागों में इसके अलग-अलग ब्लॉकों को आरंभ करने की तकनीक का अक्सर उपयोग किया जाता है:

Parallel_for_each(tiledMatrix, [=](tiled_index<2,2>आईडीएक्स) प्रतिबंधित (एम्प) ( // 32 बाइट्स ब्लॉक टाइल_स्टैटिक इंट लोकल में सभी थ्रेड्स द्वारा साझा किए जाते हैं; // निष्पादन के इस थ्रेड के लिए तत्व को एक मान निर्दिष्ट करें स्थानीय = 42; ));

जाहिर है, साझा मेमोरी के उपयोग से कोई भी लाभ केवल तभी प्राप्त किया जा सकता है जब इस मेमोरी तक पहुंच सिंक्रनाइज़ हो; अर्थात्, थ्रेड्स को तब तक मेमोरी तक नहीं पहुंचना चाहिए जब तक कि उनमें से किसी एक द्वारा इसे प्रारंभ नहीं किया गया हो। मोज़ेक में धागों का सिंक्रनाइज़ेशन वस्तुओं का उपयोग करके किया जाता है टाइल_बाधा(टीपीएल लाइब्रेरी से बैरियर क्लास की याद दिलाते हुए) - वे टाइल_बैरियर.वेट() विधि को कॉल करने के बाद ही निष्पादन जारी रख पाएंगे, जो नियंत्रण तभी लौटाएगा जब सभी थ्रेड्स ने टाइल_बैरियर.वेट को कॉल किया हो। उदाहरण के लिए:

Parallel_for_each(tiledMatrix, (tiled_index<2,2>आईडीएक्स) प्रतिबंधित (एम्प) ( // 32 बाइट्स ब्लॉक टाइल_स्टैटिक इंट लोकल में सभी थ्रेड्स द्वारा साझा किए जाते हैं; // निष्पादन के इस थ्रेड के लिए तत्व को एक मान निर्दिष्ट करें स्थानीय = 42; // idx.barrier टाइल_बैरियर का एक उदाहरण है idx.barrier.wait(); // अब यह थ्रेड "स्थानीय" ऐरे तक पहुंच सकता है, // निष्पादन के अन्य थ्रेड्स के इंडेक्स का उपयोग करके));

अब समय आ गया है कि आपने जो सीखा है उसे एक ठोस उदाहरण में तब्दील किया जाए। आइए टाइलिंग मेमोरी संगठन के उपयोग के बिना किए गए मैट्रिक्स गुणन के कार्यान्वयन पर वापस लौटें, और इसमें वर्णित अनुकूलन जोड़ें। आइए मान लें कि मैट्रिक्स का आकार 256 का गुणज है - यह हमें 16 x 16 ब्लॉक के साथ काम करने की अनुमति देगा, मैट्रिक्स की प्रकृति ब्लॉक-दर-ब्लॉक गुणन की अनुमति देती है, और हम इस सुविधा का लाभ उठा सकते हैं (वास्तव में, विभाजित करना)। ब्लॉकों में मैट्रिक्स मैट्रिक्स गुणन एल्गोरिथ्म का एक विशिष्ट अनुकूलन है, जो अधिक कुशल सीपीयू कैश उपयोग प्रदान करता है)।

इस तकनीक का सार इस प्रकार है। C i,j (परिणाम मैट्रिक्स में पंक्ति i और स्तंभ j में तत्व) को खोजने के लिए, आपको A i,* (पहली मैट्रिक्स की i-वीं पंक्ति) और B *,j (j) के बीच डॉट उत्पाद की गणना करने की आवश्यकता है -दूसरे मैट्रिक्स में वां कॉलम)। हालाँकि, यह पंक्ति और स्तंभ के आंशिक डॉट उत्पादों की गणना करने और फिर परिणामों का योग करने के बराबर है। हम इस तथ्य का उपयोग मैट्रिक्स गुणन एल्गोरिथ्म को टाइलिंग संस्करण में बदलने के लिए कर सकते हैं:

शून्य मैट्रिक्स मल्टीप्लाई(int* A, int m, int w, int* B, int n, int* C) ( array_view एवीए(एम, डब्ल्यू, ए); array_view एवीबी(डब्ल्यू, एन, बी); array_view एवीसी(एम, एन, सी); avC.discard_data(); Parallel_for_each(avC.extent.tile<16,16>(), [=](टाइल_इंडेक्स<16,16>आईडीएक्स) प्रतिबंधित (एम्प) ( पूर्णांक योग = 0; पूर्णांक लोकलरो = आईडीएक्स.लोकल, लोकलकॉल = आईडीएक्स.लोकल; के लिए (int k = 0; k

वर्णित अनुकूलन का सार यह है कि मोज़ेक में प्रत्येक धागा (16 x 16 ब्लॉक के लिए 256 धागे बनाए जाते हैं) मूल मैट्रिक्स ए और बी के टुकड़ों की 16 x 16 स्थानीय प्रतियों में अपने तत्व को आरंभ करता है। मोज़ेक में प्रत्येक धागे की आवश्यकता होती है इन ब्लॉकों की केवल एक पंक्ति और एक स्तंभ, लेकिन सभी धागे एक साथ प्रत्येक पंक्ति और प्रत्येक स्तंभ तक 16 बार पहुँचेंगे। यह दृष्टिकोण मुख्य मेमोरी तक पहुंच की संख्या को काफी कम कर देता है।

परिणाम मैट्रिक्स में तत्व (i,j) की गणना करने के लिए, एल्गोरिदम को पहले मैट्रिक्स की पूरी i-वीं पंक्ति और दूसरे मैट्रिक्स के j-वें कॉलम की आवश्यकता होती है। जब धागे को आरेख में दर्शाया गया है और k=0 16x16 टाइलिंग है, तो पहले और दूसरे मैट्रिक्स में छायांकित क्षेत्रों को साझा मेमोरी में पढ़ा जाएगा। परिणाम मैट्रिक्स में निष्पादन थ्रेड कंप्यूटिंग तत्व (i,j) मूल मैट्रिक्स के i-वें पंक्ति और j-वें कॉलम से पहले k तत्वों के आंशिक डॉट उत्पाद की गणना करेगा।

इस उदाहरण में, टाइल वाले संगठन का उपयोग करने से प्रदर्शन में भारी वृद्धि होती है। मैट्रिक्स गुणन का टाइल वाला संस्करण साधारण संस्करण की तुलना में बहुत तेज़ है, इसमें लगभग 17 मिलीसेकंड (उसी 1024 x 1024 इनपुट मैट्रिक्स के लिए) लगता है, जो पारंपरिक प्रोसेसर पर चलने वाले संस्करण की तुलना में 430 गुना तेज़ है!

इससे पहले कि हम C++ AMP फ्रेमवर्क की अपनी चर्चा समाप्त करें, हम डेवलपर्स के लिए उपलब्ध टूल (विज़ुअल स्टूडियो में) का उल्लेख करना चाहेंगे। विजुअल स्टूडियो 2012 एक ग्राफिक्स प्रोसेसिंग यूनिट (जीपीयू) डिबगर प्रदान करता है जो आपको ब्रेकप्वाइंट सेट करने, कॉल स्टैक की जांच करने और स्थानीय चर मानों को पढ़ने और बदलने की सुविधा देता है (कुछ एक्सेलेरेटर सीधे जीपीयू डिबगिंग का समर्थन करते हैं; दूसरों के लिए, विजुअल स्टूडियो एक सॉफ्टवेयर सिम्युलेटर का उपयोग करता है) , और एक प्रोफाइलर जो आपको GPU का उपयोग करके समानांतर संचालन से किसी एप्लिकेशन को मिलने वाले लाभों का मूल्यांकन करने देता है। विज़ुअल स्टूडियो में डिबगिंग क्षमताओं के बारे में अधिक जानकारी के लिए, वॉकथ्रू आलेख देखें। MSDN पर C++ AMP एप्लिकेशन को डिबग करना।

.NET में GPU कंप्यूटिंग विकल्प

हालाँकि इस आलेख ने अभी तक केवल C++ में उदाहरण दिखाए हैं, प्रबंधित अनुप्रयोगों में GPU की शक्ति का उपयोग करने के कई तरीके हैं। एक तरीका इंटरॉप टूल का उपयोग करना है जो आपको GPU कोर के साथ निम्न-स्तरीय C++ घटकों पर काम करने की अनुमति देता है। यह समाधान उन लोगों के लिए बहुत अच्छा है जो C++ AMP फ्रेमवर्क का उपयोग करना चाहते हैं या प्रबंधित अनुप्रयोगों में पूर्व-निर्मित C++ AMP घटकों का उपयोग करने की क्षमता रखते हैं।

दूसरा तरीका ऐसी लाइब्रेरी का उपयोग करना है जो प्रबंधित कोड से सीधे GPU के साथ काम करती है। वर्तमान में ऐसे कई पुस्तकालय हैं। उदाहरण के लिए, GPU.NET और CUDAfy.NET (दोनों व्यावसायिक पेशकश)। नीचे GPU.NET GitHub रिपॉजिटरी से दो वैक्टर के डॉट उत्पाद के कार्यान्वयन को प्रदर्शित करने वाला एक उदाहरण दिया गया है:

सार्वजनिक स्थैतिक शून्य मल्टीप्लीएडजीपीयू (डबल ए, डबल बी, डबल सी) (इंट थ्रेडआईडी = ब्लॉकडिमेंशन.एक्स * ब्लॉकइंडेक्स.एक्स + थ्रेडइंडेक्स.एक्स; इंट टोटलथ्रेड्स = ब्लॉकडिमेंशन.एक्स * ग्रिडडिमेंशन.एक्स; फॉर (इंट एलिमेंटआईडीएक्स = थ्रेडआईडी; एलिमेंटआईडीएक्स)

मेरी राय है कि लाइब्रेरी स्तर पर इंटरैक्शन को व्यवस्थित करने या आईएल भाषा में महत्वपूर्ण बदलाव करने की तुलना में भाषा एक्सटेंशन (सी ++ एएमपी पर आधारित) सीखना बहुत आसान और अधिक कुशल है।

इसलिए, जब हमने .NET में समानांतर प्रोग्रामिंग और GPU का उपयोग करने की संभावनाओं को देखा, तो किसी को संदेह नहीं हुआ कि समानांतर कंप्यूटिंग का आयोजन उत्पादकता बढ़ाने का एक महत्वपूर्ण तरीका है। दुनिया भर के कई सर्वरों और वर्कस्टेशनों में, सीपीयू और जीपीयू की अमूल्य प्रसंस्करण शक्ति अप्रयुक्त हो जाती है क्योंकि एप्लिकेशन इसका उपयोग ही नहीं करते हैं।

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

C++ AMP फ्रेमवर्क और अन्य बहुउद्देश्यीय GPU समानांतर कंप्यूटिंग लाइब्रेरी का उपयोग सैकड़ों GPU कोर में गणनाओं को समानांतर करने के लिए सफलतापूर्वक किया जा सकता है। अंत में, क्लाउड वितरित कंप्यूटिंग प्रौद्योगिकियों के उपयोग से उत्पादकता लाभ प्राप्त करने का एक पहले से अज्ञात अवसर है, जो हाल ही में सूचना प्रौद्योगिकी के विकास में मुख्य दिशाओं में से एक बन गया है।

AMD/ATI Radeon आर्किटेक्चर की विशेषताएं

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

आइए हम और उपमाएँ बनाएं - भूमि पर लंबे विकास के बाद, स्तनधारी समुद्र में घुस गए, जहाँ उन्होंने सामान्य समुद्री निवासियों को विस्थापित कर दिया। प्रतियोगिता में, स्तनधारियों ने पृथ्वी की सतह पर दिखाई देने वाली नई उन्नत क्षमताओं और विशेष रूप से पानी में जीवन के अनुकूलन के लिए हासिल की गई क्षमताओं का उपयोग किया। इसी तरह, 3डी ग्राफिक्स के लिए आर्किटेक्चर की ताकत के आधार पर जीपीयू, गैर-ग्राफिक्स कार्यों के लिए उपयोगी विशेष कार्यक्षमता को तेजी से जोड़ रहे हैं।

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

GPU में कई दर्जन (Nvidia GT200 के लिए 30, Evergreen के लिए 20, Fermi के लिए 16) प्रोसेसर कोर होते हैं, जिन्हें Nvidia शब्दावली में स्ट्रीमिंग मल्टीप्रोसेसर और ATI शब्दावली में SIMD इंजन कहा जाता है। इस लेख के प्रयोजनों के लिए, हम उन्हें मिनीप्रोसेसर कहेंगे, क्योंकि वे कई सौ प्रोग्राम थ्रेड निष्पादित करते हैं और लगभग वह सब कुछ कर सकते हैं जो एक नियमित सीपीयू कर सकता है, लेकिन फिर भी सब कुछ नहीं।

विपणन नाम भ्रमित करने वाले हैं - अधिक महत्व के लिए, वे कार्यात्मक मॉड्यूल की संख्या दर्शाते हैं जो घटा और गुणा कर सकते हैं: उदाहरण के लिए, 320 वेक्टर "कोर"। ये गुठलियाँ अनाज की तरह अधिक होती हैं। जीपीयू को एक प्रकार के मल्टी-कोर प्रोसेसर के रूप में सोचना बेहतर है जिसमें बड़ी संख्या में कोर एक साथ कई थ्रेड निष्पादित करते हैं।

प्रत्येक मिनीप्रोसेसर में स्थानीय मेमोरी होती है, GT200 के लिए 16 KB, एवरग्रीन के लिए 32 KB और फर्मी के लिए 64 KB (अनिवार्य रूप से एक प्रोग्रामयोग्य L1 कैश)। इसका एक्सेस समय पारंपरिक सीपीयू के पहले स्तर के कैश के समान है और यह कार्यात्मक मॉड्यूल में डेटा की सबसे तेज़ डिलीवरी के लिए समान कार्य करता है। फर्मी आर्किटेक्चर में, स्थानीय मेमोरी के हिस्से को नियमित कैश के रूप में कॉन्फ़िगर किया जा सकता है। जीपीयू में, स्थानीय मेमोरी का उपयोग निष्पादित थ्रेड्स के बीच तेजी से डेटा विनिमय के लिए किया जाता है। GPU प्रोग्राम की सामान्य योजनाओं में से एक इस प्रकार है: सबसे पहले, GPU वैश्विक मेमोरी से डेटा को स्थानीय मेमोरी में लोड किया जाता है। यह केवल सामान्य वीडियो मेमोरी है, जो "अपने" प्रोसेसर से अलग (सिस्टम मेमोरी की तरह) स्थित होती है - वीडियो के मामले में, यह वीडियो कार्ड के पीसीबी पर कई चिप्स द्वारा सोल्डर की जाती है। इसके बाद, कई सौ थ्रेड स्थानीय मेमोरी में इस डेटा के साथ काम करते हैं और परिणाम को वैश्विक मेमोरी में लिखते हैं, जिसके बाद इसे सीपीयू में स्थानांतरित किया जाता है। स्थानीय मेमोरी से डेटा लोड करने और अनलोड करने के लिए निर्देश लिखना प्रोग्रामर की ज़िम्मेदारी है। अनिवार्य रूप से, यह समानांतर प्रसंस्करण के लिए [एक विशिष्ट कार्य] डेटा का विभाजन कर रहा है। जीपीयू मेमोरी में परमाणु लिखने/पढ़ने के निर्देशों का भी समर्थन करता है, लेकिन वे अप्रभावी हैं और आमतौर पर सभी मिनीप्रोसेसरों के गणना परिणामों को "एक साथ चिपकाने" के लिए अंतिम चरण में इसकी आवश्यकता होती है।

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

और GPU की एक और महत्वपूर्ण विशेषता: "सॉफ्ट" वैश्वीकरण। प्रत्येक मिनीप्रोसेसर में बड़ी संख्या में कंप्यूट मॉड्यूल होते हैं (GT200 के लिए 8, Radeon के लिए 16 और Fermi के लिए 32), लेकिन वे सभी समान प्रोग्राम पते के साथ केवल एक ही निर्देश निष्पादित कर सकते हैं। इस मामले में, ऑपरेंड अलग-अलग हो सकते हैं, अलग-अलग थ्रेड के अपने-अपने होते हैं। उदाहरण के लिए, निर्देश दो रजिस्टरों की सामग्री जोड़ें: इसे सभी कंप्यूटिंग उपकरणों द्वारा एक साथ निष्पादित किया जाता है, लेकिन रजिस्टर अलग-अलग लिए जाते हैं। यह माना जाता है कि GPU प्रोग्राम के सभी थ्रेड, समानांतर डेटा प्रोसेसिंग करते हुए, आम तौर पर प्रोग्राम कोड के माध्यम से एक समानांतर पाठ्यक्रम में चलते हैं। इस प्रकार, सभी कंप्यूटिंग मॉड्यूल समान रूप से लोड होते हैं। और यदि प्रोग्राम में शाखाओं के कारण थ्रेड्स अपने कोड निष्पादन पथ में भिन्न हो जाते हैं, तो तथाकथित क्रमांकन होता है। तब सभी कंप्यूटिंग मॉड्यूल का उपयोग नहीं किया जाता है, क्योंकि थ्रेड निष्पादन के लिए विभिन्न निर्देश प्रस्तुत करते हैं, और कंप्यूटिंग मॉड्यूल का एक ब्लॉक निष्पादित कर सकता है, जैसा कि हमने पहले ही कहा है, केवल एक पते के साथ एक निर्देश। और, ज़ाहिर है, उत्पादकता अधिकतम के सापेक्ष गिर जाती है।

लाभ यह है कि वैश्वीकरण पूरी तरह से स्वचालित है, यह एसएसई, एमएमएक्स इत्यादि का उपयोग करके प्रोग्रामिंग नहीं है। और GPU स्वयं विसंगतियों को संभालता है। सैद्धांतिक रूप से, आप आमतौर पर निष्पादन मॉड्यूल की वेक्टर प्रकृति के बारे में सोचे बिना जीपीयू के लिए प्रोग्राम लिख सकते हैं, लेकिन ऐसे प्रोग्राम की गति बहुत अधिक नहीं होगी। नकारात्मक पक्ष वेक्टर की बड़ी चौड़ाई है। यह कार्यात्मक मॉड्यूल की नाममात्र संख्या से बड़ा है और एनवीडिया जीपीयू के लिए 32 और Radeon के लिए 64 है। धागों को उचित आकार के ब्लॉकों में संसाधित किया जाता है। एनवीडिया थ्रेड्स के इस ब्लॉक को वॉर्प शब्द कहता है, एएमडी इसे वेव फ्रंट कहता है, जो एक ही बात है। इस प्रकार, 16 कंप्यूटिंग उपकरणों पर, 64 थ्रेड्स की लंबाई वाले "वेवफ्रंट" को चार घड़ी चक्रों (सामान्य निर्देश लंबाई मानते हुए) में संसाधित किया जाता है। समुद्री शब्द वार्प के साथ जुड़ाव के कारण, लेखक इस मामले में वार्प शब्द को प्राथमिकता देता है, जिसका अर्थ है मुड़ी हुई रस्सियों से एक साथ बंधी हुई रस्सी। तो धागे "मुड़" जाते हैं और एक ठोस बंडल बनाते हैं। हालाँकि, "वेव फ्रंट" को समुद्र के साथ भी जोड़ा जा सकता है: निर्देश उसी तरह से एक्चुएटर्स तक पहुंचते हैं जैसे लहरें एक के बाद एक किनारे पर आती हैं।

यदि सभी थ्रेड प्रोग्राम निष्पादन में समान रूप से उन्नत हैं (एक ही स्थान पर स्थित हैं) और इस प्रकार एक ही निर्देश निष्पादित कर रहे हैं, तो सब कुछ ठीक है, लेकिन यदि नहीं, तो मंदी होती है। इस मामले में, एक वार्प या वेव फ्रंट से थ्रेड्स प्रोग्राम में अलग-अलग स्थानों पर स्थित होते हैं, उन्हें थ्रेड्स के समूहों में विभाजित किया जाता है जिनका निर्देश संख्या मान समान होता है (दूसरे शब्दों में, निर्देश सूचक)। और केवल एक समूह के थ्रेड्स को एक समय में निष्पादित किया जाता है - सभी एक ही निर्देश को निष्पादित करते हैं, लेकिन विभिन्न ऑपरेंड के साथ। परिणामस्वरूप, वार्प जितने समूहों में विभाजित है उससे कई गुना धीमी गति से चलता है, और समूह में धागों की संख्या कोई मायने नहीं रखती। भले ही समूह में केवल एक थ्रेड हो, फिर भी इसे पूर्ण वार्प के रूप में निष्पादित होने में उतना ही समय लगेगा। हार्डवेयर में, इसे कुछ थ्रेड्स को मास्क करके लागू किया जाता है, यानी निर्देशों को औपचारिक रूप से निष्पादित किया जाता है, लेकिन उनके निष्पादन के परिणाम कहीं भी रिकॉर्ड नहीं किए जाते हैं और भविष्य में उपयोग नहीं किए जाते हैं।

हालाँकि किसी भी समय प्रत्येक मिनीप्रोसेसर (स्ट्रीमिंग मल्टीप्रोसेसर या SIMD इंजन) केवल एक वार्प (थ्रेड्स का एक गुच्छा) से संबंधित निर्देशों को निष्पादित करता है, इसके निष्पादन पूल में कई दर्जन सक्रिय वार्प होते हैं। एक वार्प के निर्देशों को निष्पादित करने के बाद, मिनीप्रोसेसर इस वार्प के थ्रेड्स के अगले निर्देश को नहीं, बल्कि किसी अन्य वार्प के निर्देशों को निष्पादित करता है। वह वार्प प्रोग्राम में बिल्कुल अलग जगह पर हो सकता है, इससे गति प्रभावित नहीं होगी, क्योंकि केवल वार्प के अंदर ही पूरी गति से निष्पादन के लिए सभी थ्रेड्स के निर्देश समान होने चाहिए।

इस मामले में, 20 SIMD इंजनों में से प्रत्येक में चार सक्रिय तरंग मोर्चे हैं, प्रत्येक में 64 धागे हैं। प्रत्येक धागे को एक छोटी रेखा द्वारा दर्शाया गया है। कुल: 64×4×20=5120 धागे

इस प्रकार, यह देखते हुए कि प्रत्येक ताना या तरंग मोर्चे में 32-64 धागे होते हैं, मिनीप्रोसेसर में कई सौ सक्रिय धागे होते हैं जो लगभग एक साथ निष्पादित होते हैं। नीचे हम देखेंगे कि इतनी बड़ी संख्या में समानांतर धागे किस वास्तुशिल्प लाभ का वादा करते हैं, लेकिन पहले हम इस बात पर विचार करेंगे कि जीपीयू बनाने वाले मिनीप्रोसेसर की क्या सीमाएँ हैं।

मुख्य बात यह है कि जीपीयू में कोई स्टैक नहीं है जहां फ़ंक्शन पैरामीटर और स्थानीय चर संग्रहीत किए जा सकें। बड़ी संख्या में धागों के कारण, चिप पर स्टैक के लिए कोई जगह नहीं होती है। दरअसल, चूंकि जीपीयू एक साथ लगभग 10,000 थ्रेड निष्पादित करता है, 100 केबी के एक थ्रेड के स्टैक आकार के साथ, कुल वॉल्यूम 1 जीबी होगा, जो सभी वीडियो मेमोरी की मानक मात्रा के बराबर है। इसके अलावा, GPU कोर में किसी भी महत्वपूर्ण आकार का स्टैक रखने का कोई तरीका नहीं है। उदाहरण के लिए, यदि आप एक थ्रेड पर 1000 बाइट स्टैक रखते हैं, तो केवल एक मिनीप्रोसेसर को 1 एमबी मेमोरी की आवश्यकता होगी, जो कि मिनीप्रोसेसर की स्थानीय मेमोरी और रजिस्टरों को संग्रहीत करने के लिए आवंटित मेमोरी की संयुक्त मात्रा का लगभग पांच गुना है।

इसलिए, GPU प्रोग्राम में कोई रिकर्सन नहीं होता है, और फ़ंक्शन कॉल के साथ बहुत कुछ करने को नहीं होता है। प्रोग्राम संकलित करते समय सभी फ़ंक्शन सीधे कोड में डाले जाते हैं। यह GPU अनुप्रयोगों के दायरे को कम्प्यूटेशनल-प्रकार के कार्यों तक सीमित करता है। ज्ञात छोटी पुनरावृत्ति गहराई के साथ रिकर्सन एल्गोरिदम के लिए वैश्विक मेमोरी का उपयोग करके सीमित स्टैक इम्यूलेशन का उपयोग करना कभी-कभी संभव होता है, लेकिन यह एक विशिष्ट जीपीयू एप्लिकेशन नहीं है। ऐसा करने के लिए, विशेष रूप से एक एल्गोरिदम विकसित करना और सीपीयू की तुलना में सफल त्वरण की गारंटी के बिना इसके कार्यान्वयन की संभावना का पता लगाना आवश्यक है।

फर्मी ने पहली बार वर्चुअल फ़ंक्शंस का उपयोग करने की क्षमता पेश की, लेकिन फिर भी उनका उपयोग प्रत्येक थ्रेड के लिए बड़े, तेज़ कैश की कमी के कारण सीमित है। 1536 थ्रेड 48 केबी या एल1 के 16 केबी के लिए जिम्मेदार हैं, यानी, किसी प्रोग्राम में वर्चुअल फ़ंक्शंस का उपयोग अपेक्षाकृत कम ही किया जा सकता है, अन्यथा स्टैक धीमी वैश्विक मेमोरी का भी उपयोग करेगा, जो निष्पादन को धीमा कर देगा और, सबसे अधिक संभावना है, लाभ नहीं लाएगा। सीपीयू संस्करण की तुलना में।

इस प्रकार, जीपीयू को एक कंप्यूटिंग कोप्रोसेसर के रूप में दर्शाया जाता है जिसमें डेटा लोड किया जाता है, इसे कुछ एल्गोरिदम द्वारा संसाधित किया जाता है, और परिणाम तैयार किया जाता है।

वास्तु लाभ

लेकिन यह GPU की गणना बहुत तेजी से करता है। और इसकी उच्च मल्टीथ्रेडिंग इसमें मदद करती है। बड़ी संख्या में सक्रिय थ्रेड्स अलग से स्थित वैश्विक वीडियो मेमोरी की उच्च विलंबता को आंशिक रूप से छिपाना संभव बनाते हैं, जो लगभग 500 घड़ी चक्र है। अंकगणितीय परिचालनों के उच्च घनत्व वाले कोड के लिए इसे विशेष रूप से अच्छी तरह से समतल किया गया है। इस प्रकार, ट्रांजिस्टर-महंगी L1-L2-L3 कैश पदानुक्रम की आवश्यकता नहीं है। इसके बजाय, कई कंप्यूट मॉड्यूल को चिप पर रखा जा सकता है, जो उत्कृष्ट अंकगणितीय प्रदर्शन प्रदान करता है। जबकि एक थ्रेड या वार्प के निर्देशों को क्रियान्वित किया जा रहा है, शेष सैकड़ों थ्रेड चुपचाप अपने डेटा की प्रतीक्षा कर रहे हैं।

फर्मी ने लगभग 1 एमबी आकार का एल2 कैश पेश किया, लेकिन इसकी तुलना आधुनिक प्रोसेसर के कैश से नहीं की जा सकती, यह कोर और विभिन्न सॉफ्टवेयर ट्रिक्स के बीच संचार के लिए अधिक लक्षित है। यदि इसके आकार को सभी दसियों हज़ार धागों में विभाजित किया जाए, तो प्रत्येक का आयतन बहुत नगण्य होगा।

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

हम तुरंत कह सकते हैं कि यदि जीपीयू में बड़ी संख्या में समानांतर धागे उपलब्ध नहीं कराए गए हैं, तो इसका प्रदर्शन लगभग शून्य होगा, क्योंकि यह पूरी तरह से लोड होने पर उसी गति से काम करेगा, और बहुत कम काम करेगा। उदाहरण के लिए, 10,000 के बजाय केवल एक थ्रेड होने दें: प्रदर्शन लगभग एक हजार गुना कम हो जाएगा, क्योंकि न केवल सभी ब्लॉक लोड नहीं होंगे, बल्कि सभी विलंबताएं भी प्रभावित होंगी।

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

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

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

उदाहरण

जीपीयू के लिए सबसे क्लासिक समस्याओं में से एक गुरुत्वाकर्षण क्षेत्र बनाने वाले एन निकायों की बातचीत की गणना करने की समस्या है। लेकिन, उदाहरण के लिए, अगर हमें पृथ्वी-चंद्रमा-सूर्य प्रणाली के विकास की गणना करने की आवश्यकता है, तो GPU हमारे लिए एक बुरी मदद है: कुछ वस्तुएं हैं। प्रत्येक वस्तु के लिए, अन्य सभी वस्तुओं के साथ अंतःक्रिया की गणना करना आवश्यक है, और उनमें से केवल दो हैं। सभी ग्रहों और उनके चंद्रमाओं (लगभग कुछ सौ वस्तुओं) के साथ सौर मंडल की गति के मामले में, GPU अभी भी बहुत कुशल नहीं है। हालाँकि, थ्रेड प्रबंधन के उच्च ओवरहेड के कारण, एक मल्टी-कोर प्रोसेसर भी अपनी सारी शक्ति प्रदर्शित करने में सक्षम नहीं होगा और सिंगल-थ्रेडेड मोड में काम करेगा। लेकिन अगर आपको धूमकेतु और क्षुद्रग्रह बेल्ट वस्तुओं के प्रक्षेप पथ की गणना करने की भी आवश्यकता है, तो यह पहले से ही GPU के लिए एक कार्य है, क्योंकि आवश्यक संख्या में समानांतर गणना थ्रेड बनाने के लिए पर्याप्त वस्तुएं हैं।

यदि आपको सैकड़ों-हजारों तारों के गोलाकार समूहों की टक्कर की गणना करने की आवश्यकता है तो GPU भी अच्छा प्रदर्शन करेगा।

एन-बॉडी समस्या में जीपीयू पावर का उपयोग करने का एक और अवसर तब उत्पन्न होता है जब आपको कई व्यक्तिगत समस्याओं की गणना करने की आवश्यकता होती है, भले ही कम संख्या में बॉडी के साथ। उदाहरण के लिए, यदि आपको प्रारंभिक वेगों के लिए विभिन्न विकल्पों के लिए एक प्रणाली के विकास के लिए विकल्पों की गणना करने की आवश्यकता है। तब आप बिना किसी समस्या के प्रभावी ढंग से GPU का उपयोग कर सकते हैं।

AMD Radeon माइक्रोआर्किटेक्चर विवरण

हमने जीपीयू संगठन के बुनियादी सिद्धांतों को देखा; वे सभी निर्माताओं के वीडियो त्वरक के लिए सामान्य हैं, क्योंकि शुरू में उनका एक लक्ष्य कार्य था - शेडर प्रोग्राम। हालाँकि, निर्माताओं को माइक्रोआर्किटेक्चरल कार्यान्वयन के विवरण पर मतभेद करने का अवसर मिला है। हालाँकि विभिन्न विक्रेताओं के सीपीयू कभी-कभी बहुत भिन्न होते हैं, भले ही वे संगत हों, जैसे पेंटियम 4 और एथलॉन या कोर। एनवीडिया आर्किटेक्चर पहले से ही काफी व्यापक रूप से जाना जाता है, अब हम Radeon को देखेंगे और इन विक्रेताओं के दृष्टिकोण में मुख्य अंतर पर प्रकाश डालेंगे।

एएमडी वीडियो कार्ड को एवरग्रीन परिवार से शुरू करके सामान्य प्रयोजन कंप्यूटिंग के लिए पूर्ण समर्थन प्राप्त हुआ, जिसने पहली बार 47xx परिवार के डायरेक्टएक्स 11 विनिर्देशों को भी लागू किया, जिसमें कई महत्वपूर्ण सीमाएं हैं, जिन पर नीचे चर्चा की जाएगी।

स्थानीय मेमोरी के आकार में अंतर (Radeon के लिए 32 KB बनाम GT200 के लिए 16 KB और Fermi के लिए 64 KB) आम तौर पर महत्वपूर्ण नहीं हैं। साथ ही एएमडी के लिए वेव फ्रंट साइज 64 थ्रेड्स बनाम एनवीडिया के लिए 32 थ्रेड्स है। लगभग किसी भी GPU प्रोग्राम को इन मापदंडों के अनुसार आसानी से पुन: कॉन्फ़िगर और समायोजित किया जा सकता है। प्रदर्शन दसियों प्रतिशत तक बदल सकता है, लेकिन जीपीयू के मामले में यह इतना महत्वपूर्ण नहीं है, क्योंकि एक जीपीयू प्रोग्राम आमतौर पर अपने सीपीयू समकक्ष की तुलना में दस गुना धीमी गति से चलता है, या दस गुना तेज, या बिल्कुल भी काम नहीं करता है।

एएमडी द्वारा वीएलआईडब्ल्यू (वेरी लॉन्ग इंस्ट्रक्शन वर्ड) तकनीक का उपयोग अधिक महत्वपूर्ण है। एनवीडिया स्केलर सरल निर्देशों का उपयोग करता है जो स्केलर रजिस्टरों पर काम करते हैं। इसके त्वरक सरल शास्त्रीय आरआईएससी को लागू करते हैं। AMD वीडियो कार्ड में रजिस्टरों की संख्या GT200 के समान ही होती है, लेकिन रजिस्टर 128-बिट वेक्टर होते हैं। प्रत्येक वीएलआईडब्ल्यू निर्देश कई चार-घटक 32-बिट रजिस्टरों पर काम करता है, जो एसएसई के समान है, लेकिन वीएलआईडब्ल्यू में बहुत अधिक क्षमताएं हैं। यह SSE की तरह SIMD (सिंगल इंस्ट्रक्शन मल्टीपल डेटा) नहीं है - यहां ऑपरेंड के प्रत्येक जोड़े के लिए निर्देश अलग-अलग और निर्भर भी हो सकते हैं! उदाहरण के लिए, मान लें कि रजिस्टर A के घटकों को a1, a2, a3, a4 कहा जाता है; रजिस्टर बी समान है. एक एकल निर्देश के साथ गणना की जा सकती है जो एक घड़ी चक्र में निष्पादित होता है, उदाहरण के लिए, संख्या a1×b1+a2×b2+a3×b3+a4×b4 या एक द्वि-आयामी वेक्टर (a1×b1+a2×b2, a3 ×b3+a4×b4 ).

यह सीपीयू की तुलना में जीपीयू की कम आवृत्ति और हाल के वर्षों में प्रक्रिया प्रौद्योगिकी में मजबूत कमी के कारण संभव हुआ। इस मामले में, किसी अनुसूचक की आवश्यकता नहीं है; लगभग हर चीज़ एक घड़ी चक्र में निष्पादित होती है।

वेक्टर निर्देशों के लिए धन्यवाद, Radeon का चरम एकल-सटीक प्रदर्शन बहुत अधिक है, जो टेराफ्लॉप्स तक पहुंचता है।

एक वेक्टर रजिस्टर चार एकल सटीक संख्याओं के बजाय एक दोहरी सटीक संख्या संग्रहीत कर सकता है। और एक वीएलआईडब्ल्यू निर्देश या तो दोहरी संख्याओं के दो जोड़े जोड़ सकता है, या दो संख्याओं को गुणा कर सकता है, या दो संख्याओं को गुणा कर सकता है और तीसरी के साथ जोड़ सकता है। इस प्रकार, डबल में चरम प्रदर्शन फ्लोट की तुलना में लगभग पांच गुना कम है। पुराने Radeon मॉडल के लिए, यह नए Fermi आर्किटेक्चर पर Nvidia Tesla के प्रदर्शन से मेल खाता है और GT200 आर्किटेक्चर पर डबल कार्ड के प्रदर्शन से बहुत अधिक है। फर्मी-आधारित Geforce उपभोक्ता वीडियो कार्ड में, दोहरी गणना की अधिकतम गति चार गुना कम कर दी गई है।


Radeon ऑपरेशन का योजनाबद्ध आरेख। समानांतर में चलने वाले 20 में से केवल एक मिनीप्रोसेसर प्रस्तुत किया गया है

सीपीयू निर्माताओं (मुख्य रूप से x86-संगत वाले) के विपरीत, जीपीयू निर्माता संगतता मुद्दों से बंधे नहीं हैं। एक GPU प्रोग्राम को पहले कुछ मध्यवर्ती कोड में संकलित किया जाता है, और जब प्रोग्राम चलता है, तो ड्राइवर इस कोड को मॉडल-विशिष्ट मशीन निर्देशों में संकलित करता है। जैसा कि ऊपर वर्णित है, जीपीयू निर्माताओं ने अपने जीपीयू के लिए सुविधाजनक आईएसए (इंस्ट्रक्शन सेट आर्किटेक्चर) के साथ आकर और उन्हें पीढ़ी-दर-पीढ़ी बदलते हुए इसका लाभ उठाया है। किसी भी स्थिति में, डिकोडर की अनुपस्थिति (अनावश्यक) के कारण इसमें प्रदर्शन का कुछ प्रतिशत जोड़ा गया। लेकिन एएमडी मशीन कोड में निर्देशों को व्यवस्थित करने के लिए अपने स्वयं के प्रारूप के साथ आगे बढ़ गया। उन्हें क्रमिक रूप से (कार्यक्रम सूची के अनुसार) नहीं, बल्कि खंडों में व्यवस्थित किया गया है।

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

सशर्त कूद अनुदेश अनुभाग
धारा 0शाखा 0सतत अंकगणितीय निर्देशों के अनुभाग 3 से लिंक करें
खंड 1शाखा 1अनुभाग संख्या 4 से लिंक करें
धारा 2शाखा 2अनुभाग संख्या 5 से लिंक करें
सतत अंकगणित निर्देश अनुभाग
धारा 3वीएलआईडब्ल्यू निर्देश 0वीएलआईडब्ल्यू अनुदेश 1वीएलआईडब्ल्यू निर्देश 2वीएलआईडब्ल्यू अनुदेश 3
धारा 4वीएलआईडब्ल्यू अनुदेश 4वीएलआईडब्ल्यू निर्देश 5
धारा 5वीएलआईडब्ल्यू अनुदेश 6वीएलआईडब्ल्यू अनुदेश 7वीएलआईडब्ल्यू अनुदेश 8वीएलआईडब्ल्यू अनुदेश 9

एनवीडिया और एएमडी दोनों के जीपीयू में कुछ घड़ी चक्रों में एकल-सटीक संख्याओं के लिए बुनियादी गणित कार्यों, वर्गमूल, घातांक, लघुगणक, साइन और कोसाइन की त्वरित गणना करने के लिए अंतर्निहित निर्देश हैं। इसके लिए विशेष कंप्यूटिंग इकाइयाँ हैं। वे ज्योमेट्री शेडर्स में इन कार्यों के तेजी से सन्निकटन को लागू करने की आवश्यकता से "उत्पन्न" होते हैं।

यहां तक ​​कि अगर किसी को यह नहीं पता था कि जीपीयू का उपयोग ग्राफिक्स के लिए किया जाता है, और केवल तकनीकी विशेषताओं को पढ़ता है, तो इस संकेत से वह अनुमान लगा सकता है कि ये कंप्यूटिंग कोप्रोसेसर वीडियो त्वरक से उत्पन्न हुए हैं। इसी तरह, समुद्री स्तनधारियों के कुछ लक्षणों के आधार पर, वैज्ञानिकों ने महसूस किया कि उनके पूर्वज भूमि जीव थे।

लेकिन एक अधिक स्पष्ट विशेषता जो डिवाइस की ग्राफिकल उत्पत्ति का खुलासा करती है वह है बिलिनियर इंटरपोलेशन के समर्थन के साथ 2डी और 3डी बनावट पढ़ने वाली इकाइयां। वे GPU कार्यक्रमों में व्यापक रूप से उपयोग किए जाते हैं, क्योंकि वे केवल-पढ़ने योग्य डेटा सरणियों की त्वरित और सरलीकृत रीडिंग प्रदान करते हैं। जीपीयू एप्लिकेशन के मानक व्यवहारों में से एक स्रोत डेटा के सरणियों को पढ़ना, उन्हें कंप्यूटिंग कोर में संसाधित करना और परिणाम को दूसरे ऐरे में लिखना है, जिसे फिर सीपीयू में वापस स्थानांतरित कर दिया जाता है। यह योजना मानक और सामान्य है क्योंकि यह GPU आर्किटेक्चर के लिए सुविधाजनक है। ऐसे कार्य जिनमें वैश्विक मेमोरी के एक बड़े क्षेत्र में गहन पढ़ने और लिखने की आवश्यकता होती है, इस प्रकार डेटा निर्भरताएं होती हैं, उन्हें जीपीयू पर समानांतर करना और कुशलतापूर्वक कार्यान्वित करना मुश्किल होता है। साथ ही, उनका प्रदर्शन काफी हद तक वैश्विक मेमोरी की विलंबता पर निर्भर करेगा, जो बहुत अधिक है। लेकिन यदि कार्य को "डेटा पढ़ना - प्रसंस्करण - परिणाम लिखना" पैटर्न द्वारा वर्णित किया गया है, तो आप निश्चित रूप से इसे GPU पर निष्पादित करने से एक बड़ा बढ़ावा प्राप्त कर सकते हैं।

GPU में बनावट डेटा के लिए, पहले और दूसरे स्तर के छोटे कैश का एक अलग पदानुक्रम है। यह वही है जो बनावट के उपयोग से त्वरण प्रदान करता है। यह पदानुक्रम मूल रूप से बनावट तक पहुंच की स्थानीयता का लाभ उठाने के लिए जीपीयू में दिखाई दिया: जाहिर है, एक पिक्सेल को संसाधित करने के बाद, एक पड़ोसी पिक्सेल (उच्च संभावना के साथ) को पास के बनावट डेटा की आवश्यकता होगी। लेकिन कई पारंपरिक कंप्यूटिंग एल्गोरिदम में समान डेटा एक्सेस पैटर्न होते हैं। इसलिए ग्राफ़िक्स से टेक्सचर कैश बहुत उपयोगी होंगे।

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

यह अंतर 3डी बनावट का उपयोग करते समय भी दिखाई देता है। पहले जीपीयू कंप्यूटिंग बेंचमार्क में से एक, जिसने एएमडी के लिए एक गंभीर लाभ दिखाया, 3 डी बनावट का उपयोग किया, क्योंकि यह त्रि-आयामी डेटा सरणी के साथ काम करता था। और Radeon में बनावट तक पहुंच की विलंबता काफी तेज है, और 3D केस अतिरिक्त रूप से हार्डवेयर में अधिक अनुकूलित है।

विभिन्न कंपनियों के हार्डवेयर से अधिकतम प्रदर्शन प्राप्त करने के लिए, किसी विशिष्ट कार्ड के लिए एप्लिकेशन की कुछ ट्यूनिंग की आवश्यकता होती है, लेकिन यह सैद्धांतिक रूप से जीपीयू आर्किटेक्चर के लिए एल्गोरिदम के विकास से कम महत्वपूर्ण है।

Radeon 47xx श्रृंखला की सीमाएँ

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

सदाबहार के फायदे और नुकसान

यदि आप GPU कंप्यूटिंग परिप्रेक्ष्य से AMD और Nvidia उत्पादों की तुलना करते हैं, तो 5xxx श्रृंखला एक बहुत शक्तिशाली GT200 की तरह दिखती है। इतना शक्तिशाली कि चरम प्रदर्शन में यह फर्मी से लगभग ढाई गुना आगे निकल जाता है। विशेष रूप से नए एनवीडिया वीडियो कार्ड के मापदंडों में कटौती और कोर की संख्या कम होने के बाद। लेकिन फर्मी में एल2 कैश की शुरूआत जीपीयू पर कुछ एल्गोरिदम के कार्यान्वयन को सरल बनाती है, जिससे जीपीयू का दायरा बढ़ जाता है। दिलचस्प बात यह है कि CUDA कार्यक्रमों के लिए जो पिछली पीढ़ी के GT200 के लिए अच्छी तरह से अनुकूलित थे, फर्मी के वास्तुशिल्प नवाचारों से अक्सर कुछ नहीं मिलता था। उन्होंने कंप्यूटिंग मॉड्यूल की संख्या में वृद्धि के अनुपात में तेजी लाई, यानी दोगुने से भी कम (एकल-सटीक संख्याओं के लिए), या उससे भी कम, क्योंकि मेमोरी बैंडविड्थ में वृद्धि नहीं हुई (या अन्य कारणों से)।

और ऐसे कार्यों में जो GPU वास्तुकला के लिए उपयुक्त हैं और एक स्पष्ट वेक्टर प्रकृति (उदाहरण के लिए, मैट्रिक्स गुणन) है, Radeon सैद्धांतिक शिखर के अपेक्षाकृत करीब प्रदर्शन दिखाता है और फर्मी से बेहतर प्रदर्शन करता है। मल्टी-कोर सीपीयू का उल्लेख नहीं है। विशेष रूप से एकल परिशुद्धता संख्याओं वाली समस्याओं में।

लेकिन Radeon का मरने का क्षेत्र छोटा है, गर्मी का अपव्यय कम है, बिजली की खपत अधिक है, उपज अधिक है और, तदनुसार, लागत भी कम है। और सीधे 3डी ग्राफिक्स कार्यों में, फर्मी का लाभ, यदि मौजूद है, तो क्रिस्टल क्षेत्र में अंतर से बहुत कम है। यह काफी हद तक इस तथ्य के कारण है कि प्रति मिनीप्रोसेसर 16 कंप्यूट इकाइयों, 64 थ्रेड्स के वेव फ्रंट साइज और वीएलआईडब्ल्यू वेक्टर निर्देशों के साथ Radeon कंप्यूटिंग आर्किटेक्चर अपने मुख्य कार्य - ग्राफिक्स शेडर्स की गणना के लिए उत्कृष्ट है। आम उपयोगकर्ताओं के विशाल बहुमत के लिए, गेमिंग प्रदर्शन और कीमत प्राथमिकताएं हैं।

एक पेशेवर, वैज्ञानिक सॉफ़्टवेयर परिप्रेक्ष्य से, Radeon आर्किटेक्चर सर्वोत्तम मूल्य-प्रदर्शन, प्रदर्शन-प्रति-वाट और कार्यों पर पूर्ण प्रदर्शन प्रदान करता है जो स्वाभाविक रूप से GPU आर्किटेक्चर से मेल खाते हैं, जो समानांतरकरण और वैश्वीकरण की अनुमति देते हैं।

उदाहरण के लिए, पूरी तरह से समानांतर, आसानी से वेक्टरकृत कुंजी चयन कार्य में, Radeon GeForce से कई गुना तेज और CPU से कई गुना तेज है।

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

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

माप 0बार 1माप 2माप 3बार 4बार 5बार 6बार 7वीएलआईडब्ल्यू मॉड्यूल
लहर सामने 0लहर सामने 1लहर सामने 0लहर सामने 1लहर सामने 0लहर सामने 1लहर सामने 0लहर सामने 1
निर्देश 0निर्देश 0निर्देश 16निर्देश 16निर्देश 32निर्देश 32निर्देश 48निर्देश 48VLIW0
निर्देश 1वीएलआईडब्ल्यू1
निर्देश 2वीएलआईडब्ल्यू2
निर्देश 3वीएलआईडब्ल्यू3
निर्देश 4वीएलआईडब्ल्यू4
निर्देश 5वीएलआईडब्ल्यू5
निर्देश 6वीएलआईडब्ल्यू6
निर्देश 7वीएलआईडब्ल्यू7
निर्देश 8वीएलआईडब्ल्यू8
निर्देश 9वीएलआईडब्लू9
निर्देश 10वीएलआईडब्ल्यू10
निर्देश ग्यारहवीएलआईडब्ल्यू11
निर्देश 12वीएलआईडब्ल्यू12
निर्देश 13वीएलआईडब्ल्यू13
निर्देश 14वीएलआईडब्ल्यू14
निर्देश 15वीएलआईडब्ल्यू15

दो तरंग मोर्चों के 128 निर्देश, जिनमें से प्रत्येक में 64 ऑपरेशन शामिल हैं, आठ घड़ी चक्रों में 16 वीएलआईडब्ल्यू मॉड्यूल द्वारा निष्पादित किए जाते हैं। इंटरलीविंग होती है, और वास्तव में प्रत्येक मॉड्यूल में पूरे निर्देश को निष्पादित करने के लिए दो घड़ी चक्र होते हैं, बशर्ते कि दूसरे घड़ी चक्र पर यह समानांतर में एक नया निष्पादित करना शुरू कर दे। यह संभवतः a1×a2+b1×b2+c1×c2+d1×d2 जैसे VLIW निर्देश को तुरंत निष्पादित करने में मदद करता है, यानी आठ घड़ी चक्रों में आठ ऐसे निर्देशों को निष्पादित करता है। (औपचारिक रूप से, यह प्रति माप एक होता है।)

जाहिर तौर पर एनवीडिया के पास ऐसी तकनीक नहीं है। और वीएलआईडब्ल्यू की अनुपस्थिति में, स्केलर निर्देशों का उपयोग करके उच्च प्रदर्शन के लिए उच्च आवृत्ति संचालन की आवश्यकता होती है, जो स्वचालित रूप से गर्मी अपव्यय को बढ़ाता है और प्रक्रिया पर उच्च मांग रखता है (सर्किट को उच्च आवृत्ति पर संचालित करने के लिए मजबूर करने के लिए)।

GPU कंप्यूटिंग के दृष्टिकोण से Radeon का नुकसान इसकी ब्रांचिंग के प्रति अत्यधिक नापसंदगी है। जीपीयू आम तौर पर निर्देशों को निष्पादित करने के लिए ऊपर वर्णित तकनीक के कारण ब्रांचिंग का पक्ष नहीं लेते हैं: एक बार में एक प्रोग्राम पते के साथ थ्रेड्स के समूह में। (वैसे, इस तकनीक को SIMT कहा जाता है: एकल निर्देश - एकाधिक थ्रेड (एक निर्देश - कई धागे), SIMD के अनुरूप, जहां एक निर्देश अलग-अलग डेटा के साथ एक ऑपरेशन करता है।) हालांकि, Radeon को विशेष रूप से ब्रांचिंग पसंद नहीं है: यह यह धागों के बंडल के बड़े आकार के कारण होता है। यह स्पष्ट है कि यदि प्रोग्राम पूरी तरह से वेक्टर नहीं है, तो वार्प या वेव फ्रंट का आकार जितना बड़ा होगा, उतना ही बुरा होगा, क्योंकि जब पड़ोसी धागे अपने प्रोग्राम पथों में विचलन करते हैं, तो अधिक समूह बनते हैं जिन्हें क्रमिक रूप से निष्पादित किया जाना चाहिए (क्रमबद्ध)। मान लीजिए कि सभी धागे बिखरे हुए हैं, तो यदि ताना का आकार 32 धागे है, तो प्रोग्राम 32 गुना धीमी गति से काम करेगा। और आकार 64 के मामले में, जैसे कि Radeon में, यह 64 गुना धीमा है।

यह ध्यान देने योग्य है, लेकिन "शत्रुता" की एकमात्र अभिव्यक्ति नहीं है। एनवीडिया वीडियो कार्ड में, प्रत्येक कार्यात्मक मॉड्यूल, जिसे अन्यथा CUDA कोर कहा जाता है, में एक विशेष शाखा प्रसंस्करण इकाई होती है। और 16 कंप्यूटिंग मॉड्यूल वाले Radeon वीडियो कार्ड में केवल दो शाखा नियंत्रण इकाइयाँ हैं (उन्हें अंकगणितीय इकाइयों के डोमेन से हटा दिया गया है)। इसलिए सशर्त जंप निर्देश की सरल प्रसंस्करण में भी, भले ही इसका परिणाम तरंग मोर्चे के सभी थ्रेड्स के लिए समान हो, अतिरिक्त समय लगता है। और गति धीमी हो जाती है.

AMD CPU भी बनाता है। उनका मानना ​​है कि बड़ी संख्या में शाखाओं वाले कार्यक्रमों के लिए, सीपीयू अभी भी बेहतर अनुकूल है, जबकि जीपीयू शुद्ध वेक्टर कार्यक्रमों के लिए है।

इसलिए Radeon कम समग्र प्रोग्रामिंग दक्षता प्रदान करता है, लेकिन कई मामलों में बेहतर कीमत/प्रदर्शन प्रदान करता है। दूसरे शब्दों में, ऐसे प्रोग्राम कम हैं जिन्हें CPU से Radeon पर कुशलतापूर्वक (लाभदायक) माइग्रेट किया जा सकता है, जबकि ऐसे प्रोग्राम हैं जो Fermi पर कुशलतापूर्वक चल सकते हैं। लेकिन जिन्हें प्रभावी ढंग से स्थानांतरित किया जा सकता है वे कई मायनों में Radeon पर अधिक कुशलता से काम करेंगे।

जीपीयू कंप्यूटिंग के लिए एपीआई

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

और Radeon उत्पादों के लिए सॉफ़्टवेयर समर्थन अभी भी हार्डवेयर विकास से पीछे है। (एनवीडिया की स्थिति के विपरीत, जहां हार्डवेयर की रिलीज में देरी हुई थी और उत्पाद को अलग-अलग रूप में जारी किया गया था।) अभी हाल ही में, एएमडी द्वारा निर्मित ओपनसीएल कंपाइलर को बीटा स्थिति मिली थी, जिसमें कई खामियां थीं। इसने अक्सर गलत कोड उत्पन्न किया, या सही स्रोत कोड से कोड संकलित करने से इनकार कर दिया, या इसने स्वयं एक त्रुटि उत्पन्न की और क्रैश हो गया। केवल वसंत के अंत में उच्च प्रदर्शन वाली एक रिलीज़ जारी की गई थी। यह त्रुटियों के बिना भी नहीं है, लेकिन उनमें से काफी कम हैं, और शुद्धता के कगार पर किसी चीज़ को प्रोग्राम करने का प्रयास करते समय वे पार्श्व दिशाओं में उत्पन्न होते हैं। उदाहरण के लिए, वे uchar4 प्रकार के साथ काम करते हैं, जो 4-बाइट चार-घटक चर को परिभाषित करता है। यह प्रकार OpenCL विनिर्देशों में है, लेकिन Radeon पर इसके साथ काम करना उचित नहीं है, क्योंकि रजिस्टर 128-बिट हैं: समान चार घटक, लेकिन 32-बिट। और ऐसा uchar4 वैरिएबल अभी भी पूरे रजिस्टर पर कब्जा कर लेगा, इसके लिए केवल अतिरिक्त पैकिंग संचालन और व्यक्तिगत बाइट घटकों तक पहुंच की आवश्यकता होगी। कंपाइलर में कोई त्रुटि नहीं होनी चाहिए, लेकिन दोषों के बिना कोई कंपाइलर नहीं है। यहां तक ​​कि 11 संस्करणों के बाद इंटेल कंपाइलर में भी संकलन त्रुटियां हैं। पहचानी गई त्रुटियों को अगली रिलीज़ में ठीक कर दिया जाएगा, जिसे शरद ऋतु के करीब रिलीज़ किया जाएगा।

लेकिन अभी भी कई चीजें हैं जिनमें सुधार की जरूरत है. उदाहरण के लिए, मानक Radeon GPU ड्राइवर अभी भी OpenCL का उपयोग करके GPU कंप्यूटिंग का समर्थन नहीं करता है। उपयोगकर्ता को एक अतिरिक्त विशेष पैकेज डाउनलोड और इंस्टॉल करना होगा।

लेकिन सबसे महत्वपूर्ण बात किसी फ़ंक्शन लाइब्रेरी का अभाव है। दोहरी परिशुद्धता वाली वास्तविक संख्याओं के लिए कोई ज्या, कोज्या या घातांक भी नहीं है। खैर, मैट्रिक्स जोड़ और गुणा के लिए इसकी आवश्यकता नहीं है, लेकिन यदि आप कुछ अधिक जटिल प्रोग्राम करना चाहते हैं, तो आपको स्क्रैच से सभी फ़ंक्शन लिखने होंगे। या नए SDK रिलीज़ की प्रतीक्षा करें. बेसिक मैट्रिक्स फ़ंक्शंस के समर्थन के साथ एवरग्रीन जीपीयू परिवार के लिए एसीएमएल (एएमडी कोर मैथ लाइब्रेरी) जल्द ही जारी किया जाना चाहिए।

फिलहाल, लेख के लेखक के अनुसार, स्वाभाविक रूप से सीमाओं को ध्यान में रखते हुए, Radeon वीडियो कार्ड प्रोग्रामिंग के लिए डायरेक्ट कंप्यूट 5.0 एपीआई का उपयोग करना संभव लगता है: विंडोज 7 और विंडोज विस्टा प्लेटफॉर्म को लक्षित करना। माइक्रोसॉफ्ट के पास कंपाइलर बनाने का व्यापक अनुभव है, और हम बहुत जल्द पूरी तरह कार्यात्मक रिलीज की उम्मीद कर सकते हैं, माइक्रोसॉफ्ट की इसमें सीधे रुचि है। लेकिन डायरेक्ट कंप्यूट इंटरैक्टिव अनुप्रयोगों की जरूरतों पर केंद्रित है: किसी चीज़ की गणना करना और तुरंत परिणाम की कल्पना करना - उदाहरण के लिए, किसी सतह पर तरल का प्रवाह। इसका मतलब यह नहीं है कि इसका उपयोग केवल गणनाओं के लिए नहीं किया जा सकता है, लेकिन यह इसका प्राकृतिक उद्देश्य नहीं है। मान लीजिए कि माइक्रोसॉफ्ट डायरेक्ट कंप्यूट में लाइब्रेरी फ़ंक्शंस जोड़ने की योजना नहीं बना रहा है - केवल वे जो एएमडी के पास वर्तमान में नहीं हैं। यानी, जो अब Radeon पर प्रभावी ढंग से गणना की जा सकती है - कुछ बहुत परिष्कृत कार्यक्रम नहीं हैं - उन्हें डायरेक्ट कंप्यूट पर भी लागू किया जा सकता है, जो OpenCL की तुलना में बहुत सरल है और अधिक स्थिर होना चाहिए। साथ ही, यह पूरी तरह से पोर्टेबल है और एनवीडिया और एएमडी दोनों पर चलेगा, इसलिए आपको प्रोग्राम को केवल एक बार संकलित करना होगा, जबकि एनवीडिया और एएमडी के ओपनसीएल एसडीके कार्यान्वयन पूरी तरह से संगत नहीं हैं। (इस अर्थ में कि यदि आप एएमडी ओपनसीएल एसडीके का उपयोग करके एएमडी सिस्टम पर ओपनसीएल प्रोग्राम विकसित करते हैं, तो यह एनवीडिया पर इतनी आसानी से नहीं चल सकता है। आपको एनवीडिया एसडीके का उपयोग करके उसी पाठ को संकलित करने की आवश्यकता हो सकती है। और, निश्चित रूप से, इसके विपरीत .)

फिर, ओपनसीएल में बहुत सारी अनावश्यक कार्यक्षमताएं हैं, क्योंकि ओपनसीएल का उद्देश्य सिस्टम की एक विस्तृत श्रृंखला के लिए एक सार्वभौमिक प्रोग्रामिंग भाषा और एपीआई बनना है। और जीपीयू, और सीपीयू, और सेल। इसलिए यदि आपको किसी विशिष्ट उपयोगकर्ता सिस्टम (प्रोसेसर प्लस वीडियो कार्ड) के लिए एक प्रोग्राम लिखना है, तो ओपनसीएल "अत्यधिक उत्पादक" प्रतीत नहीं होता है। प्रत्येक फ़ंक्शन में दस पैरामीटर होते हैं, और उनमें से नौ को 0 पर सेट किया जाना चाहिए। और प्रत्येक पैरामीटर को सेट करने के लिए, आपको एक विशेष फ़ंक्शन को कॉल करने की आवश्यकता है, जिसमें पैरामीटर भी हैं।

और डायरेक्ट कंप्यूट का सबसे महत्वपूर्ण वर्तमान लाभ यह है कि उपयोगकर्ता को एक विशेष पैकेज स्थापित करने की आवश्यकता नहीं है: जो कुछ भी आवश्यक है वह पहले से ही DirectX 11 में है।

GPU कंप्यूटिंग विकास की समस्याएं

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

व्यावसायिक अनुप्रयोगों और वर्कस्टेशन क्षेत्र में उपयोग के मामले में जीपीयू की संभावनाएं कुछ हद तक बेहतर हैं, क्योंकि वहां प्रदर्शन की अधिक आवश्यकता है। जीपीयू समर्थन के साथ 3डी संपादकों के लिए प्लगइन्स हैं: उदाहरण के लिए, रे ट्रेसिंग का उपयोग करके रेंडरिंग के लिए - नियमित जीपीयू रेंडरिंग के साथ भ्रमित न हों! जटिल प्रभावों के तेजी से निर्माण के साथ 2डी और प्रेजेंटेशन संपादकों के लिए भी कुछ उभर रहा है। वीडियो प्रोसेसिंग प्रोग्राम भी धीरे-धीरे GPU समर्थन प्राप्त कर रहे हैं। उपरोक्त कार्य, अपनी समानांतर प्रकृति के कारण, GPU आर्किटेक्चर के साथ अच्छी तरह फिट बैठते हैं, लेकिन अब CPU की सभी क्षमताओं के लिए एक बहुत बड़ा कोड बेस बनाया, डिबग और अनुकूलित किया गया है, इसलिए अच्छे GPU कार्यान्वयन के सामने आने में समय लगेगा .

इस सेगमेंट में जीपीयू की ऐसी कमजोरियां भी सामने आती हैं, जैसे वीडियो मेमोरी की सीमित मात्रा - पारंपरिक जीपीयू के लिए लगभग 1 जीबी। जीपीयू कार्यक्रमों के प्रदर्शन को कम करने वाले मुख्य कारकों में से एक धीमी गति से सीपीयू और जीपीयू के बीच डेटा का आदान-प्रदान करने की आवश्यकता है, और सीमित मेमोरी के कारण, अधिक डेटा स्थानांतरित करना होगा। और यहां एक मॉड्यूल में जीपीयू और सीपीयू के संयोजन की एएमडी की अवधारणा आशाजनक लगती है: आप साझा मेमोरी तक आसान और सरल पहुंच के लिए और कम विलंबता के साथ ग्राफिक्स मेमोरी की उच्च बैंडविड्थ का त्याग कर सकते हैं। वर्तमान DDR5 वीडियो मेमोरी की यह उच्च बैंडविड्थ अधिकांश GPU कंप्यूटिंग प्रोग्रामों की तुलना में सीधे ग्राफिक्स प्रोग्रामों से कहीं अधिक मांग में है। सामान्य तौर पर, जीपीयू और सीपीयू की साझा मेमोरी जीपीयू के दायरे का काफी विस्तार करेगी, जिससे कार्यक्रमों के छोटे उप-कार्यों में इसकी कंप्यूटिंग क्षमताओं का उपयोग करना संभव हो जाएगा।

और वैज्ञानिक कंप्यूटिंग के क्षेत्र में GPU की सबसे अधिक मांग है। कई GPU-आधारित सुपर कंप्यूटर पहले ही बनाए जा चुके हैं, जो मैट्रिक्स संचालन परीक्षण में बहुत अच्छे परिणाम दिखाते हैं। वैज्ञानिक समस्याएँ इतनी विविध और असंख्य हैं कि हमेशा ऐसी कई समस्याएँ होती हैं जो GPU वास्तुकला में पूरी तरह से फिट होती हैं, जिसके लिए GPU के उपयोग से उच्च प्रदर्शन प्राप्त करना आसान हो जाता है।

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

यह प्रश्न अक्सर उठता है: Adobe Media Encoder CC में कोई GPU त्वरण क्यों नहीं है? हमें पता चला कि Adobe Media Encoder GPU त्वरण का उपयोग करता है, और इसके उपयोग की बारीकियों पर भी ध्यान दिया। एक बयान यह भी है कि Adobe Media Encoder CC ने GPU त्वरण के लिए समर्थन हटा दिया है। यह एक गलत राय है और इस तथ्य से उत्पन्न होती है कि मुख्य एडोब प्रीमियर प्रो सीसी प्रोग्राम अब पंजीकृत और अनुशंसित वीडियो कार्ड के बिना काम कर सकता है, और एडोब मीडिया एनकोडर सीसी में जीपीयू इंजन को सक्षम करने के लिए, वीडियो कार्ड को दस्तावेजों में पंजीकृत होना चाहिए : cuda_supported_cards या opencl_supported_cards. यदि एनवीडिया चिपसेट के साथ सब कुछ स्पष्ट है, तो बस चिपसेट का नाम लें और इसे cuda_supported_cards दस्तावेज़ में दर्ज करें। फिर, एएमडी वीडियो कार्ड का उपयोग करते समय, आपको चिपसेट का नाम नहीं, बल्कि कोर का कोड नाम दर्ज करना होगा। तो, आइए अभ्यास में देखें कि असतत ग्राफिक्स एटीआई मोबिलिटी Radeon HD 5730 के साथ ASUS N71JQ लैपटॉप पर Adobe Media Encoder CC में GPU इंजन को कैसे सक्षम किया जाए। GPU-Z उपयोगिता द्वारा दिखाए गए ATI मोबिलिटी Radeon HD 5730 ग्राफिक्स एडॉप्टर का तकनीकी डेटा:

एडोब प्रीमियर प्रो सीसी लॉन्च करें और इंजन चालू करें: मर्करी प्लेबैक इंजन जीपीयू एक्सेलेरेशन (ओपनसीएल)।

एक टाइमलाइन पर तीन डीएसएलआर वीडियो, एक के ऊपर एक, उनमें से दो, पिक्चर-इन-पिक्चर प्रभाव पैदा करते हैं।

Ctrl+M, Mpeg2-DVD प्रीसेट का चयन करें, स्केल टू फिल विकल्प का उपयोग करके किनारों पर काली पट्टियों को हटा दें। हम GPU के बिना परीक्षणों के लिए बढ़ी हुई गुणवत्ता भी शामिल करते हैं: MRQ (अधिकतम रेंडर गुणवत्ता का उपयोग करें)। बटन पर क्लिक करें: निर्यात करें। सीपीयू लोड 20% तक और रैंडम एक्सेस मेमोरी 2.56 जीबी.


ATI मोबिलिटी Radeon HD 5730 चिपसेट का GPU लोड 97% और 352MB ऑन-बोर्ड वीडियो मेमोरी है। लैपटॉप का परीक्षण बैटरी पावर पर चलते समय किया गया था, इसलिए ग्राफिक्स कोर/मेमोरी कम आवृत्तियों पर काम करती है: 375/810 मेगाहर्ट्ज।

कुल प्रतिपादन समय: 1 मिनट 55 सेकंड(जीपीयू इंजन का उपयोग करते समय एमआरक्यू को चालू/बंद करने से अंतिम रेंडरिंग समय प्रभावित नहीं होता है)।
अधिकतम रेंडर गुणवत्ता का उपयोग करें चेकबॉक्स चेक करने के साथ, अब बटन पर क्लिक करें: कतार।


बैटरी पावर पर चलने पर प्रोसेसर की घड़ी की गति: 930 मेगाहर्ट्ज।

AMEEncodingLog चलाएँ और अंतिम रेंडरिंग समय देखें: 5 मिनट और 14 सेकंड.

हम परीक्षण दोहराते हैं, लेकिन अधिकतम रेंडर गुणवत्ता का उपयोग करें चेकबॉक्स अनचेक होने पर, बटन पर क्लिक करें: कतार।

कुल प्रतिपादन समय: 1 मिनट 17 सेकंड.

अब Adobe Media Encoder CC में GPU इंजन चालू करें, Adobe Premiere Pro CC प्रोग्राम लॉन्च करें, कुंजी संयोजन दबाएँ: Ctrl + F12, कंसोल > कंसोल व्यू निष्पादित करें और कमांड फ़ील्ड में GPUSniffer दर्ज करें, Enter दबाएँ।


नाम चुनें और उसे GPU कंप्यूटेशन जानकारी में कॉपी करें।

Adobe Premiere Pro CC प्रोग्राम निर्देशिका में, opencl_supported_cards दस्तावेज़ खोलें, और चिपसेट का कोड नाम वर्णानुक्रम में Ctrl+S दर्ज करें।

बटन पर क्लिक करें: कतार, और हमें एडोब मीडिया एनकोडर सीसी में एडोब प्रीमियर प्रो सीसी प्रोजेक्ट के प्रतिपादन का जीपीयू त्वरण मिलता है।

कुल समय: 1 मिनट 55 सेकंड.

हम लैपटॉप को आउटलेट से जोड़ते हैं और गणना के परिणाम दोहराते हैं। कतार, एमआरक्यू चेकबॉक्स अनियंत्रित है, इंजन चालू किए बिना, रैम लोड थोड़ा बढ़ गया है:


प्रोसेसर क्लॉक स्पीड: दीवार आउटलेट से चलने पर 1.6 गीगाहर्ट्ज़ और मोड सक्षम: उच्च प्रदर्शन।

कुल समय: 46 सेकंड.

हम इंजन चालू करते हैं: मर्करी प्लेबैक इंजन जीपीयू एक्सेलेरेशन (ओपनसीएल), जैसा कि नेटवर्क से देखा जा सकता है, लैपटॉप वीडियो कार्ड अपनी बेस आवृत्तियों पर चल रहा है, एडोब मीडिया एनकोडर सीसी में जीपीयू लोड 95% तक पहुंच जाता है।

से कुल प्रतिपादन समय कम हो गया 1 मिनट 55 सेकंड, पहले 1 मिनट और 5 सेकंड.

*Adobe Media Encoder CC अब रेंडरिंग के लिए ग्राफ़िक्स प्रोसेसिंग यूनिट (GPU) का उपयोग करता है। CUDA और OpenCL मानक समर्थित हैं। Adobe Media Encoder CC में, GPU इंजन का उपयोग निम्नलिखित रेंडरिंग प्रक्रियाओं के लिए किया जाता है:
- स्पष्टता बदलें (उच्च से मानक और इसके विपरीत)।
- समय कोड फ़िल्टर।
- पिक्सेल प्रारूप रूपांतरण।
- विच्छेद करना।
यदि आप एक प्रीमियर प्रो प्रोजेक्ट प्रस्तुत कर रहे हैं, तो एएमई उस प्रोजेक्ट के लिए निर्दिष्ट जीपीयू रेंडरिंग सेटिंग्स का उपयोग करता है। यह प्रीमियर प्रो में पाई जाने वाली सभी जीपीयू रेंडरिंग क्षमताओं का लाभ उठाएगा। एएमई परियोजनाएं जीपीयू रेंडरिंग क्षमताओं के सीमित सेट का उपयोग करके प्रस्तुत करती हैं। यदि अनुक्रम को मूल समर्थन का उपयोग करके प्रस्तुत किया जाता है, तो AME से GPU सेटिंग लागू की जाती है, प्रोजेक्ट सेटिंग को अनदेखा कर दिया जाता है। इस मामले में, प्रीमियर प्रो की सभी जीपीयू रेंडरिंग क्षमताओं का उपयोग सीधे एएमई में किया जाता है। यदि प्रोजेक्ट में तृतीय-पक्ष VST शामिल हैं, तो प्रोजेक्ट की GPU सेटिंग का उपयोग किया जाता है। अनुक्रम को PProHeadless का उपयोग करके एन्कोड किया गया है, जैसा कि AME के ​​पुराने संस्करणों में था। यदि नेटिव प्रीमियर प्रो अनुक्रम आयात सक्षम करें अनचेक किया गया है, तो PProHeadless और GPU सेटिंग का हमेशा उपयोग किया जाता है।

हमने ASUS N71JQ लैपटॉप के सिस्टम डिस्क पर एक छिपे हुए विभाजन के बारे में पढ़ा।

कभी भी बहुत अधिक नाभिक नहीं हो सकते...

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

यह आलेख जीपीयू अनुकूलन के सिद्धांत और बुनियादी नियमों को नेविगेट करना आसान बनाने के लिए बुनियादी अवधारणाओं का वर्णन करता है ताकि इन अवधारणाओं को कम बार संबोधित करना पड़े।

प्रसंस्करण की आवश्यकता वाले बड़ी मात्रा में डेटा के साथ काम करने के लिए GPU प्रभावी होने के कारण:

  • उनके पास कार्यों के समानांतर निष्पादन के लिए महान क्षमताएं हैं (कई, कई प्रोसेसर)
  • उच्च मेमोरी बैंडविड्थ

मेमोरी बैंडविड्थ- यह कितनी जानकारी - एक बिट या एक गीगाबाइट - समय की प्रति यूनिट - एक सेकंड या एक प्रोसेसर चक्र में स्थानांतरित की जा सकती है।

अनुकूलन कार्यों में से एक है अधिकतम थ्रूपुट का उपयोग करना - प्रदर्शन बढ़ाने के लिए THROUGHPUT(आदर्श रूप से यह मेमोरी बैंडविड्थ के बराबर होना चाहिए)।

बैंडविड्थ उपयोग में सुधार करने के लिए:

  • जानकारी की मात्रा बढ़ाएँ - बैंडविड्थ का पूर्ण उपयोग करें (उदाहरण के लिए, प्रत्येक स्ट्रीम फ्लोट4 के साथ काम करती है)
  • विलंबता को कम करें - संचालन के बीच की देरी

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

यदि सिंक्रोनाइज़ेशन का उपयोग किया जाता है तो विलंबता को कैसे कम करें:

  • किसी ब्लॉक में थ्रेड्स की संख्या कम करें
  • ब्लॉक समूहों की संख्या बढ़ाएँ

GPU संसाधनों का पूर्ण उपयोग - GPU अधिभोग

अनुकूलन के बारे में उच्च चर्चाओं में, यह शब्द अक्सर प्रकट होता है - जीपीयू अधिभोगया कर्नेल अधिभोग- यह वीडियो कार्ड के संसाधनों के उपयोग की दक्षता को दर्शाता है। मैं अलग से यह नोट करना चाहूंगा कि भले ही आप सभी संसाधनों का उपयोग करें, इसका मतलब यह नहीं है कि आप उनका सही उपयोग कर रहे हैं।

जीपीयू की कंप्यूटिंग शक्ति सैकड़ों कम्प्यूटेशनल रूप से भूखे प्रोसेसर हैं; प्रोग्राम बनाते समय - कर्नेल - लोड को वितरित करने का बोझ प्रोग्रामर के कंधों पर पड़ता है। एक गलती से इनमें से अधिकांश बहुमूल्य संसाधन बेकार पड़े रह सकते हैं। अब मैं समझाऊंगा क्यों. हमें दूर से शुरुआत करनी होगी.

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

प्रत्येक सिंक्रनाइज़ेशन बिंदु, तर्क की प्रत्येक शाखा ऐसी निष्क्रिय स्थिति उत्पन्न कर सकती है। अधिकतम विचलन (निष्पादन तर्क की शाखा) ताना के आकार पर निर्भर करता है। एनवीडिया जीपीयू के लिए यह 32 है, एएमडी के लिए यह 64 है।

वार्प निष्पादन के दौरान मल्टीप्रोसेसर डाउनटाइम को कम करने के लिए:

  • बाधा प्रतीक्षा समय को कम करें
  • कर्नेल फ़ंक्शन में निष्पादन तर्क के विचलन को कम करें

इस समस्या को प्रभावी ढंग से हल करने के लिए, यह समझना समझ में आता है कि ताना कैसे बनता है (कई आयामों वाले मामले के लिए)। वास्तव में, क्रम सरल है - पहले X में, फिर Y में और अंत में, Z में।

कर्नेल को 64x16 आकार के ब्लॉक के साथ लॉन्च किया गया है, थ्रेड्स को X, Y, Z - यानी क्रम में वॉर्प्स में विभाजित किया गया है। पहले 64 तत्वों को दो वार्पों में विभाजित किया गया है, फिर दूसरे को, आदि।

कर्नेल 16x64 ब्लॉक के साथ चलता है। पहले और दूसरे 16 तत्वों को पहले ताना, तीसरे और चौथे - दूसरे ताना आदि में जोड़ा जाता है।

विचलन को कैसे कम करें (याद रखें, ब्रांचिंग हमेशा महत्वपूर्ण प्रदर्शन हानि का कारण नहीं है)

  • जब आसन्न प्रवाह के अलग-अलग निष्पादन पथ होते हैं - उनके साथ कई स्थितियां और संक्रमण होते हैं - पुनर्गठन के तरीकों की तलाश करें
  • धागों के असंतुलित भार को देखें और निर्णायक रूप से इसे हटा दें (ऐसा तब होता है जब न केवल हमारे पास शर्तें होती हैं, बल्कि इन स्थितियों के कारण, पहला धागा हमेशा कुछ गणना करता है, और पांचवां इस शर्त को पूरा नहीं करता है और निष्क्रिय है)

अपने GPU संसाधनों का अधिकतम लाभ कैसे उठाएं

दुर्भाग्य से, GPU संसाधनों की भी अपनी सीमाएँ हैं। और, कड़ाई से बोलते हुए, कर्नेल फ़ंक्शन लॉन्च करने से पहले, सीमाएं निर्धारित करना और लोड वितरित करते समय इन सीमाओं को ध्यान में रखना समझ में आता है। यह महत्वपूर्ण क्यों है?

वीडियो कार्ड में एक मल्टीप्रोसेसर द्वारा निष्पादित थ्रेड्स की कुल संख्या, एक ब्लॉक में थ्रेड्स की अधिकतम संख्या, एक प्रोसेसर पर वॉर्प्स की अधिकतम संख्या, विभिन्न प्रकार की मेमोरी पर प्रतिबंध आदि पर प्रतिबंध होते हैं। यह सारी जानकारी या तो प्रोग्रामेटिक रूप से, उपयुक्त एपीआई के माध्यम से, या पहले एसडीके से उपयोगिताओं का उपयोग करके अनुरोध की जा सकती है। (एनवीडिया उपकरणों के लिए डिवाइसक्वेरी मॉड्यूल, सीएलइन्फो - एएमडी वीडियो कार्ड के लिए)।

सामान्य चलन:

  • थ्रेड ब्लॉक/कार्यसमूहों की संख्या स्ट्रीम प्रोसेसर की संख्या की गुणज होनी चाहिए
  • ब्लॉक/कार्यसमूह का आकार वार्प आकार का एक गुणज होना चाहिए

यह ध्यान में रखा जाना चाहिए कि प्रत्येक प्रोसेसर पर एक साथ घूमने वाले न्यूनतम 3-4 वार्प/वेफ्रंट हैं, बुद्धिमान गाइड कम से कम सात वेफ्रंट्स पर विचार करके आगे बढ़ने की सलाह देते हैं। साथ ही, हार्डवेयर प्रतिबंधों को न भूलें!

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

उपयोग की जानकारी:
http://docs.nvidia.com/cuda/cuda-c-best-practices-guide/#calculated-occupancy

जीपीयू और मेमोरी संचालन

वीडियो कार्ड 128-बिट मेमोरी संचालन के लिए अनुकूलित हैं। वे। आदर्श रूप से, प्रत्येक मेमोरी हेरफेर को आदर्श रूप से एक समय में 4 चार-बाइट मान बदलना चाहिए। एक प्रोग्रामर के लिए मुख्य परेशानी यह है कि आधुनिक जीपीयू कंपाइलर ऐसी चीजों को अनुकूलित करना नहीं जानते हैं। इसे सीधे फ़ंक्शन कोड में करना होता है और, औसतन, प्रदर्शन में एक प्रतिशत की वृद्धि होती है। मेमोरी अनुरोधों की आवृत्ति का प्रदर्शन पर बहुत अधिक प्रभाव पड़ता है।

समस्या यह है: प्रत्येक अनुरोध डेटा का एक टुकड़ा लौटाता है जो आकार में 128 बिट्स का गुणक होता है। और प्रत्येक थ्रेड इसका केवल एक चौथाई उपयोग करता है (नियमित चार-बाइट चर के मामले में)। जब आसन्न थ्रेड एक साथ मेमोरी कोशिकाओं में क्रमिक रूप से स्थित डेटा के साथ काम करते हैं, तो इससे मेमोरी एक्सेस की कुल संख्या कम हो जाती है। इस घटना को संयुक्त पढ़ने और लिखने के संचालन कहा जाता है ( सम्मिलित पहुंच - अच्छा! दोनों पढ़ें और लिखें) - और कोड के सही संगठन के साथ ( स्मृति के सन्निहित हिस्से तक पहुंच में बाधा - बुरा!) प्रदर्शन में उल्लेखनीय सुधार कर सकता है। अपने कोर को व्यवस्थित करते समय - याद रखें - सन्निहित पहुंच - मेमोरी की एक पंक्ति के तत्वों के भीतर, कॉलम तत्वों के साथ काम करना अब उतना कुशल नहीं है। अधिक विवरण चाहते हैं? मुझे यह पीडीएफ पसंद आया - या "के लिए गूगल करें" स्मृति संयोजन तकनीक “.

"अड़चन" श्रेणी में अग्रणी स्थान पर एक अन्य मेमोरी ऑपरेशन का कब्जा है - होस्ट मेमोरी से GPU में डेटा कॉपी करना . कॉपी करना किसी भी तरह से नहीं होता है, बल्कि ड्राइवर और सिस्टम द्वारा विशेष रूप से आवंटित मेमोरी क्षेत्र से होता है: जब डेटा कॉपी करने का अनुरोध होता है, तो सिस्टम पहले इस डेटा को वहां कॉपी करता है, और उसके बाद ही इसे GPU पर अपलोड करता है। डेटा परिवहन की गति पीसीआई एक्सप्रेस एक्सएन बस (जहां एन डेटा लाइनों की संख्या है) की बैंडविड्थ द्वारा सीमित है जिसके माध्यम से आधुनिक वीडियो कार्ड होस्ट के साथ संचार करते हैं।

हालाँकि, होस्ट पर धीमी मेमोरी की अनावश्यक प्रतिलिपि बनाना कभी-कभी एक अनुचित लागत होती है। समाधान तथाकथित का उपयोग करना है पिन की गई मेमोरी - एक विशेष रूप से चिह्नित मेमोरी क्षेत्र, ताकि ऑपरेटिंग सिस्टम इसके साथ कोई भी ऑपरेशन करने में सक्षम न हो (उदाहरण के लिए, अपने विवेक पर स्वैप/स्थानांतरित करने के लिए अपलोड करें, आदि)। होस्ट से वीडियो कार्ड में डेटा ट्रांसफर बिना किसी भागीदारी के किया जाता है ऑपरेटिंग सिस्टम- अतुल्यकालिक रूप से, के माध्यम से डीएमए (प्रत्यक्ष मेमोरी एक्सेस)।

और अंत में, स्मृति के बारे में थोड़ा और। मल्टीप्रोसेसर पर साझा मेमोरी आमतौर पर 32-बिट शब्द - डेटा वाले मेमोरी बैंकों के रूप में व्यवस्थित होती है। अच्छी परंपरा के अनुसार, बैंकों की संख्या एक जीपीयू पीढ़ी से दूसरी पीढ़ी में भिन्न होती है - 16/32 यदि प्रत्येक थ्रेड डेटा के लिए एक अलग बैंक तक पहुंचता है, तो सब कुछ ठीक है। अन्यथा, हमें एक बैंक से कई पढ़ने/लिखने के अनुरोध मिलते हैं और हमें एक विरोध मिलता है ( साझा मेमोरी बैंक संघर्ष). ऐसी परस्पर विरोधी कॉलें क्रमबद्ध होती हैं और इसलिए समानांतर के बजाय क्रमिक रूप से निष्पादित की जाती हैं। यदि सभी थ्रेड एक बैंक तक पहुंचते हैं, तो "प्रसारण" प्रतिक्रिया का उपयोग किया जाता है ( प्रसारण) और कोई विरोध नहीं है. पहुंच संबंधी विवादों से प्रभावी ढंग से निपटने के कई तरीके हैं, मुझे यह पसंद आया मेमोरी बैंकों तक पहुंच संबंधी विवादों से छुटकारा पाने की मुख्य तकनीकों का विवरण – .

गणित की संक्रियाओं को और भी तेज़ कैसे बनाएं? उसे याद रखो:

  • दोहरी परिशुद्धता गणना fp64 >> fp32 के साथ एक उच्च लोड ऑपरेशन है
  • कोड में फॉर्म 3.13 के स्थिरांक, डिफ़ॉल्ट रूप से, fp64 के रूप में व्याख्या किए जाते हैं यदि 3.14f स्पष्ट रूप से निर्दिष्ट नहीं है
  • गणित को अनुकूलित करने के लिए, यह देखने के लिए गाइडों की जांच करना एक अच्छा विचार होगा कि कंपाइलर के पास कोई झंडे हैं या नहीं
  • निर्माता अपने एसडीके में ऐसी विशेषताएं शामिल करते हैं जो प्रदर्शन हासिल करने के लिए डिवाइस सुविधाओं का फायदा उठाते हैं (अक्सर पोर्टेबिलिटी की कीमत पर)

CUDA डेवलपर्स के लिए इस अवधारणा पर बारीकी से ध्यान देना उचित है कूडा धाराआपको एक डिवाइस पर एक साथ कई कर्नेल फ़ंक्शंस चलाने या फ़ंक्शंस निष्पादित करते समय होस्ट से डिवाइस में डेटा की एसिंक्रोनस कॉपी को संयोजित करने की अनुमति देता है। ओपनसीएल अभी तक ऐसी कार्यक्षमता प्रदान नहीं करता है :)

प्रोफाइलिंग के लिए स्क्रैप:

एनवीफ़िया विज़ुअल प्रोफाइलर एक दिलचस्प उपयोगिता है जो CUDA और OpenCL कर्नेल दोनों का विश्लेषण करती है।

पी.एस. अनुकूलन के लिए एक अधिक व्यापक मार्गदर्शिका के रूप में, मैं सभी प्रकार की गूगलिंग की अनुशंसा कर सकता हूँ सर्वोत्तम अभ्यास मार्गदर्शिका ओपनसीएल और सीयूडीए के लिए।

  • ,

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

जीपीजीपीयू का जन्म

हम सभी यह सोचने के आदी हैं कि कंप्यूटर का एकमात्र घटक जो किसी भी कोड को निष्पादित करने में सक्षम है, वह केंद्रीय प्रोसेसर है। लंबे समय तक, लगभग सभी बड़े पैमाने पर उत्पादित पीसी एक ही प्रोसेसर से लैस थे जो ऑपरेटिंग सिस्टम कोड, हमारे सभी सॉफ़्टवेयर और वायरस सहित सभी कल्पनीय गणनाओं को संभालता था।

बाद में प्रकट हुए मल्टी-कोर प्रोसेसरऔर मल्टीप्रोसेसर सिस्टम, जिसमें ऐसे कई घटक थे। इससे मशीनों को एक साथ कई कार्य करने की अनुमति मिल गई, और समग्र (सैद्धांतिक) सिस्टम प्रदर्शन मशीन में स्थापित कोर की संख्या के बराबर बढ़ गया। हालाँकि, यह पता चला कि मल्टी-कोर प्रोसेसर का उत्पादन और डिज़ाइन करना बहुत कठिन और महंगा था।

प्रत्येक कोर में अपने स्वयं के (बल्कि बड़े) कैश, निर्देश पाइपलाइन, एसएसई ब्लॉक, अनुकूलन करने वाले कई ब्लॉक आदि के साथ एक जटिल और जटिल x86 आर्किटेक्चर का एक पूर्ण प्रोसेसर होना चाहिए। और इसी तरह। इसलिए, कोर की संख्या बढ़ाने की प्रक्रिया काफी धीमी हो गई, और सफेद विश्वविद्यालय कोट, जिनके लिए दो या चार कोर स्पष्ट रूप से पर्याप्त नहीं थे, ने अपनी वैज्ञानिक गणना के लिए अन्य कंप्यूटिंग शक्ति का उपयोग करने का एक तरीका ढूंढ लिया, जो वीडियो में प्रचुर मात्रा में था कार्ड (परिणामस्वरूप, ब्रुकजीपीयू टूल भी अनुकरण करते हुए दिखाई दिया अतिरिक्त प्रोसेसर DirectX और OpenGL फ़ंक्शन कॉल का उपयोग करके)।

ग्राफिक्स प्रोसेसर, केंद्रीय प्रोसेसर के कई नुकसानों से रहित, एक उत्कृष्ट और बहुत तेज़ गणना करने वाली मशीन बन गए, और बहुत जल्द जीपीयू निर्माताओं ने स्वयं वैज्ञानिक दिमागों के विकास पर करीब से नज़र डालना शुरू कर दिया (और वास्तव में एनवीडिया को काम पर रखा गया) अधिकांश शोधकर्ता)। परिणामस्वरूप, एनवीडिया सीयूडीए तकनीक सामने आई, जो एक इंटरफ़ेस को परिभाषित करती है जिसके साथ जटिल एल्गोरिदम की गणना को बिना किसी बैसाखी के जीपीयू के कंधों पर स्थानांतरित करना संभव हो गया। बाद में इसके बाद ATi (AMD) ने क्लोज़ टू मेटल (अब स्ट्रीम) नामक तकनीक का अपना संस्करण पेश किया, और बहुत जल्द Apple का एक मानक संस्करण सामने आया, जिसे OpenCL कहा गया।

क्या GPU ही सब कुछ है?

तमाम फायदों के बावजूद, GPGPU तकनीक में कई समस्याएं हैं। इनमें से पहला अनुप्रयोग का बहुत ही संकीर्ण दायरा है। बढ़ती कंप्यूटिंग शक्ति और कोर की कुल संख्या (वीडियो कार्ड में सौ से अधिक कोर वाली एक कंप्यूटिंग इकाई होती है) के मामले में जीपीयू केंद्रीय प्रोसेसर से बहुत आगे निकल गए हैं, लेकिन डिज़ाइन के सरलीकरण को अधिकतम करके ऐसा उच्च घनत्व प्राप्त किया जाता है। चिप का ही.

संक्षेप में, GPU का मुख्य कार्य नीचे आता है गणितीय गणनाका उपयोग करके सरल एल्गोरिदम, जो इनपुट के रूप में पूर्वानुमानित डेटा की बहुत बड़ी मात्रा प्राप्त नहीं करते हैं। इस कारण से, जीपीयू कोर में एक बहुत ही सरल डिज़ाइन, कम कैश आकार और निर्देशों का एक मामूली सेट होता है, जिसके परिणामस्वरूप अंततः उनकी उत्पादन लागत कम होती है और चिप पर बहुत सघन प्लेसमेंट की संभावना होती है। GPU हजारों श्रमिकों वाली एक चीनी फ़ैक्टरी की तरह हैं। वे कुछ साधारण चीजें बहुत अच्छी तरह से करते हैं (और सबसे महत्वपूर्ण, जल्दी और सस्ते में), लेकिन यदि आप उन्हें एक हवाई जहाज को असेंबल करने का काम सौंपते हैं, तो परिणाम, अधिक से अधिक, एक हैंग ग्लाइडर होगा।

इसलिए, GPU की पहली सीमा तेज़ गणितीय गणनाओं पर उनका ध्यान है, जो मल्टीमीडिया अनुप्रयोगों में सहायता के लिए GPU के अनुप्रयोग के दायरे को सीमित करता है, साथ ही जटिल डेटा प्रोसेसिंग में शामिल किसी भी प्रोग्राम (उदाहरण के लिए, आर्काइवर्स या एन्क्रिप्शन सिस्टम, साथ ही) प्रतिदीप्ति माइक्रोस्कोपी, आणविक गतिशीलता, इलेक्ट्रोस्टैटिक्स और लिनक्स उपयोगकर्ताओं के लिए कम रुचि वाली अन्य चीजों में शामिल सॉफ़्टवेयर के रूप में)।

GPGPU के साथ दूसरी समस्या यह है कि प्रत्येक एल्गोरिदम को GPU पर निष्पादन के लिए अनुकूलित नहीं किया जा सकता है। अलग-अलग जीपीयू कोर काफी धीमे होते हैं, और उनकी शक्ति केवल एक साथ काम करने पर ही स्पष्ट होती है। इसका मतलब यह है कि एल्गोरिदम उतना ही प्रभावी होगा जितना प्रोग्रामर इसे प्रभावी ढंग से समानांतर कर सकता है। ज्यादातर मामलों में, केवल एक अच्छा गणितज्ञ ही ऐसे काम को संभाल सकता है, जिनमें से बहुत कम सॉफ्टवेयर डेवलपर होते हैं।

और तीसरा, जीपीयू स्वयं ग्राफिक्स कार्ड पर स्थापित मेमोरी के साथ काम करता है, इसलिए हर बार जब जीपीयू का उपयोग किया जाता है तो दो अतिरिक्त कॉपी ऑपरेशन होंगे: एप्लिकेशन की रैम से इनपुट डेटा और GRAM से वापस एप्लिकेशन मेमोरी में आउटपुट डेटा। जैसा कि आप कल्पना कर सकते हैं, यह एप्लिकेशन रनटाइम में किसी भी लाभ को नकार सकता है (जैसा कि FlacCL टूल के मामले में है, जिसे हम बाद में देखेंगे)।

लेकिन वह सब नहीं है। ओपनसीएल के रूप में आम तौर पर स्वीकृत मानक के अस्तित्व के बावजूद, कई प्रोग्रामर अभी भी जीपीजीपीयू तकनीक के विक्रेता-विशिष्ट कार्यान्वयन का उपयोग करना पसंद करते हैं। CUDA विशेष रूप से लोकप्रिय साबित हुआ, हालांकि यह अधिक लचीला प्रोग्रामिंग इंटरफ़ेस प्रदान करता है (वैसे, OpenCL इन एनवीडिया ड्राइवर CUDA के शीर्ष पर लागू किया गया), लेकिन एप्लिकेशन को एक निर्माता के वीडियो कार्ड से मजबूती से जोड़ता है।

केजीपीयू या लिनक्स कर्नेल जीपीयू द्वारा त्वरित किया गया

यूटा विश्वविद्यालय के शोधकर्ताओं ने एक केजीपीयू प्रणाली विकसित की है जो सीयूडीए ढांचे का उपयोग करके कुछ लिनक्स कर्नेल कार्यों को जीपीयू पर निष्पादित करने की अनुमति देती है। इस कार्य को करने के लिए, एक संशोधित लिनक्स कर्नेल और एक विशेष डेमॉन का उपयोग किया जाता है जो उपयोगकर्ता स्थान में चलता है, कर्नेल अनुरोधों को सुनता है और उन्हें CUDA लाइब्रेरी का उपयोग करके वीडियो कार्ड ड्राइवर को भेजता है। दिलचस्प बात यह है कि इस तरह की वास्तुकला से उत्पन्न होने वाले महत्वपूर्ण ओवरहेड के बावजूद, केजीपीयू के लेखक एईएस एल्गोरिदम का कार्यान्वयन बनाने में कामयाब रहे, जो एन्क्रिप्शन गति को बढ़ाता है फाइल सिस्टम eCryptfs 6 बार।

अब वहां क्या है?

हालाँकि, अपनी युवावस्था के कारण, और ऊपर वर्णित समस्याओं के कारण, GPGPU कभी भी वास्तव में व्यापक तकनीक नहीं बन पाई उपयोगी सॉफ्टवेयर, अपनी क्षमताओं का उपयोग करते हुए, मौजूद है (यद्यपि कम मात्रा में)। विभिन्न हैश के क्रैकर सबसे पहले सामने आए, जिनके एल्गोरिदम को समानांतर करना बहुत आसान है।

मल्टीमीडिया एप्लिकेशन भी पैदा हुए, जैसे कि FlacCL एनकोडर, जो आपको ऑडियो ट्रैक को FLAC प्रारूप में ट्रांसकोड करने की अनुमति देता है। कुछ पहले से मौजूद अनुप्रयोगों ने भी GPGPU समर्थन हासिल कर लिया है, जिनमें से सबसे उल्लेखनीय ImageMagick है, जो अब OpenCL का उपयोग करके अपने कुछ काम को GPU पर लोड कर सकता है। डेटा संग्रहकर्ताओं और अन्य सूचना संपीड़न प्रणालियों को CUDA/OpenCL में स्थानांतरित करने की भी परियोजनाएं हैं (ATi Unixoids पसंद नहीं हैं)। हम लेख के निम्नलिखित अनुभागों में इनमें से सबसे दिलचस्प परियोजनाओं को देखेंगे, लेकिन अभी यह जानने का प्रयास करें कि इसे शुरू करने और स्थिर रूप से काम करने के लिए हमें क्या चाहिए।

जीपीयू ने प्रदर्शन में लंबे समय तक x86 प्रोसेसर को पीछे छोड़ दिया है

· दूसरे, वीडियो कार्ड के लिए नवीनतम मालिकाना ड्राइवरों को सिस्टम में स्थापित किया जाना चाहिए; वे कार्ड और ओपन ओपनसीएल की मूल जीपीजीपीयू प्रौद्योगिकियों दोनों के लिए समर्थन प्रदान करेंगे।

· और तीसरा, चूंकि वितरण डेवलपर्स ने अभी तक जीपीजीपीयू समर्थन के साथ एप्लिकेशन पैकेज वितरित करना शुरू नहीं किया है, इसलिए हमें स्वयं एप्लिकेशन बनाना होगा, और इसके लिए हमें निर्माताओं से आधिकारिक एसडीके की आवश्यकता है: सीयूडीए टूलकिट या एटीआई स्ट्रीम एसडीके। इनमें एप्लिकेशन बनाने के लिए आवश्यक हेडर फ़ाइलें और लाइब्रेरी शामिल हैं।

CUDA टूलकिट इंस्टॉल करें

ऊपर दिए गए लिंक का पालन करें और लिनक्स के लिए CUDA टूलकिट डाउनलोड करें (आप कई संस्करणों में से चुन सकते हैं, फेडोरा, आरएचईएल, उबंटू और एसयूएसई वितरण के लिए, x86 और x86_64 आर्किटेक्चर दोनों के लिए संस्करण हैं)। इसके अलावा, आपको वहां डेवलपर्स के लिए ड्राइवर किट भी डाउनलोड करनी होगी (लिनक्स के लिए डेवलपर ड्राइवर, वे सूची में पहले स्थान पर हैं)।

SDK इंस्टॉलर लॉन्च करें:

$ sudo sh cudatoolkit_4.0.17_linux_64_ubuntu10.10.run

जब इंस्टॉलेशन पूरा हो जाता है, तो हम ड्राइवरों को इंस्टॉल करने के लिए आगे बढ़ते हैं। ऐसा करने के लिए, X सर्वर बंद करें:

# sudo /etc/init.d/gdm रुकें

कंसोल खोलें और ड्राइवर इंस्टॉलर चलाएँ:

$ sudo sh devdriver_4.0_linux_64_270.41.19.run

इंस्टॉलेशन पूरा होने के बाद, X ​​प्रारंभ करें:

एप्लिकेशन को CUDA/OpenCL के साथ काम करने में सक्षम बनाने के लिए, हम LD_LIBRARY_PATH वेरिएबल में CUDA लाइब्रेरीज़ के साथ निर्देशिका का पथ सेट करते हैं:

$ निर्यात LD_LIBRARY_PATH=/usr/local/cuda/lib64

या, यदि आपने 32-बिट संस्करण स्थापित किया है:

$ निर्यात LD_LIBRARY_PATH=/usr/local/cuda/lib32

आपको CUDA हेडर फ़ाइलों के लिए पथ निर्दिष्ट करने की भी आवश्यकता है ताकि कंपाइलर उन्हें एप्लिकेशन बिल्ड चरण में ढूंढ सके:

$ निर्यात C_INCLUDE_PATH=/usr/local/cuda/include

बस, अब आप CUDA/OpenCL सॉफ़्टवेयर बनाना शुरू कर सकते हैं।

एटीआई स्ट्रीम एसडीके स्थापित करें

स्ट्रीम एसडीके को इंस्टॉलेशन की आवश्यकता नहीं है, इसलिए वेबसाइट से डाउनलोड किए गए एएमडी संग्रह को किसी भी निर्देशिका में अनपैक किया जा सकता है ( सर्वोत्तम पसंद/opt होगा) और उसका पथ उसी LD_LIBRARY_PATH वेरिएबल में लिखें:

$ wget http://goo.gl/CNCNo

$ sudo tar -xzf ~/AMD-APP-SDK-v2.4-lnx64.tgz -C /opt

$ निर्यात LD_LIBRARY_PATH=/opt/AMD-APP-SDK-v2.4-lnx64/lib/x86_64/

$ निर्यात C_INCLUDE_PATH=/opt/AMD-APP-SDK-v2.4-lnx64/include/

CUDA टूलकिट की तरह, 32-बिट सिस्टम पर x86_64 को x86 से बदला जाना चाहिए। अब रूट डायरेक्टरी में जाएं और icd-registration.tgz आर्काइव को अनपैक करें (यह एक तरह का फ्री है) लाइसेंस कुंजी):

$ sudo tar -xzf /opt/AMD-APP-SDK-v2.4-lnx64/icd-registration.tgz -साथ /

हम क्लिनफो टूल का उपयोग करके पैकेज की सही स्थापना/संचालन की जांच करते हैं:

$ /opt/AMD-APP-SDK-v2.4-lnx64/bin/x86_64/clinfo

इमेजमैजिक और ओपनसीएल

ImageMagick में OpenCL समर्थन काफी समय से उपलब्ध है, लेकिन यह किसी भी वितरण में डिफ़ॉल्ट रूप से सक्षम नहीं है। इसलिए, हमें स्रोत से आईएम को स्वयं संकलित करना होगा। इसमें कुछ भी जटिल नहीं है, आपको जो कुछ भी चाहिए वह पहले से ही एसडीके में है, इसलिए असेंबली को एनवीडिया या एएमडी से कोई अतिरिक्त लाइब्रेरी स्थापित करने की आवश्यकता नहीं है। तो, स्रोतों के साथ संग्रह को डाउनलोड/अनपैक करें:

$ wget http://goo.gl/F6VYV

$ tar -xjf ImageMagick-6.7.0-0.tar.bz2

$ सीडी इमेजमैजिक-6.7.0-0

$ sudo apt-get install बिल्ड-एसेंशियल

हम कॉन्फिगरेटर लॉन्च करते हैं और ओपनसीएल समर्थन के लिए इसका आउटपुट लेते हैं:

$ LDFLAGS=-L$LD_LIBRARY_PATH ./confi gure | ग्रेप -ई सीएल.एच -ई ओपनसीएल

कमांड से सही आउटपुट कुछ इस तरह दिखना चाहिए:

सीएल/सीएल.एच प्रयोज्यता की जाँच कर रहा हूँ... हाँ

सीएल/सीएल.एच उपस्थिति की जाँच कर रहा हूँ... हाँ

सीएल/सीएल.एच के लिए जाँच कर रहा हूँ... हाँ

OpenCL/cl.h प्रयोज्यता की जाँच करना... नहीं

OpenCL/cl.h उपस्थिति की जाँच कर रहा हूँ... नहीं

OpenCL/cl.h...नहीं की जाँच हो रही है

ओपनसीएल लाइब्रेरी की जांच हो रही है... -एलओपनसीएल

शब्द "हाँ" को या तो पहली तीन पंक्तियों में या दूसरी (या दोनों विकल्पों में एक साथ) अंकित किया जाना चाहिए। यदि यह मामला नहीं है, तो सबसे अधिक संभावना है कि C_INCLUDE_PATH वैरिएबल को सही ढंग से प्रारंभ नहीं किया गया था। यदि "नहीं" शब्द अंकित है अंतिम पंक्ति, तो समस्या LD_LIBRARY_PATH वेरिएबल में है। यदि सब कुछ ठीक है, तो निर्माण/स्थापना प्रक्रिया शुरू करें:

$सुडो स्थापित करेंसाफ

आइए जांचें कि क्या ImageMagick वास्तव में OpenCL समर्थन के साथ संकलित किया गया था:

$ /usr/local/bin/convert -version | ग्रेप विशेषताएँ

विशेषताएं: ओपनएमपी ओपनसीएल

आइए अब परिणामी गति वृद्धि को मापें। ImageMagick डेवलपर्स इसके लिए कॉन्वोल्व फ़िल्टर का उपयोग करने की सलाह देते हैं:

$ समय /usr/bin/convert image.jpg -convolve "-1, -1, -1, -1, 9, -1, -1, -1, -1" image2.jpg

$ समय /usr/local/bin/convert image.jpg -convolve "-1, -1, -1, -1, 9, -1, -1, -1, -1" image2.jpg

कुछ अन्य ऑपरेशन, जैसे कि आकार बदलना, को भी अब बहुत तेजी से काम करना चाहिए, लेकिन आपको ImageMagick से यह उम्मीद नहीं करनी चाहिए कि वह ग्राफिक्स को ख़तरनाक गति से संसाधित करना शुरू कर देगा। अब तक, पैकेज का एक बहुत छोटा हिस्सा ओपनसीएल का उपयोग करके अनुकूलित किया गया है।

FlacCL (फ्लैकुडा)

FlacCL, FLAC प्रारूप में ऑडियो फ़ाइलों का एक एनकोडर है, जो अपने काम में OpenCL की क्षमताओं का उपयोग करता है। यह विंडोज़ के लिए CUETools पैकेज में शामिल है, लेकिन मोनो के लिए धन्यवाद, इसका उपयोग लिनक्स पर भी किया जा सकता है। एन्कोडर के साथ एक संग्रह प्राप्त करने के लिए, निम्नलिखित कमांड चलाएँ:

$ mkdir flaccl && cd flaccl

$ wget www.cuetools.net/install/flaccl03.rar

$ sudo apt-get install unrar मोनो

$ unrar x fl accl03.rar

ताकि प्रोग्राम ओपनसीएल लाइब्रेरी ढूंढ सके, हम एक प्रतीकात्मक लिंक बनाते हैं:

$ ln -s $LD_LIBRARY_PATH/libOpenCL.so libopencl.so

अब एनकोडर चलाएँ:

$ मोनो CUETools.FLACCL.cmd.exe संगीत.wav

यदि त्रुटि संदेश "त्रुटि: अनुरोधित संकलन आकार 32 के आवश्यक कार्यसमूह आकार से बड़ा है" स्क्रीन पर प्रदर्शित होता है, तो हमारे सिस्टम में वीडियो कार्ड बहुत कमजोर है, और शामिल कोर की संख्या को निर्दिष्ट संख्या तक कम किया जाना चाहिए '--ध्वज समूह-आकार XX' का उपयोग करते हुए, जहां XX कोर की आवश्यक संख्या है।

मैं तुरंत कहूंगा कि ओपनसीएल के लंबे आरंभीकरण समय के कारण, ध्यान देने योग्य लाभ केवल पर्याप्त लंबे ट्रैक पर ही प्राप्त किया जा सकता है। FlacCL लघु ऑडियो फ़ाइलों को अपने पारंपरिक संस्करण के समान ही गति से संसाधित करता है।

oclHashcat या जानवर बल जल्दी से

जैसा कि मैंने पहले ही कहा, विभिन्न क्रैकर्स और ब्रूट-फोर्स पासवर्ड सिस्टम के डेवलपर्स अपने उत्पादों में जीपीजीपीयू समर्थन जोड़ने वाले पहले लोगों में से थे। उन को नई टेक्नोलॉजीएक वास्तविक पवित्र कब्र बन गया, जिसने तेज़ GPU प्रोसेसर के कंधों पर स्वाभाविक रूप से आसानी से समानांतर कोड को स्थानांतरित करना संभव बना दिया। इसलिए, यह आश्चर्य की बात नहीं है कि अब ऐसे कार्यक्रमों के दर्जनों विभिन्न कार्यान्वयन हैं। लेकिन इस लेख में मैं उनमें से केवल एक के बारे में बात करूंगा - oclHashcat।

oclHashcat एक हैकर है जो अत्यधिक हैश के आधार पर पासवर्ड का अनुमान लगा सकता है उच्च गति, OpenCL का उपयोग करके GPU की शक्ति का उपयोग करते हुए। यदि आप प्रोजेक्ट वेबसाइट पर प्रकाशित मापों पर विश्वास करते हैं, तो nVidia GTX580 पर MD5 पासवर्ड चुनने की गति 15,800 मिलियन संयोजन प्रति सेकंड तक है, जिसकी बदौलत oclHashcat केवल 9 मिनट में औसत जटिलता वाला आठ-अक्षर वाला पासवर्ड ढूंढने में सक्षम है।

कार्यक्रम OpenCL और CUDA, MD5, md5($pass.$salt), md5(md5($pass)), vBulletin एल्गोरिदम का समर्थन करता है< v3.8.5, SHA1, sha1($pass.$salt), хэши MySQL, MD4, NTLM, Domain Cached Credentials, SHA256, поддерживает распределенный подбор паролей с задействованием мощности нескольких машин.

$7z x oclHashcat-0.25.7z

$cd oclHashcat-0.25

और प्रोग्राम चलाएँ (हम हैश की एक नमूना सूची और एक नमूना शब्दकोश का उपयोग करेंगे):

$ ./oclHashcat64.bin example.hash ?l?l?l?l example.dict

oclHashcat उपयोगकर्ता अनुबंध का पाठ खोलेगा, जिस पर आपको "YES" टाइप करके सहमति देनी होगी। इसके बाद सर्च प्रक्रिया शुरू हो जाएगी, जिसे दबाकर प्रगति का पता लगाया जा सकेगा . प्रक्रिया को रोकने के लिए क्लिक करें

फिर से शुरू करने के लिए - . आप प्रत्यक्ष गणना का भी उपयोग कर सकते हैं (उदाहरण के लिए, आआआआआ से zzzzzzzz तक):

$ ./oclHashcat64.bin हैश.txt ?l?l?l?l ?l?l?l?l

और शब्दकोश के विभिन्न संशोधन और प्रत्यक्ष खोज विधि, साथ ही उनके संयोजन (आप इसके बारे में फ़ाइल docs/examples.txt में पढ़ सकते हैं)। मेरे मामले में, पूरे शब्दकोश में खोज की गति 11 मिनट थी, जबकि सीधी खोज (आआआआआ से ज़ज़्ज़्ज़्ज़्ज़ तक) लगभग 40 मिनट तक चली। GPU (RV710 चिप) की औसत गति 88.3 मिलियन/सेकेंड थी।

निष्कर्ष

कई अलग-अलग सीमाओं और सॉफ्टवेयर विकास की जटिलता के बावजूद, जीपीजीपीयू उच्च प्रदर्शन वाले डेस्कटॉप कंप्यूटर का भविष्य है। लेकिन सबसे महत्वपूर्ण बात यह है कि आप अभी इस तकनीक की क्षमताओं का उपयोग कर सकते हैं, और यह न केवल विंडोज मशीनों पर, बल्कि लिनक्स पर भी लागू होता है।




मित्रों को बताओ