2015-02-23 9 views
5
के लिए पढ़ता है

मेरा प्रश्न किताब से निम्नलिखित वाक्यांश के संबंध में है:सरणी vectorization

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

मेरे अनुमान क्यों AOS बेहतर प्रदर्शन में हो सकता है पर जब अलग है, या सब बेहतर, एक ही ढांचे में क्षेत्रों एकल vectorization समय में भाग ले रहे हैं।

उदाहरण (सिर्फ एक अवधारणा है, कोई ठोस, या बिल्कुल भी काम कर कोड):

/*Note that the types of data I maintain the same intentionally, 
    to simplify discussion*/ 
struct Data { 
    float mean; 
    float distribution[10] 
} 

और परिभाषित उन की सरणी

Data aos[5];

अब कुछ डेटा स्रोत से बेतरतीब ढंग से मिला , यदि वेक्टरेशन लूप के दौरान मैं कुछ ऐसा करता हूं:

float* dataPtr = &(aos[0].mean); 

#pragma simd 
for(int i=0; i< 60; i++) 
{ 
    const float mean = (*dataPtr); 
    /*do something with mean */ 

    dataPtr++; 

    /*do something with distribution */ 
} 

इसके परिणामस्वरूप बेहतर प्रदर्शन होगा, एसओए के मामले में, मैं कैश लाइन पर अधिक जानकारी दूंगा जो मुझे वास्तव में इस गणना के दौरान आवश्यक हो सकता है। कुछ सीपीयू प्री-कैशिंग? एओएस के परिणामस्वरूप बेहतर प्रदर्शन में इसके परिणामस्वरूप।

क्या मेरी धारणा सही है, या कुछ और है?

+3

डरावनी तीन अक्षर शब्दकोष: SOA = Arrays का संरचना, AoS = संरचनाओं का ऐरे। –

+0

@ हंसपैसेंट: इस तरह वे कैसे कहते हैं, और पूर्ण नाम लिखने से शीर्षक बहुत लंबा और कम बदसूरत नहीं होता है। – Tigran

+3

@ टिग्रान: उन लोगों के लाभ के लिए, जो आपकी पुस्तक की शब्दावली नहीं जानते हैं, के लिए शर्तों को परिभाषित करना, इसमें अधिक समय नहीं लगता है। –

उत्तर

8

आप अपने प्रोग्राम को दो तरीकों से समानांतर कर सकते हैं: क्षैतिज और लंबवत। मुझे लगता है कि आप उन दो दृष्टिकोणों को मिला रहे हैं।

क्षैतिज समांतरता आपके सिम इकाई में प्रत्येक लेन को एक अलग डेटा पर काम कर रहे एक अलग "थ्रेड" के रूप में मानती है। लंबवत समांतरता एक ही डेटा ऑब्जेक्ट पर काम कर रही संपूर्ण सिम इकाई लेती है, जो इसकी आंतरिक बहु-आयामीता से लाभ उठाने का प्रयास करती है।

एक ठोस उदाहरण देने के लिए: मान लें कि आपके पास 2 एरे X और Y 3 डी वेक्टर हैं जिन्हें आप जोड़ना चाहते हैं।

  • क्षैतिज दृष्टिकोण: SIMD यूनिट के हर लेन करना होगा:

    for(idx = 0; idx<size; idx+=SIMD_size) { 
        ... = X[idx+laneid].x + Y[idx+laneid].x; 
        ... = X[idx+laneid].y + Y[idx+laneid].y; 
        ... = X[idx+laneid].z + Y[idx+laneid].z; 
    } 
    
  • कार्यक्षेत्र दृष्टिकोण:

    : SIMD यूनिट के हर लेन ही वेक्टर का एक अलग घटक लेता है
    for(idx = 0; idx<size; idx+=1) { 
        ... = X[idx].coord(laneid) + Y[idx].coord(laneid); 
    } 
    

वर्टिकल दृष्टिकोण लागू करना आसान है। वास्तव में, कंपाइलर्स पहले ही ऑटो-वेक्टरिज़ करने की कोशिश कर रहे हैं। समस्या यह है कि सिम इकाई की चौड़ाई बढ़ रही है, इसलिए कार्यान्वयन इससे लाभ नहीं उठा सकता है। यदि आप 4-चौड़े से 16-चौड़े सिम तक स्विच करते हैं, तो आप अभी भी अपने 3 डी वेक्टर के समानांतर में केवल 3 संख्याएं जोड़ रहे हैं।

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


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

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

एक बेहतर समाधान एक हाइब्रिड दृष्टिकोण होना है: आप अपने डेटा को एक ऐरे-ऑफ-स्ट्रक्चर-ऑफ-एरेज़-ऑफ-सिम-इन-साइज में पैक करते हैं। लेकिन यह एक और कहानी है ...

+1

सोए के साथ पैथोलॉजिकल केस का उल्लेख करना चाह सकता है - जहां एक ही लॉजिकल स्ट्रक्चर के दो घटकों में कैश लाइन विवाद होता है (एक से पढ़ना एक दूसरे को उतारने का कारण बनता है) – Yakk

1

हां, आप स्थिति को समझते हैं।

यदि आप एक ही संरचना से कई मूल्य पढ़ते हैं, तो सीपीयू को केवल उन संरचना सदस्यों के लिए आवश्यक कैश लाइनों को लाने की आवश्यकता होगी - शायद केवल एक, यदि संरचना के सदस्यों को अच्छी तरह से रखा गया हो। तो कैश ऐसा दिख सकता है (जहां v मूल्यों आप चाहते हैं, और खाली स्लॉट अन्य मूल्यों हैं)

line 1: | v | | v | v | | | v | | 

उन मूल्यों को प्रत्येक एक अलग सरणी से पढ़ने के लिए है, तो यह एक लाने के लिए होगा प्रत्येक मूल्य के लिए पूरी कैश लाइन। तो कैश की तरह

line 1: | | | v | | | | | | 
line 2: | | | | | v | | | | 
line 3: | | v | | | | | | | 
line 4: | | | v | | | | | | 

लग सकता है आप क्रम में सरणी के माध्यम से काम कर रहे हैं, तो यह अच्छी बात है - आप जल्द ही अतिरिक्त मानों फ़ेच किए गए की आवश्यकता होगी, दिया जाएगा।

हालांकि, अगर आप क्रम में काम नहीं कर रहे हैं (पुस्तक के शब्दों में, आप "यादृच्छिक या असंगत परिस्थितियों" में हैं), तो आपको हर बार आवश्यकता से अधिक लाने से कैश में जगह बर्बाद हो जाएगी, और आप ' यदि आवश्यक मूल्य एक संरचना में एक साथ थे, तो अधिक स्मृति बैंडविड्थ का उपयोग कर समाप्त हो जाएगा।