2016-12-01 7 views
10

संक्षिप्त सवाल यह है कि यदि मेरे पास एक ऐसा कार्य है जो दो वैक्टर लेता है। एक इनपुट है और दूसरा आउटपुट (कोई उपनाम नहीं है)। मैं केवल उनमें से एक को संरेखित कर सकता हूं, मुझे किसको चुनना चाहिए?असाइन किए गए लोड बनाम unaligned स्टोर

अब संस्करण है कि एक समारोह पर विचार करें,

void func(size_t n, void *in, void *out) 
{ 
    __m256i *in256 = reinterpret_cast<__m256i *>(in); 
    __m256i *out256 = reinterpret_cast<__m256i *>(out); 
    while (n >= 32) { 
     __m256i data = _mm256_loadu_si256(in256++); 
     // process data 
     _mm256_storeu_si256(out256++, data); 
     n -= 32; 
    } 
    // process the remaining n % 32 bytes; 
} 

है in और out 32-बाइट गठबंधन कर रहे हैं, तो vmovdqu बजाय vmovdqa का उपयोग करने का कोई जुर्माना है। सबसे खराब स्थिति यह है कि दोनों को असाइन किया गया है, और चार लोड/स्टोर में से एक कैश-लाइन सीमा पार करेगा।

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

+3

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

+0

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

+0

@ कोडीग्रे वैसे भी धन्यवाद। मैं इस समस्या के कुछ परीक्षणों पर काम कर रहा हूं। अब तक मैं जो कह सकता हूं वह केवल "यह निर्भर करता है" –

उत्तर

0

यहां स्पष्ट स्थिति देने का जोखिम: "वास्तविक कोड और वास्तविक डेटा दोनों के साथ आपको बेंचमार्क करने की आवश्यकता" को छोड़कर कोई "सही उत्तर" नहीं है। जो भी संस्करण तेजी से दृढ़ता से आपके द्वारा उपयोग किए जा रहे CPU पर निर्भर करता है, आप प्रत्येक पैकेज और कई अन्य चीजों पर गणना की गणना करते हैं।

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

__m256i next = _mm256_loadu_si256(in256++); 
for(...){ 
    __m256i data = next; // usually 0 cost 
    next = _mm256_loadu_si256(in256++); 
    // do computations and store data 
} 

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

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