मैं अच्छे प्रदर्शन लाभ के साथ कुछ समय के लिए इंटेल के एसएसई इंट्रिनिक्स का उपयोग कर रहा हूं। इसलिए, मुझे उम्मीद है कि एवीएक्स इंट्रिनिक्स मेरे कार्यक्रमों को आगे बढ़ाएगा। दुर्भाग्यवश, यह अब तक मामला नहीं था। शायद मैं एक बेवकूफ गलती कर रहा हूं, इसलिए अगर कोई मेरी मदद कर सकता है तो मैं बहुत आभारी रहूंगा।एसएसई के बजाय एवीएक्स इंट्रिनिक्स का उपयोग गति में सुधार नहीं करता है - क्यों?
मैं उबंटू 11.10 का उपयोग जी ++ 4.6.1 के साथ करता हूं। मैंने
g++ simpleExample.cpp -O3 -march=native -o simpleExample
परीक्षण प्रणाली में इंटेल i7-2600 सीपीयू के साथ अपना प्रोग्राम संकलित किया (नीचे देखें)।
यहां कोड है जो मेरी समस्या का उदाहरण है। अपने सिस्टम पर, मैं आउटपुट प्राप्त
98.715 ms, b[42] = 0.900038 // Naive
24.457 ms, b[42] = 0.900038 // SSE
24.646 ms, b[42] = 0.900038 // AVX
ध्यान दें कि गणना sqrt (sqrt (sqrt (x))) केवल कि स्मृति बैंडविड्थ सुनिश्चित करने के लिए निष्पादन की गति को सीमित नहीं करता चुना गया था; यह सिर्फ एक उदाहरण है।
simpleExample.cpp:
#include <immintrin.h>
#include <iostream>
#include <math.h>
#include <sys/time.h>
using namespace std;
// -----------------------------------------------------------------------------
// This function returns the current time, expressed as seconds since the Epoch
// -----------------------------------------------------------------------------
double getCurrentTime(){
struct timeval curr;
struct timezone tz;
gettimeofday(&curr, &tz);
double tmp = static_cast<double>(curr.tv_sec) * static_cast<double>(1000000)
+ static_cast<double>(curr.tv_usec);
return tmp*1e-6;
}
// -----------------------------------------------------------------------------
// Main routine
// -----------------------------------------------------------------------------
int main() {
srand48(0); // seed PRNG
double e,s; // timestamp variables
float *a, *b; // data pointers
float *pA,*pB; // work pointer
__m128 rA,rB; // variables for SSE
__m256 rA_AVX, rB_AVX; // variables for AVX
// define vector size
const int vector_size = 10000000;
// allocate memory
a = (float*) _mm_malloc (vector_size*sizeof(float),32);
b = (float*) _mm_malloc (vector_size*sizeof(float),32);
// initialize vectors //
for(int i=0;i<vector_size;i++) {
a[i]=fabs(drand48());
b[i]=0.0f;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Naive implementation
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
s = getCurrentTime();
for (int i=0; i<vector_size; i++){
b[i] = sqrtf(sqrtf(sqrtf(a[i])));
}
e = getCurrentTime();
cout << (e-s)*1000 << " ms" << ", b[42] = " << b[42] << endl;
// -----------------------------------------------------------------------------
for(int i=0;i<vector_size;i++) {
b[i]=0.0f;
}
// -----------------------------------------------------------------------------
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// SSE2 implementation
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
pA = a; pB = b;
s = getCurrentTime();
for (int i=0; i<vector_size; i+=4){
rA = _mm_load_ps(pA);
rB = _mm_sqrt_ps(_mm_sqrt_ps(_mm_sqrt_ps(rA)));
_mm_store_ps(pB,rB);
pA += 4;
pB += 4;
}
e = getCurrentTime();
cout << (e-s)*1000 << " ms" << ", b[42] = " << b[42] << endl;
// -----------------------------------------------------------------------------
for(int i=0;i<vector_size;i++) {
b[i]=0.0f;
}
// -----------------------------------------------------------------------------
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AVX implementation
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
pA = a; pB = b;
s = getCurrentTime();
for (int i=0; i<vector_size; i+=8){
rA_AVX = _mm256_load_ps(pA);
rB_AVX = _mm256_sqrt_ps(_mm256_sqrt_ps(_mm256_sqrt_ps(rA_AVX)));
_mm256_store_ps(pB,rB_AVX);
pA += 8;
pB += 8;
}
e = getCurrentTime();
cout << (e-s)*1000 << " ms" << ", b[42] = " << b[42] << endl;
_mm_free(a);
_mm_free(b);
return 0;
}
किसी भी मदद की सराहना की है!
मुझे पता है कि AVX कभी नकल करते था नहीं था रुचि रखते हैं के लिए है - आप इस के लिए एक संदर्भ है? किस सीपीयू पर विशेष रूप से यह मामला होगा? –
[निर्देश तालिका] (http://www.agner.org/optimize/instruction_tables.pdf) के अनुसार, सैंडी ब्रिज पर, पृष्ठ 87--88, ऐसा लगता है कि 'VDIVPS/PD' पोर्ट 0 पर 2 माइक्रोप्स निष्पादित करता है , 'DIVPS/PS' के लिए 1 माइक्रोप की तुलना में। 'एसक्यूआरटी 'निर्देश समान होंगे। चूंकि विभाजन इकाई पाइपलाइन नहीं है, इसलिए निष्पादन में 2x अधिक समय लगता है। यह इंगित करता है कि सैंडी ब्रिज में वास्तव में विभाजन इकाई का केवल 128-बिट कार्यान्वयन है। –
@ नोर्बर्ट: स्पष्टीकरण के लिए धन्यवाद - मुझे –