Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1037 connectés 

  FORUM HardWare.fr
  Programmation
  ASM

  [Défit !] Normaliser un vecteur

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Défit !] Normaliser un vecteur

n°1332418
lirey83
Posté le 26-03-2006 à 12:44:04  profilanswer
 

Salut,
 
J'essaies d'écrire le code le plus rapide pour normaliser un vecteur. Après pas mal de tatonnement je suis arrivé au code suivant :
void  Normalize(TDVector3D &V)
{
  __asm
  {
    mov    eax,[ebp+0x8]
    fld    qword ptr [eax]        // ST0=X       X
    fld    ST                     // ST1=X ST0=X
    fmul   ST,ST                  // ST1=X ST0=X²
    fld    qword ptr [eax+0x8]    // ST2=X ST1=X² ST0=Y      Y
    fld    ST                     // ST3=X ST2=X² ST1=Y ST0=Y
    fmul   ST,ST                  // ST3=X ST2=X² ST1=Y ST0=Y²
    faddp  ST(2),ST               // ST2=X ST1=X²+Y² ST0=Y
    fld    qword ptr [eax+0x10]   // ST3=X ST2=X²+Y² ST1=Y ST0=Z     Z
    fld    ST                     // ST4=X ST3=X²+Y² ST2=Y ST1=Z ST0=Z
    fmul   ST,ST                  // ST4=X ST3=X²+Y² ST2=Y ST1=Z ST0=Z²
    faddp  ST(3),ST               // ST3=X ST2=X²+Y²+Z² ST1=Y ST0=Z
    fxch   ST(2)                  // ST3=X ST2=Z ST1=Y ST0=X²+Y²+Z²
    fsqrt                         // ST3=X ST2=Z ST1=Y ST0=Sqrt(X²+Y²+Z²)
    fld1                          // ST4=X ST3=Z ST2=Y ST1=Sqrt(X²+Y²+Z²) ST0=1
    fdivrp                        // ST3=X ST2=Z ST1=Y ST0=1/Sqrt(X²+Y²+Z²)=N
    fmul   ST(3),ST               // ST3=X*N ST2=Z ST1=Y ST0=N
    fmul   ST(2),ST               // ST3=X*N ST2=Z*N ST1=Y ST0=N
    fmulp                         // ST2=X*N ST1=Z*N ST0=Y*N
    fstp   qword ptr [eax+0x8]    // ST1=X*N ST0=Z*N     Y
    fstp   qword ptr [eax+0x10]   // ST0=X*N      Z
    fstp   qword ptr [eax]        // vide    X
    fwait
  }
}
 
ou j'ai défini le type vecteur :
typedef struct
{
  double X, Y, Z;
} TDVector3D;
 
Cela marche super bien, mais je voudrais encore plus rapide !!!
 
Je suis tombé que le bout de code suivant :
float fast_invSqrt(float x)
{
  float xhalf = 0.5f*x;
  int i = *(int*)&x; // get bits for floating value
  i = 0x5f3759df - (i>>1); // give initial guess y0
  x = *(float*)&i; // convert bits back to float
  x *= 1.5f - xhalf*x*x; // newton step, repeating this step increases accuracy
  x *= 1.5f - xhalf*x*x;
 
  return x;
}
 
qui calcule une approximation rapide de 1/Sqrt(x). J'ai voulu traduire ce code en assembleur pour l'intégrer dans le mien mais je n'y suis pas arrivé. Je ne sais pas comment traduire tous ces transtypages ....
 
J'ai aussi voulu mettre juste avant l'appel de fsqrt un test de nullité et d'égalité à 1. Le code suivant refuse de fonctionner :
    fldz
    fcomp
    fstsw  AX
    fwait
    jnz @Fin
 
idem avec un fld1. @Fin est l'étiquette de sortie de la routine puisqu'il n'y a rien à faire si la norme du vecteur vaut 0 ou 1.
 
Est-ce qu'une bonne âme pourrait m'aider.
 
Cordialement,
Lionel

mood
Publicité
Posté le 26-03-2006 à 12:44:04  profilanswer
 

n°1332434
skelter
Posté le 26-03-2006 à 13:26:45  profilanswer
 

il y a une code similaire dans le source de quake 3, fichier "code/game/q_math.c", ligne 532
 

Code :
  1. /*
  2. ** float q_rsqrt( float number )
  3. */
  4. float Q_rsqrt( float number )
  5. {
  6. long i;
  7. float x2, y;
  8. const float threehalfs = 1.5F;
  9. x2 = number * 0.5F;
  10. y  = number;
  11. i  = * ( long * ) &y;      // evil floating point bit level hacking
  12. i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
  13. y  = * ( float * ) &i;
  14. y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
  15. // y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
  16. #ifndef Q3_VM
  17. #ifdef __linux__
  18. assert( !isnan(y) ); // bk010122 - FPE?
  19. #endif
  20. #endif
  21. return y;
  22. }


 

Citation :


Je ne sais pas comment traduire tous ces transtypages ....


 
ca doit se faire assez facilement en asm
 

Code :
  1. int i = *(int*)&x


ca mappe l'image memoire du flottant x dans l'entier i
 

Citation :

x = *(float*)&i


