2016-02-06 7 views
6

कार्यात्मक प्रोग्रामिंग, map फ़ंक्शन का एक लाभ यह है कि इसे समानांतर में निष्पादित करने के लिए कार्यान्वित किया जा सकता है।कार्यात्मक प्रोग्रामिंग में "कम" फ़ंक्शन समानांतर हो सकता है?

तो एक 4 कोर हार्डवेयर पर, इस कोड और map के एक समानांतर कार्यान्वयन 4 मूल्यों एक ही समय में संसाधित किया जा करने की अनुमति होगी।

let numbers = [0,1,2,3] 
let increasedNumbers = numbers.map { $0 + 1 } 

ठीक है, अब reduce समारोह के बारे में बात करने देता है।

वापसी बार-बार कॉल एक संचित मूल्य प्रारंभिक प्रारंभ और स्वयं के प्रत्येक तत्व के साथ गठबंधन, बारी में का परिणाम है, यानी वापसी गठबंधन (गठबंधन (... गठबंधन (गठबंधन (प्रारंभिक, आत्म [0]), स्वयं [1]), ... स्वयं [गिनती -2]), स्वयं [गिनती -1])।

मेरा प्रश्न: reduce फ़ंक्शन को समानांतर में निष्पादित करने के लिए कार्यान्वित किया जा सकता है? या, परिभाषा के अनुसार, यह कुछ ऐसा है जो केवल अनुक्रमिक रूप से निष्पादित किया जा सकता है?

उदाहरण:

let sum = numbers.reduce(0) { $0 + $1 } 
+5

ऑपरेशन पर निर्भर करता है ... यदि आपके पास एक सहयोगी है तो हाँ आप '(एक% बी)% (सी% डी)' '((%%)% c ​​के बजाय'% d' कर सकते हैं उदाहरण के लिए (और अंदरूनी वाले बाहरी बाहरी से पहले समानांतर में (यदि '%' ऑपरेशन है) – Carsten

+2

कभी-कभी आप ऑपरेशन को तोड़ सकते हैं - एक अच्छा उदाहरण सॉर्ट करना है जहां आप कुछ ऐसा कर सकते हैं जैसे कि विलय (जो समानांतर हो सकता है)) डालने के बजाय;) – Carsten

+0

आप 'मानचित्र' को 'कम करने' का एक विशेष मामला मान सकते हैं। अब आपके प्रश्न के लिए इसका क्या अर्थ है? :-) – Bergi

उत्तर

4

सबसे आम कटौती में से एक सभी तत्वों का योग है।

((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 हार्डवेयर (उदाहरण के लिए के तरह 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 सामान किसी एकल थ्रेड स्मृति का एक सन्निहित हिस्सा पर काम के भीतर लागू होता है। आप (या आपकी कार्यात्मक भाषा के लिए कंपाइलर!) दोनों तकनीकों का उपयोग कर सकते हैं और इन्हें कोर पर निष्पादन इकाइयों को संतृप्त करने वाले एकाधिक धागे रखने के लिए कर सकते हैं।


इस जवाब में कार्यात्मक-प्रोग्रामिंग की कमी के लिए क्षमा करें। आपने अनुमान लगाया होगा कि मैंने सिम टैग के कारण यह प्रश्न देखा था।: पी

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

+0

आपके महान उत्तर के लिए बहुत धन्यवाद। यह सामान बेहद दिलचस्प है। –

+0

@appzYourLife: चीयर्स। :) मुझे यह भी यकीन नहीं था कि इस तरह का जवाब वह था जिसे आप उम्मीद कर रहे थे। –

+0

अद्यतन और अधिसूचना के लिए धन्यवाद (वास्तव में मैंने अद्यतन को नोटिस नहीं किया)। मैं इसे बहुत सावधानी से पढ़ूंगा। –

संबंधित मुद्दे