Sto provando a definire il tempo necessario per calcolare un sqrt utilizzando il seguente codice C semplice, dove readTSC() è una funzione per leggere il contatore di cicli della CPU.Perché il compilatore genera sqrts aggiuntivi nel codice assembly compilato
double sum = 0.0;
int i;
tm = readTSC();
for (i = 0; i < n; i++)
sum += sqrt((double) i);
tm = readTSC() - tm;
printf("%lld clocks in total\n",tm);
printf("%15.6e\n",sum);
Tuttavia, come ho stampato il codice assembly utilizzando
gcc -S timing.c -o timing.s
su una macchina Intel, il risultato (vedi sotto) è stato sorprendente?
Perché nel codice assembly sono presenti due sqrts con uno che utilizza l'istruzione sqrtsd
e l'altro con una chiamata di funzione? È correlato allo srotolamento del loop e sta tentando di eseguire due sqrts in un'unica iterazione?
E come capire la linea
ucomisd %xmm0, %xmm0
Perché ci si confronta %xmm0
a se stesso?
//----------------start of for loop----------------
call readTSC
movq %rax, -32(%rbp)
movl $0, -4(%rbp)
jmp .L4
.L6:
cvtsi2sd -4(%rbp), %xmm1
// 1. use sqrtsd instruction
sqrtsd %xmm1, %xmm0
ucomisd %xmm0, %xmm0
jp .L8
je .L5
.L8:
movapd %xmm1, %xmm0
// 2. use C funciton call
call sqrt
.L5:
movsd -16(%rbp), %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, -16(%rbp)
addl $1, -4(%rbp)
.L4:
movl -4(%rbp), %eax
cmpl -36(%rbp), %eax
jl .L6
//----------------end of for loop----------------
call readTSC
Questo deve essere un codice non ottimizzato. [Codice reale] (http://goo.gl/CewylI) disegna correttamente i rami (senza rami presi sul caso non NaN), e lascia fuori 'je' poiché sarà sempre vero dopo un' ucomisd '. –