meme chose mais dans l'autre sens
 
le but est de permettre d'appliquer des opérations "bit à bit" sur l'image mémoire d'un flottant

n°1332653
lirey83
Posté le 27-03-2006 à 00:03:16  profilanswer
 

Merci Skelter de ta réponse mais elle ne m'aide pas beaucoup. J'ai bien compris qu'il y avait un bidouillage sur les bits du nombre pour obtenir la première approximation pour les itérations de l'algorithme de Newton.
Je doute pas que cela se fasse facilement en asm, j'aimerais savoir comment ;)
 
A++
Lionel

n°1335310
lirey83
Posté le 30-03-2006 à 10:16:23  profilanswer
 

Bon j'ai trouvé, cela se résume à :
mov       eax, DWORD PTR [esp]    
sar       eax, 1                  
neg       eax                    
add       eax, 1597463007        
mov       DWORD PTR [esp+4], eax
 
J'ai aussi trouvé avec les instruction SSE, encore plus rapide !

n°1344277
tbp
Posté le 11-04-2006 à 16:21:04  profilanswer
 

Citation :

J'ai aussi trouvé avec les instruction SSE, encore plus rapide !


 
Sauf que tu ne vas pas gagner grand chose si tu ne bascules pas en SoA, cad de { x,y,z,0 } à { x,x,x,x }/{ y,y,y,y }/{ z,z,z,z }; sinon tu gaspilles 1/4 des calculs.
 
Disons que tu persistes, il te faudra aussi user de rsqrt*s pour obtenir un quelconque gain. Vu le peu d'ulp que procurent ces instructions reciproques, il te faudra coller par dessus une iteration à la Newton-Raphson: x0 = rsqrtss(val), rsqrt = 0.5f*x0*(3.f-(val * x0²)).
Sauf qu'il y a une légere embrouille en 0 et au lieu de +/- inf tu te retrouveras avec un chouette NaN; la aussi ça se corrige sans branche aucune mais la latence continue de s'envoler.
 
Note: "float y; i  = * ( long * ) &y;" -> aliasing -> caca.

n°1385434
Palito
Posté le 11-06-2006 à 16:36:32  profilanswer
 

Salut, Je me joint a la reflexion ...
 
J'ai trouvédu code sse qui fait (bien ?) le travail.

Code :
  1. movaps xmm2, xmm0
  2.  mulps xmm0, xmm0
  3.  movaps xmm1, xmm0
  4.  shufps xmm0, xmm1, 0x4e
  5.  addps xmm0, xmm1
  6.  movaps xmm1, xmm0
  7.  shufps xmm1, xmm1, 0x11
  8.  addps xmm0, xmm1
  9.  rsqrtps xmm0, xmm0
  10.  mulps xmm2, xmm0


Le probleme c'est qu'il faut de je donne a manger a xmm0.
Comme 'st une fonction de la classe, j'ai codé ca:

Code :
  1. inline void float4::NormalizeSSE()
  2. {
  3. cVector *p=this;
  4. __asm {
  5.  movups xmm0, [p]
  6.  movaps xmm2, xmm0
  7.  mulps xmm0, xmm0
  8.  movaps xmm1, xmm0
  9.  shufps xmm0, xmm1, 0x4e
  10.  addps xmm0, xmm1
  11.  movaps xmm1, xmm0
  12.  shufps xmm1, xmm1, 0x11
  13.  addps xmm0, xmm1
  14.  rsqrtps xmm0, xmm0
  15.  mulps xmm2, xmm0
  16.  movups [p], xmm2
  17. }
  18. }


 
Cependant je me doute bien qe c'est pas optimal mais je ne sais pas comme mette this dans xmm0 ...
 
Et c'est super long aussi :(
 
Allez, Salut tous


Message édité par Palito le 12-06-2006 à 10:44:16
n°1479649
tbp
Posté le 21-11-2006 à 22:54:09  profilanswer
 

J'avais raté cette réponse.
 
Non, Palito, rsqrtps n'est pas à utiliser en lieu et place d'un 1/sqrt pour la bonne et simple raison que cela ne procure que ~12bits de précision. Comme indiqué plus haut, il faut 1 iteration de Newton-Raphson pour obtenir ~23bits sur la mantisse mais une implémentation naive ne recouvre pas le même domaine etc... au final, une fois tous les trous bouchés le gain est loin d'etre substantiel.

n°1479655
Palito
Posté le 21-11-2006 à 23:14:18  profilanswer
 

oui je me suis rendu compte que c'etait pas super precis comme calcul, mais j'ai depuis zappé le truc (laisssant une normalisation en bon vieux c++), il faudrait que je m'y remette


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  ASM

  [Défit !] Normaliser un vecteur

 

Sujets relatifs
Vecteur sans templatePetite question a propos d'un defit d'acces
Probleme de vecteurvecteur de string static
vecteur de poiteur sur fonctionPointeur sur un vecteur d'objets
[VB] Extraire un vecteur à partir d'une matrice sans boucleParcourir un vecteur
[ C++ ] Passer par adresse un vecteur à 2 dimensions + mallocvecteur de vecteur
Plus de sujets relatifs à : [Défit !] Normaliser un vecteur


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR