यह पोस्ट some days ago पर पोस्ट किए गए किसी अन्य से निकटता से संबंधित है। इस बार, मैंने एक साधारण कोड लिखा था जो तत्वों के सरणी की एक जोड़ी जोड़ता है, परिणाम को किसी अन्य सरणी में मानों से गुणा करता है और इसे आगे सरणी में संग्रहीत करता है, सभी वैरिएबल फ़्लोटिंग पॉइंट डबल परिशुद्धता टाइप किया जाता है।जीसीसी एसएसई कोड अनुकूलन
मैंने उस कोड के दो संस्करण बनाए: एक एसएसई निर्देशों के साथ, कॉल का उपयोग करके और उनके बिना किसी अन्य के बाद मैंने उन्हें gcc और -O0 अनुकूलन स्तर के साथ संकलित किया। मैं उन्हें नीचे लिखें:
// SSE VERSION
#define N 10000
#define NTIMES 100000
#include <time.h>
#include <stdio.h>
#include <xmmintrin.h>
#include <pmmintrin.h>
double a[N] __attribute__((aligned(16)));
double b[N] __attribute__((aligned(16)));
double c[N] __attribute__((aligned(16)));
double r[N] __attribute__((aligned(16)));
int main(void){
int i, times;
for(times = 0; times < NTIMES; times++){
for(i = 0; i <N; i+= 2){
__m128d mm_a = _mm_load_pd(&a[i]);
_mm_prefetch(&a[i+4], _MM_HINT_T0);
__m128d mm_b = _mm_load_pd(&b[i]);
_mm_prefetch(&b[i+4] , _MM_HINT_T0);
__m128d mm_c = _mm_load_pd(&c[i]);
_mm_prefetch(&c[i+4] , _MM_HINT_T0);
__m128d mm_r;
mm_r = _mm_add_pd(mm_a, mm_b);
mm_a = _mm_mul_pd(mm_r , mm_c);
_mm_store_pd(&r[i], mm_a);
}
}
}
//NO SSE VERSION
//same definitions as before
int main(void){
int i, times;
for(times = 0; times < NTIMES; times++){
for(i = 0; i < N; i++){
r[i] = (a[i]+b[i])*c[i];
}
}
}
जब उन्हें -O0 साथ संकलन, जीसीसी, XMM/MMX रजिस्टर और SSE intstructions का उपयोग करता है नहीं तो विशेष रूप से -mno-SSE (और अन्य) विकल्प दिए। मैंने दूसरे कोड के लिए उत्पन्न असेंबली कोड का निरीक्षण किया और मैंने देखा कि यह movsd, जोड़ और mulsd निर्देशों का उपयोग करता है। इसलिए यह एसएसई निर्देशों का उपयोग करता है, लेकिन केवल उन लोगों में से जो रजिस्टरों के निम्नतम भाग का उपयोग करते हैं, अगर मैं गलत नहीं हूं। पहले सी कोड के लिए जेनरेट किया गया असेंबली कोड एडीपी और mulpd निर्देशों की अपेक्षा के अनुसार उपयोग किया गया, हालांकि एक बहुत बड़ा असेंबली कोड उत्पन्न हुआ था।
वैसे भी, पहला कोड बेहतर लाभ प्राप्त करना चाहिए, जहां तक मुझे पता है, सिम प्रतिमान के, क्योंकि प्रत्येक पुनरावृत्ति दो परिणाम मानों की गणना की जाती है। फिर भी, दूसरा कोड कुछ ऐसा करता है जैसे कि पहले की तुलना में 25 प्रतिशत तेज। मैंने एकल परिशुद्धता मानों के साथ एक परीक्षण भी किया और इसी तरह के परिणाम प्राप्त किए। इसके लिए क्या कारण है?
ऑप्टिमाइज़ेशन के बिना संकलन करते समय प्रदर्शन की तुलना करना काफी अर्थहीन है। – interjay
आप केवल 2 एक्स अंकगणितीय परिचालनों के लिए 3 एक्स लोड और 1 एक्स स्टोर कर रहे हैं, इसलिए आप बैंडविड्थ-सीमित होने की संभावना अधिकतर होंगे। –
क्या होता है जब आप _mm_prefetch कॉल को हटाते हैं? मुझे लगता है कि वे आपको – TJD