2015-10-15 12 views
10

का उपयोग करने के बाद धीमा चलता है मुझे कुछ एसएसई 2 और एवीएक्स कोड के साथ एक अजीब समस्या है जो मैं काम कर रहा हूं। मैं जीसीसी का उपयोग कर अपना आवेदन बना रहा हूं जो रनटाइम सीपीयू फीचर डिटेक्शन। वस्तु फ़ाइलों, प्रत्येक सीपीयू सुविधा के लिए अलग झंडों से निर्माण कर रहे हैं, उदाहरण के लिए:एसईएस AVX

g++ -c -o ConvertSamples_SSE.o ConvertSamples_SSE.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -msse 
g++ -c -o ConvertSamples_SSE2.o ConvertSamples_SSE2.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -msse2 
g++ -c -o ConvertSamples_AVX.o ConvertSamples_AVX.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -mavx 

जब मैं पहली बार कार्यक्रम शुरू, मुझे लगता है कि SSE2 दिनचर्या गैर SSE दिनचर्या पर एक अच्छा गति को बढ़ावा देने के साथ सामान्य के अनुसार हैं (लगभग 100% तेज)। किसी भी एवीएक्स दिनचर्या को चलाने के बाद, सटीक वही एसएसई 2 दिनचर्या अब बहुत धीमी गति से चलती है।

क्या कोई यह बता सकता है कि इसका क्या कारण हो सकता है?

एवीएक्स दिनचर्या से पहले, सभी परीक्षण 80-130% तेज होते हैं तो एफपीयू गणित, जैसा कि यहां देखा जा सकता है, एवीएक्स दिनचर्या के बाद, एसएसई दिनचर्या बहुत धीमी होती है।

यदि मैं एवीएक्स परीक्षण दिनचर्या छोड़ देता हूं तो मुझे यह प्रदर्शन हानि कभी नहीं दिखाई देती है।

यहाँ मेरी SSE2 दिनचर्या

void Float_S16(const float *in, int16_t *out, const unsigned int samples) 
{ 
    static float ratio = (float)Limits<int16_t>::range()/(float)Limits<float>::range(); 
    static __m128 mul = _mm_set_ps1(ratio); 

    unsigned int i; 
    for (i = 0; i < samples - 3; i += 4, in += 4, out += 4) 
    { 
    __m128i con = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(in), mul)); 
    out[0] = ((int16_t*)&con)[0]; 
    out[1] = ((int16_t*)&con)[2]; 
    out[2] = ((int16_t*)&con)[4]; 
    out[3] = ((int16_t*)&con)[6]; 
    } 

    for (; i < samples; ++i, ++in, ++out) 
    *out = (int16_t)lrint(*in * ratio); 
} 

और उसी के avx संस्करण है।

void Float_S16(const float *in, int16_t *out, const unsigned int samples) 
{ 
    static float ratio = (float)Limits<int16_t>::range()/(float)Limits<float>::range(); 
    static __m256 mul = _mm256_set1_ps(ratio); 

    unsigned int i; 
    for (i = 0; i < samples - 7; i += 8, in += 8, out += 8) 
    { 
    __m256i con = _mm256_cvtps_epi32(_mm256_mul_ps(_mm256_load_ps(in), mul)); 
    out[0] = ((int16_t*)&con)[0]; 
    out[1] = ((int16_t*)&con)[2]; 
    out[2] = ((int16_t*)&con)[4]; 
    out[3] = ((int16_t*)&con)[6]; 
    out[4] = ((int16_t*)&con)[8]; 
    out[5] = ((int16_t*)&con)[10]; 
    out[6] = ((int16_t*)&con)[12]; 
    out[7] = ((int16_t*)&con)[14]; 
    } 

    for(; i < samples; ++i, ++in, ++out) 
    *out = (int16_t)lrint(*in * ratio); 
} 

मैंने इसे वालग्रिंड के माध्यम से भी चलाया है जो कोई त्रुटि नहीं पहचानता है।

+1

समय कैसे मापा जाता है अन्य बदलाव केवल 1 चक्र कर रहे हैं? – Gilles

+0

@ घड़ी 'घड़ी_gettime (CLOCK_MONOTONIC, और प्रारंभ) का उपयोग करके;' पहले और बाद में, फिर अंतर की गणना। – Geoffrey

+0

मैंने मिश्रित एसएसईएक्स और एवीएक्स कोड के साथ उत्सुक समस्याओं में भाग लिया है ..., ज्यादातर क्योंकि लिंक टाइम कोड पीढ़ी/आदि। समस्या का। अपनी असेंबली फ़ाइलों को देखो (और शायद पोस्ट)। – Christopher

उत्तर

15

मिश्रण एवीएक्स कोड और विरासत एसएसई कोड प्रदर्शन प्रदर्शन जुर्माना लगाता है। कोड का एवीएक्स सेगमेंट के बाद विशेष रूप से बस एसएसई कोड निष्पादित करने से पहले VZEROALL निर्देश निष्पादित करना सबसे उचित समाधान है।

इंटेल के आरेख के अनुसार, राज्य सी में प्रवेश या बाहर होने पर दंड (एवीएक्स रजिस्टरों के ऊपरी हिस्से के साथ विरासत एसएसई) 100 घड़ी चक्रों के क्रम में है।

संदर्भ::

+2

यह समस्या कठोर प्रभाव को प्रभावित कर सकती है जो इस जुर्माना से पूरी तरह से असंबंधित प्रतीत होती है। [यह प्रश्न] देखें (http://stackoverflow.com/q/21960229/2542702) जहां ओपी ने एक सिस्टम पर 500 से अधिक धागे के साथ गति देखी, जिसमें केवल आठ हाइपर-थ्रेड थे। –

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