Ostatnio postanowiłem przyśpieszyć obliczenia w swoich programach za pomocą SIMD intela, postanowiłem najpierw sprawdzić jakie korzyści takie działanie przyniesie a wiec napisałem program testujący :
#include <iostream>
#include <ctime>
__declspec(align(16)) struct Vectorf{
float x,y,z,tmp;
};
using namespace std;
inline void add2(Vectorf *a, Vectorf *b){
a->x+=b->x;
a->y+=b->y;
a->z+=b->z;
a->tmp+=b->tmp;
}
inline void add(Vectorf *a, Vectorf *b, Vectorf *c){
c->x=a->x+b->x;
c->y=a->y+b->y;
c->z=a->z+b->z;
c->tmp=a->tmp+b->tmp;
}
inline void add_fast(Vectorf *a, Vectorf *b, Vectorf *c){
__asm{
mov esi, a
mov ebx, b
mov edi, c
movaps xmm0, [esi]
addps xmm0, [ebx]
movaps [edi], xmm0
/* wersja gdy nie ma wyrownania do 16
movups xmm0, [esi]
movups xmm1, [ebx]
addps xmm0, xmm1
movups [edi], xmm0*/
}
}
#define n 50000000
int main(){
Vectorf a,b,c;
clock_t start,koniec;
cout<<sizeof(Vector)<<endl;
start = clock();
for(long i=0; i<n; i++) {
a.x=3.3f; a.y=-2.6f; a.z=1.2f; a.tmp=0.0f;
b.x=-2.8f; b.y=5.0f; b.z=-4.3f; b.tmp=0.0f;
add2(&a,&b);
}
koniec = clock();
cout<<"Czas : "<<(float)(koniec-start)/CLOCKS_PER_SEC<<endl;
cout<<"add per sec: "<<(float)n/((float)(koniec-start)/CLOCKS_PER_SEC)<<endl;
start = clock();
for(long i=0; i<n; i++){
a.x=3.3f; a.y=-2.6f; a.z=1.2f;a.tmp=0.0f;
b.x=-2.8f; b.y=5.0f; b.z=-4.3f;b.tmp=0.0f;
add(&a,&b,&c);
}
koniec = clock();
cout<<"Czas : "<<(float)(koniec-start)/CLOCKS_PER_SEC<<endl;
cout<<"add per sec: "<<(float)n/((float)(koniec-start)/CLOCKS_PER_SEC)<<endl;
start = clock();
for(long i=0; i<n; i++){
a.x=3.3f; a.y=-2.6f; a.z=1.2f; a.tmp=0.0f;
b.x=-2.8f; b.y=5.0f; b.z=-4.3f; b.tmp=0.0f;
add_fast(&a,&b,&c);
}
koniec = clock();
cout<<"Czas : "<<(float)(koniec-start)/CLOCKS_PER_SEC<<endl;
cout<<"add per sec: "<<(float)n/((float)(koniec-start)/CLOCKS_PER_SEC)<<endl;
cout<<"float'y : "<<2.5f * 3.4f << endl;
cout<<"int'y : "<<2*5<<endl;
a.x=3.3f; a.y=-2.6f; a.z=1.2f;
b.x=-2.8f; b.y=5.0f; b.z=-4.3f;
add_fast(&a, &b, &c);
cout<<c.x<<" "<<c.y<<" "<<c.z<<endl;
system("pause");
return 0;
}
Wyniki dla wersji Debbug są takie jak można się było spodziewać :
czas 1 : 2.719 // a+=b
czas 2 : 2.797 // c=a+b
czas 3 : 2.297 // SIMD c=a+b
Jeśli jednak przejdę na release wyniki są takie :
czas 1 : 0 // a+=b
czas 2 : 0 // c=a+b
czas 3 : 0.906 // SIMD C=a+b
Czemu tak się dzieje? SIMD chyba powinno być szybsze w obu przypadkach. Nie wiem czy ja coś źle robię, czy kompilator coś miesza w ramach optymalizacji?