सवाल:
सॉफ्टवेयर उद्योग की सर्वसम्मति यह है कि स्वच्छ और सरल कोड कोड आधार की दीर्घकालिक व्यवहार्यता और इसके स्वामित्व वाले संगठन के लिए मौलिक है। इन गुणों के कारण रखरखाव लागत कम हो जाती है और कोड बेस के जारी रहने की संभावना बढ़ जाती है।
हालांकि, SIMD कोड सामान्य एप्लिकेशन कोड से अलग है, और मैं जानना चाहूंगा कि क्या विशेष रूप से SIMD कोड पर लागू होने वाले स्वच्छ और सरल कोड के बारे में समान सहमति है।
मेरे सवाल का बैकग्राउंड।
मैं विभिन्न छवि प्रसंस्करण और विश्लेषण कार्यों के लिए बहुत सारे SIMD (एकल-निर्देश, एकाधिक डेटा) कोड लिखता हूं। हाल ही में मुझे इन कार्यों की एक छोटी संख्या को एक वास्तुकला (SSE2) से दूसरे (ARM NEON) में पोर्ट करना था।
कोड सिकुड़ते लिपटे सॉफ़्टवेयर के लिए लिखा गया है, इसलिए यह अप्रतिबंधित पुनर्वितरण अधिकारों जैसे MATLAB के बिना मालिकाना भाषाओं पर निर्भर नहीं कर सकता है।
विशिष्ट कोड संरचना का एक उदाहरण:
- सभी मेमोरी, बफर और आजीवन प्रबंधन के लिए OpenCV के मैट्रिक्स प्रकार (
Mat
) का उपयोग करना । - इनपुट तर्कों के आकार (आयामों) की जांच करने के बाद, पिक्सल की प्रत्येक पंक्ति के आरंभिक पते पर संकेत ले जाया जाता है।
- पिक्सेल गणना, और प्रत्येक इनपुट मैट्रिक्स से पिक्सेल की प्रत्येक पंक्ति के शुरुआती पते कुछ निम्न-स्तरीय C ++ फ़ंक्शन में पारित किए जाते हैं।
- ये निम्न स्तर के C ++ फ़ंक्शंस में SIMD इंट्रेंसिक्स ( इंटेल आर्किटेक्चर , और ARM नीयन के लिए ) का उपयोग किया जाता है, जो कच्चे सूचक पते से लोड होता है और बचत करता है।
- इन निम्न-स्तरीय C ++ फ़ंक्शन के लक्षण:
- विशिष्ट रूप से एक-आयामी (लगातार स्मृति में)
- मेमोरी आवंटन से संबंधित नहीं है।
(प्रत्येक आवंटन, जिसमें अस्थायी कर्मचारी भी शामिल हैं, को OpenCV सुविधाओं का उपयोग करके बाहरी कोड द्वारा नियंत्रित किया जाता है।) - प्रतीकों की नाम लंबाई की सीमा (आंतरिक, चर नाम, आदि) लगभग 10 - 20 वर्ण हैं, जो काफी अधिक है।
(टेक्नो-बेबीबल की तरह पढ़ता है।) - SIMD चर का पुन: उपयोग हतोत्साहित किया जाता है क्योंकि कंपाइलर सही ढंग से पार्सिंग कोड में काफी छोटी हैं जो "एकल-असाइनमेंट" कोडिंग शैली में नहीं लिखा गया है।
(मैंने कई संकलक बग रिपोर्ट दर्ज की हैं।)
SIMD प्रोग्रामिंग के किन पहलुओं के कारण चर्चा सामान्य मामले से भिन्न होगी? या, SIMD अलग क्यों है?
प्रारंभिक विकास लागत के संदर्भ में
- यह सर्वविदित है कि अच्छे प्रदर्शन के साथ C ++ SIMD कोड की प्रारंभिक विकास लागत लापरवाही से लिखे C ++ कोड की तुलना में लगभग 10x - 100x (विस्तृत मार्जिन के साथ) है ।
- जैसा कि प्रदर्शन बनाम पढ़ने योग्य / क्लीनर कोड के बीच चयन के जवाबों में उल्लेख किया गया है ? , अधिकांश कोड (लापरवाही से लिखे गए कोड और SIMD कोड सहित) शुरू में न तो साफ है और न ही तेज है ।
- कोड प्रदर्शन (स्केलर और SIMD कोड दोनों) में विकासवादी सुधार को हतोत्साहित किया जाता है (क्योंकि इसे एक तरह के सॉफ्टवेयर rework के रूप में देखा जाता है ), और लागत और लाभ को ट्रैक नहीं किया जाता है।
प्रवृत्ति के संदर्भ में
(जैसे पेरेटो सिद्धांत, उर्फ 80-20 नियम )
- भले ही छवि प्रसंस्करण में एक सॉफ्टवेयर सिस्टम (कोड आकार और कार्यक्षमता दोनों में) का 20% शामिल है, छवि प्रसंस्करण तुलनात्मक रूप से धीमा है (जब खर्च किए गए सीपीयू समय के प्रतिशत के रूप में देखा जाता है), 80% से अधिक समय ले रहा है।
- यह डेटा आकार प्रभाव के कारण है: मेगाबाइट में एक विशिष्ट छवि आकार मापा जाता है, जबकि गैर-छवि डेटा का विशिष्ट आकार किलोबाइट में मापा जाता है।
- इमेज प्रोसेसिंग कोड के भीतर, एक SIMD प्रोग्रामर को C ++ कोड में लूप संरचना की पहचान करके हॉटस्पॉट्स को शामिल करने वाले 20% कोड को स्वचालित रूप से पहचानने के लिए प्रशिक्षित किया जाता है। इस प्रकार, एक SIMD प्रोग्रामर के दृष्टिकोण से, "कोड जो मायने रखता है" का 100% प्रदर्शन अड़चन है।
- अक्सर एक छवि प्रसंस्करण प्रणाली में, कई हॉटस्पॉट मौजूद होते हैं और समय के तुलनीय अनुपात लेते हैं। उदाहरण के लिए, कुल समय के लिए प्रत्येक में 20 हॉटस्पॉट हो सकते हैं (20%, 18%, 16%, 14%, 12%)। उच्च प्रदर्शन लाभ प्राप्त करने के लिए, सभी हॉटस्पॉट को SIMD में फिर से लिखना होगा।
- इसे गुब्बारे-पॉपिंग नियम के रूप में संक्षेपित किया गया है : एक गुब्बारे को दो बार पॉप नहीं किया जा सकता है।
- मान लीजिए कि कुछ गुब्बारे हैं, उनमें से 5 को कहें। उन्हें अलग करने का एकमात्र तरीका उन्हें एक-एक करके पॉप करना है।
- एक बार पहला गुब्बारा पॉप होने के बाद, शेष 4 गुब्बारे अब कुल निष्पादन समय का उच्च प्रतिशत शामिल करते हैं।
- आगे लाभ कमाने के लिए, एक और गुब्बारा पॉप करना चाहिए।
(यह अनुकूलन के 80-20 नियम की अवहेलना है : 20% सबसे कम-फांसी वाले फलों को चुनने के बाद एक अच्छा आर्थिक परिणाम प्राप्त किया जा सकता है।)
पठनीयता और रखरखाव के संदर्भ में
SIMD कोड को पढ़ना मुश्किल है।
- यह तब भी सच है, जब कोई हर सॉफ्टवेयर इंजीनियरिंग का सबसे अच्छा अभ्यास करता है, जैसे कि नामकरण, एनकैप्सुलेशन, कांस्टीट्यूशन (और साइड-इफेक्ट्स को स्पष्ट करना), फ़ंक्शन अपघटन आदि।
- अनुभवी SIMD प्रोग्रामर के लिए भी यह सही है।
Optimal SIMD कोड अपने समकक्ष C ++ प्रोटोटाइप कोड की तुलना में बहुत विपरीत है, (टिप्पणी देखें) ।
- SIMD कोड को गर्भपात करने के कई तरीके हैं, लेकिन 10 प्रयासों में से केवल 1 ही तेजी से परिणाम प्राप्त करेगा।
- (यह है कि उच्च विकास लागत का औचित्य साबित करने के लिए 4x-10x प्रदर्शन लाभ की धुनों में। व्यवहार में उच्चतर लाभ भी देखा गया है।)
(टिप्पणी)
यह एमआईटी हैलाइड परियोजना का मुख्य शोध है- कागज के शीर्षक शब्दशः उद्धृत करते हुए:
"इमेज प्रोसेसिंग पाइपलाइनों के आसान अनुकूलन के लिए शेड्यूल से एल्गोरिदम को डिकूप्ल करना"
आगे की प्रयोज्यता के संदर्भ में
- SIMD कोड कड़ाई से एकल वास्तुकला से बंधा है। प्रत्येक नए आर्किटेक्चर (या SIMD रजिस्टरों में से प्रत्येक को चौड़ा करना) को फिर से लिखना पड़ता है।
- सॉफ्टवेयर विकास के बहुमत के विपरीत, SIMD कोड के प्रत्येक टुकड़े को आमतौर पर एक ही उद्देश्य के लिए लिखा जाता है जो कभी नहीं बदलता है।
(अन्य आर्किटेक्चर के लिए पोर्टिंग के अपवाद के साथ।) - कुछ आर्किटेक्चर पूर्ण पिछड़ी संगतता (इंटेल) को बनाए रखते हैं; कुछ तुच्छ राशि से कम हो जाते हैं (ARM AArch64, के
vtbl
साथ प्रतिस्थापितvtblq
) लेकिन जो कुछ कोड को संकलित करने में विफल होने के लिए पर्याप्त है।
कौशल और प्रशिक्षण के संदर्भ में
- यह स्पष्ट नहीं है कि SIMD कोड लिखने और बनाए रखने के लिए नए प्रोग्रामर को ठीक से प्रशिक्षित करने के लिए कौन से ज्ञान आवश्यक हैं।
- कॉलेज के स्नातक जिन्होंने स्कूल में SIMD प्रोग्रामिंग सीखी है, एक अव्यवहारिक कैरियर ट्रैक के रूप में इसे तुच्छ समझते हैं और इसे खारिज कर देते हैं।
- Disassembly-रीडिंग और निम्न-स्तरीय प्रदर्शन प्रोफाइलिंग को उच्च-प्रदर्शन SIMD कोड लिखने के लिए दो मौलिक कौशल के रूप में उद्धृत किया जाता है। हालांकि, यह स्पष्ट नहीं है कि इन दो कौशलों में प्रोग्रामर को व्यवस्थित रूप से कैसे प्रशिक्षित किया जाए।
- आधुनिक सीपीयू वास्तुकला (जो पाठ्यपुस्तकों में सिखाई गई बातों से महत्वपूर्ण रूप से भिन्न होता है) प्रशिक्षण को और भी कठिन बना देता है।
शुद्धता और दोष-संबंधी लागतों के संदर्भ में
- एक एकल SIMD प्रसंस्करण फ़ंक्शन वास्तव में पर्याप्त रूप से एकजुट होता है जो एक द्वारा शुद्धता स्थापित कर सकता है:
- औपचारिक तरीकों को लागू करना (पेन-एंड-पेपर के साथ) , और
- आउटपुट पूर्णांक श्रेणियों (प्रोटोटाइप कोड के साथ और रन-टाइम के बाहर प्रदर्शन) को सत्यापित करना ।
- सत्यापन प्रक्रिया, हालांकि, बहुत महंगी है (कोड समीक्षा पर 100% समय और प्रोटोटाइप मॉडल की जाँच पर 100% समय खर्च करता है), जो कि SIMD कोड की पहले से ही महंगी विकास लागत को ट्रिपल करता है।
- यदि कोई बग किसी तरह इस सत्यापन प्रक्रिया के माध्यम से फिसलने का प्रबंधन करता है, तो संदिग्ध दोषपूर्ण फ़ंक्शन को बदलने (फिर से लिखना) को छोड़कर "मरम्मत" (फिक्स) करना लगभग असंभव है।
- SIMD कोड C ++ कंपाइलर (कोड जनरेटर का अनुकूलन) में दोषों के कुंद से ग्रस्त है।
- C ++ अभिव्यक्ति टेम्पलेट्स का उपयोग करके उत्पन्न SIMD कोड भी संकलक के दोषों से बहुत ग्रस्त है।
विघटनकारी नवाचारों के संदर्भ में
शिक्षाविदों से कई समाधान प्रस्तावित किए गए हैं, लेकिन कुछ व्यापक व्यावसायिक उपयोग देख रहे हैं।
- MIT हैलाइड
- स्टैनफोर्ड डार्करूम
- NT2 (न्यूमेरिकल टेम्पलेट टूलबॉक्स) और संबंधित Boost.SIMD
व्यापक व्यावसायिक उपयोग वाले पुस्तकालय भारी सिमड-सक्षम नहीं लगते हैं।
- ओपन-सोर्स लाइब्रेरी सिमड के लिए गुनगुना लगती हैं।
- संस्करण 2.4.9 के रूप में बड़ी संख्या में OpenCV API फ़ंक्शंस की रूपरेखा तैयार करने के बाद हाल ही में मेरा यह पहला अवलोकन है।
- कई अन्य इमेज प्रोसेसिंग लाइब्रेरियों को मैंने प्रोफिल्ड किया है जो कि SIMD का भारी उपयोग नहीं करते हैं, या वे सच्चे हॉटस्पॉट्स को याद करते हैं।
- वाणिज्यिक पुस्तकालय पूरी तरह से SIMD से बचते हैं।
- कुछ मामलों में, मैंने बाद के संस्करण में पहले के संस्करण में SIMD- अनुकूलित कोड को पुनः प्राप्त करने वाली छवि प्रसंस्करण पुस्तकालयों को बाद के संस्करण में गैर-SIMD कोड में देखा है, जिसके परिणामस्वरूप गंभीर प्रदर्शन प्रतिगमन हुए हैं।
(विक्रेता की प्रतिक्रिया है कि संकलक कीड़ों से बचना आवश्यक था।)
- कुछ मामलों में, मैंने बाद के संस्करण में पहले के संस्करण में SIMD- अनुकूलित कोड को पुनः प्राप्त करने वाली छवि प्रसंस्करण पुस्तकालयों को बाद के संस्करण में गैर-SIMD कोड में देखा है, जिसके परिणामस्वरूप गंभीर प्रदर्शन प्रतिगमन हुए हैं।
- ओपन-सोर्स लाइब्रेरी सिमड के लिए गुनगुना लगती हैं।
इस प्रोग्रामर का सवाल: क्या कम विलंबता कोड कभी-कभी "बदसूरत" होना पड़ता है? संबंधित है, और मैंने पहले कुछ साल पहले अपने विचार बिंदुओं को समझाने के लिए उस प्रश्न का उत्तर लिखा था।
हालांकि, यह जवाब "समय से पहले अनुकूलन" के दृष्टिकोण के लिए "तुष्टिकरण" के लिए बहुत अधिक है, यानी दृष्टिकोण के लिए:
- सभी ऑप्टिमाइज़ेशन परिभाषा द्वारा समय से पहले (या प्रकृति द्वारा अल्पकालिक ), और हैं
- दीर्घकालिक अनुकूलन का एकमात्र अनुकूलन सादगी की ओर है।
लेकिन इस तरह के दृष्टिकोण इस एसीएम लेख में लड़े जाते हैं ।
यह सब मुझे पूछने के लिए प्रेरित करता है:
SIMD कोड सामान्य एप्लिकेशन कोड से अलग है, और मैं जानना चाहूंगा कि क्या SIMD कोड के लिए स्वच्छ और सरल कोड के मूल्य के बारे में समान उद्योग सहमति है।