सबसे आम कटौती में से एक सभी तत्वों का योग है।
((a+b) + c) + d == (a + b) + (c+d) # associative
a+b == b+a # commutative
समानता पूर्णांकों के लिए काम करता है यही कारण है, तो आप एक से अधिक कम निर्भरता चेन, बहु सूत्रण की इजाजत दी और SIMD समानांतरवाद करने के लिए एक लंबे समय से निर्भरता श्रृंखला से संचालन के क्रम बदल सकते हैं।
यह गणितीय वास्तविक संख्याओं, but not for floating point numbers के लिए भी सच है। कई मामलों में, catastrophic cancellation की उम्मीद नहीं है, इसलिए अंतिम परिणाम भारी प्रदर्शन लाभ के लायक होने के लिए पर्याप्त होगा। सी/सी ++ कंपाइलर्स के लिए, यह -ffast-math
विकल्प द्वारा सक्षम अनुकूलन में से एक है। (-ffast-math
की सिर्फ इस हिस्से के लिए एक -fassociative-math
विकल्प, और infinities की कमी Nans के बारे में मान्यताओं के बिना नहीं है।)
यह अगर एक विस्तृत लोड कई उपयोगी मान स्कूप नहीं कर सकते हैं ज्यादा SIMD speedup पाने के लिए मुश्किल है। इंटेल के AVX2 ने "इकट्ठा" लोड जोड़ा, लेकिन ओवरहेड बहुत अधिक है। हैसवेल के साथ, स्केलर कोड का उपयोग करने के लिए आमतौर पर तेज़ होता है, लेकिन बाद में माइक्रोआर्किटेक्चर में तेजी से एकत्र होता है। तो सिमड कमी सरणी पर या अधिक प्रभावी रूप से संग्रहीत अन्य डेटा पर अधिक प्रभावी है।
आधुनिक SIMD हार्डवेयर (उदाहरण के लिए x86 के sse तरह 16B वैक्टर के साथ,) एक वेक्टर रजिस्टर में तैरता 2 लगातार डबल परिशुद्धता लोड करके काम करता है। एक पैक-एफपी-एड निर्देश है जो दो वैक्टरों के संबंधित तत्व जोड़ता है। तथाकथित "ऊर्ध्वाधर" वेक्टर ऑपरेशंस (जहां दो वैक्टरों में संबंधित तत्वों के बीच एक ही ऑपरेशन होता है) "क्षैतिज" परिचालनों से बहुत सस्ता है (एक दूसरे के लिए एक वेक्टर में दो double
एस जोड़ना)।
तो एएसएम स्तर पर, आप एक पाश है कि एक वेक्टर संचायक के एक आधा में सभी सम-संख्यांकित तत्वों, और दूसरे आधे में सभी विषम क्रमांकित तत्वों का योग है। फिर अंत में एक क्षैतिज ऑपरेशन उन्हें जोड़ता है। तो मल्टीथ्रेडिंग के बिना भी, सिमड का उपयोग करने के लिए सहयोगी संचालन की आवश्यकता होती है (या कम से कम, सहयोगी के लिए पर्याप्त बंद करें, जैसे फ्लोटिंग पॉइंट आमतौर पर है)। यदि आपके इनपुट में अनुमानित पैटर्न है, जैसे कि +1.001, -0.9 99, रद्दीकरण त्रुटियां एक बड़ी सकारात्मक को एक बड़ी नकारात्मक संख्या में जोड़ने से रोक सकती हैं, तो प्रत्येक रद्दीकरण अलग से हुआ था।
व्यापक वैक्टर, या संकरा तत्वों के साथ
, एक वेक्टर संचायक अधिक तत्वों पकड़, SIMD के लाभ में वृद्धि होगी।
आधुनिक हार्डवेयर निष्पादन इकाइयों है कि एक (या कभी कभी दो) एफपी घड़ी प्रति वेक्टर कहते बनाए रख सकते हैं pipelined है, लेकिन हर एक का परिणाम 5 चक्रों के लिए तैयार नहीं है। हार्डवेयर की थ्रूपुट क्षमताओं को संतृप्त करने के लिए लूप में एकाधिक संचयकों का उपयोग करने की आवश्यकता होती है, इसलिए 5 या 10 अलग-अलग लूप-संचालित निर्भरता श्रृंखलाएं होती हैं। (कंक्रीट होने के लिए, इंटेल स्काइलेक 4 सी विलंबता के साथ वेक्टर-एफपी गुणा, जोड़, या एफएमए (मिश्रित मल्टीप्ली-एड) करता है और एक 0.5 सी थ्रुपुट के साथ। 4 सी/0.5 सी = 8 एफपी अतिरिक्त उड़ान में स्काइलेक के एफपी गणित को संतृप्त करने के लिए यूनिट। प्रत्येक ऑपरेशन आठ सिंगल-प्रेसिजन फ्लोट्स, चार डबल-प्रेसिजन फ्लोट्स, एक 16 बी वेक्टर, या स्केलर का 32 बी वेक्टर हो सकता है। (उड़ान में कई ऑपरेशन रखने से स्केलर सामान भी तेज हो सकता है, लेकिन यदि कोई डेटा- स्तर समानांतरवाद उपलब्ध, तो आप शायद यह रूप में अच्छी तरह के रूप में इस्तेमाल कई एक्युमुलेटरों vectorize कर सकते हैं।) x86 निर्देश समय, पाइपलाइन विवरण, और एएसएम अनुकूलन सामान के लिए http://agner.org/optimize/ देखें। लेकिन ध्यान दें कि यहां सब कुछ नियोन, पीपीसी Altivec की बांह पर लागू होता है, और अन्य SIMD आर्किटेक्चर। वे सभी वेक्टर रजिस्टरों और समान वेक्टर निर्देश दिया है।
एक सान्द्र के लिए rete उदाहरण, here's how gcc 5.3 auto-vectorizes a FP sum reduction। यह केवल एक संचयक का उपयोग करता है, इसलिए यह स्काइलेक के लिए 8 थ्रुपुट के कारक पर गायब है। क्लेंग एक और अधिक चालाक है, और uses two accumulators, but not as many as the loop unroll factor स्किलेक के अधिकतम थ्रूपुट के 1/4 प्राप्त करने के लिए। ध्यान दें कि यदि आप संकलन विकल्पों से -ffast-math
निकालते हैं, तो एफपी लूप (स्केलर सिंगल जोड़ें) addps
(पैक एकल जोड़ें) के बजाय उपयोग करता है। पूर्णांक लूप अभी भी स्वतः-vectorizes, क्योंकि पूर्णांक गणित सहयोगी है।
अभ्यास में, स्मृति बैंडविड्थ सीमित कारक समय के सबसे अधिक है। हैसवेल और बाद में इंटेल सीपीयू एल 1 कैश से प्रति चक्र दो 32 बी भार को बनाए रख सकते हैं। In theory, they could sustain that from L2 cache। साझा एल 3 कैश एक और कहानी है: यह मुख्य स्मृति की तुलना में बहुत तेज है, लेकिन इसकी बैंडविड्थ सभी कोरों द्वारा साझा की जाती है। एल 1 या एल 2 के लिए यह कैश-अवरुद्ध (उर्फ loop tiling) बनाता है जब यह 256k से अधिक डेटा के साथ काम करते समय सस्ते तरीके से किया जा सकता है। उत्पादन के 10 एमआईबीबी को कम करने और फिर कम करने के बजाय, 128k हिस्सों में उत्पादन करते हैं और उन्हें कम करते हैं जबकि वे अभी भी मुख्य स्मृति में धक्का देने के लिए एल 2 कैश में रहते हैं और उन्हें वापस लाने के लिए रेड्यूसर होता है। उच्च स्तर की भाषा, आपकी सर्वश्रेष्ठ शर्त यह उम्मीद कर सकती है कि कार्यान्वयन आपके लिए यह करता है। सीपीयू वास्तव में क्या करता है, इस संदर्भ में आप आदर्श रूप से ऐसा करना चाहते हैं।
ध्यान दें कि सभी SIMD speedup सामान किसी एकल थ्रेड स्मृति का एक सन्निहित हिस्सा पर काम के भीतर लागू होता है। आप (या आपकी कार्यात्मक भाषा के लिए कंपाइलर!) दोनों तकनीकों का उपयोग कर सकते हैं और इन्हें कोर पर निष्पादन इकाइयों को संतृप्त करने वाले एकाधिक धागे रखने के लिए कर सकते हैं।
इस जवाब में कार्यात्मक-प्रोग्रामिंग की कमी के लिए क्षमा करें। आपने अनुमान लगाया होगा कि मैंने सिम टैग के कारण यह प्रश्न देखा था।: पी
मैं अन्य परिचालनों के अलावा सामान्यीकृत करने की कोशिश नहीं कर रहा हूं। आईडीके आप किस तरह की चीजें कार्यात्मक-प्रोग्रामिंग लोगों को कटौती के साथ मिलते हैं, लेकिन जोड़ या तुलना (न्यूनतम/अधिकतम, गिनती मिलान ढूंढें) वे हैं जो सिम-ऑप्टिमाइज़ेशन उदाहरणों के रूप में उपयोग किए जाते हैं।
ऑपरेशन पर निर्भर करता है ... यदि आपके पास एक सहयोगी है तो हाँ आप '(एक% बी)% (सी% डी)' '((%%)% c के बजाय'% d' कर सकते हैं उदाहरण के लिए (और अंदरूनी वाले बाहरी बाहरी से पहले समानांतर में (यदि '%' ऑपरेशन है) – Carsten
कभी-कभी आप ऑपरेशन को तोड़ सकते हैं - एक अच्छा उदाहरण सॉर्ट करना है जहां आप कुछ ऐसा कर सकते हैं जैसे कि विलय (जो समानांतर हो सकता है)) डालने के बजाय;) – Carsten
आप 'मानचित्र' को 'कम करने' का एक विशेष मामला मान सकते हैं। अब आपके प्रश्न के लिए इसका क्या अर्थ है? :-) – Bergi