IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

x86 32-bits / 64-bits Assembleur Discussion :

[3DNow !] Précision


Sujet :

x86 32-bits / 64-bits Assembleur

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut [3DNow !] Précision
    Salut !!

    J'optimise actuellement mon programme graphique (un "jeu" ou plutot test coding) en réécrivant toutes les fonctions mathématiques usuelles avec les optimisations possibles du processeur.

    Ainsi, j'en suis a la 3DNow !. Je viens de terminer ma fonction exponentielle. Cependant, je n'obtiens pas une excellente précision
    Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    float exp(int Power)
      {
       float Res;
     
       _asm{
    	femms
     
    	//initialisation des variables
    	mov Res,0
    	movq mm0, [fExp]
    	mov eax,1 
     
    	//debut de la boucle
    calcexp:
    	pfmul mm0,[fExp]
     
    	inc eax
        cmp eax, Power
    jne calcexp
     
    	movq [Res], mm0
    	femms
       }
     
       return Res;
      }
    #define Exp1 2.71828182845f // e^1
    ....
    float fExp = Exp1;
    => c'est un code C++ dans lequel est inséré de l'asm.

    Sauriez vous donc pourquoi la précision laisse quelque peu a désirer (J'en ai une de l'ordre de 10^-4 avec la derniere décimale arrondi) ?

    merci[/quote]

  2. #2
    Membre confirmé
    Inscrit en
    Juin 2002
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 24
    Par défaut
    salut,

    je vais peut-être dire des bêtises mais il me semble que le 3DNow ne fait des calculs que sur des singles (des flottants sur 32 bits), d'où cette mauvaise précision.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    Dans ce cas il me suffirait de remplacer mes "movq" par des "movd" ?
    Je débute dans l'asm...

    merci.

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2003
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 247
    Par défaut
    Pour commencer, je mettrais plutot ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #define Exp1 2.71828182845
    .... 
    double fExp = Exp1;

    La précisions d'un calcul vaut la précision du nombre à la plus faible précision.
    Donc travail dès le départ avec le max de précision. Ensuite un double peut stocké jusqu'à 15 chiffres significatif. Avec ton approximation, tu ne les utilises pas tous.


    J'optimise actuellement mon programme graphique
    Lol, pas besoins de se trouver des excuses bidon pour s'amuser ;-).

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    Merci.

    Mais c'est pas bidon le coup du prog graphique
    En fait, c'est aussi un peu pour m'amuser, puisque ca ne sera qu'eventuellement implementé

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2003
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 247
    Par défaut
    Concrètement, les routines mathématiques sont déjà très bien implantée. Je ne pense pas que leur réécriture améliore les performance. Voir plutôt le contraire.

    Surtout dans ton cas. Tu n'utilise même pas d'exponentiation rapide. Ta routine sera bien plus lente que celle qui existent déjà.

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    Ah bon ?

    Je réécrivais la fct exponentielle parce que je ne savait pas qu'il existait une instruction 3dNow faite pour ca !!!

    La quelle est-ce ?

    merci.

    ps : quand je dis réécriture, c'est par rapport aux fonctions c++, qui sont, c''est connu, lentes

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2003
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 247
    Par défaut
    Citation Envoyé par delire8
    ps : quand je dis réécriture, c'est par rapport aux fonctions c++, qui sont, c''est connu, lentes
    Tu me parait bien sûr de toi...
    En tout cas, si tu utilise DX ou OGL, soit sûr que le fonctions sont optimiser à fond pour chaque processeur.

    Sinon, je te renvoie à l'instruction F2XM1. C'est une instruction du coprocesseur qui calcule 2^x - 1. Ce n'est pas une instruction 3dNow!. Je croit que avec on peut calculer n'importe quel a^x.

    Si tel n'est pas le cas, je t'invite à charcher sur Google Exponentiation rapide qui permet de limiter le nombre de multiplication et donc d'une part la rapidité at d'autre par la précision. Ceci car à chaque multiplication, la précision relative diminue.

    Et cherche aussi du côté du jeu d'instruction de 3dNow!, il y doit surement y avoir une instruction qui calcule directement une exponentielle.

  9. #9
    Membre confirmé
    Inscrit en
    Juin 2002
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 24
    Par défaut
    Citation Envoyé par Blawk
    Pour commencer, je mettrais plutot ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #define Exp1 2.71828182845
    .... 
    double fExp = Exp1;
    ça serait bien la pire des choses à faire dans ce cas là.

    faut déjà comprendre comment fonctionne le 3D Now! :

    le 3D Now! reprend les 8 registres 64 bits MMX et les "subdivise" en 2 registres de flottants simple précision :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
               1             2
        +-------------+-------------+
    MM0 |             |             |
        |-------------|-------------|
    MM1 |             |             |
        |-------------|-------------|
    MM2 |             |             |
        |-------------|-------------|
    MM3 |             |             |
        |-------------|-------------|
    MM4 |             |             |
        |-------------|-------------|
    MM5 |             |             |
        |-------------|-------------|
    MM6 |             |             |
        |-------------|-------------|
    MM7 |             |             |
        +-------------+-------------+
         <- 32 bits -> <- 32 bits ->
    quand on fait une opération sur un registre (par ex multiplication sur mm0), l'opération est effectué sur les deux membres du registres. l'intérêt de ça est de pouvoir faire la même opération sur 2 nombres en même temps (d'où Single Instruction Multiple Data).

    donc premièrement, du fait du codage des réels, on ne peut pas utiliser des doubles en 3D Now! que des singles (d'où la précision).
    ensuite, l'utilisation du 3D Now! et des SIMDs en général ne peut pas se faire partout. elle n'est utile que lorsqu'on doit effectuer les mêmes opérations sur plusieurs données. si c'est pour une fonction exponentielle, le 3D Now! est inutile.

    comme te l'indique Blawk, dirige toi plutôt vers le fpu qui te donnera la précision voulue.

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    merci encore.
    Je tiens a préciser que l'asm est pour moi assez nouveau.... Alors 3DNow !, etc....

    Sinon, Blawk, je voulais juste dire que c'est possible d'optimiser les fonctions du c++.... il y a effectivement une nuance, que j'ai négligé.


    merci encore a vosu tous

  11. #11
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2003
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 247
    Par défaut
    Excusez moi pour mon erreur. En fait, je pensais que 3dNow! fonctionnait avec 64 bits. En fait je ne l'ai jamais utilisé, juste MMX (qui lui aussi travaille en 32bits) ;-).


    Quant aux fonctions déjà écrites, bien sur qu'il est possible de les optimisée, mais en étant sûr de ce que l'on fait ;-).

  12. #12
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Par défaut
    Nan, c'est pas vrai, c'est pas optimisé ! Le plus rapide est d'utiliser des virgules fixes ! (seulement, vlà comment ca complique les choses)
    Ta méhode, est entre l'exposant à virgule floattante et celle à nombre entier. Attention, c'est une élévation à la puissance, pas une exponentielle !
    Si tu dois ne calculer qu'un seul exposant, utilises peut être le fpu (il faudrait tester). Enfin, tu fais beaucoup trop de calculs. Imagine tu veux passer à l'exposant 4, il vaut mieux calculer y=x*x, et z=y*y, ce qui demande 2 multiplications au lieu de 3 z=x*x*x*x, mais on peut faire encore mieux ! (je l'écris en C, je connais pas 3Dnow, mais y'a plein et petites erreurs dans ton prog, tu charges un quadword alors que les float ne font que 4 octets, tu as des instructions inutiles.)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    float Puissance(float x, unsigned int Puissance) 
    { 
      float Resultat = 1;
     
      do
      {
        if (Puissance & 1)
          Resultat *= x;
     
        x *= x;
        Puissance >>= 1;
      }
      while(Puissance);
     
      return Resultat; 
    }
    c'est déjà certainement plus rapide, sans utiliser d'asm ! Par contre, là l'asm va servir. Les compilateurs gèrent mal les virgules flottantes et on peut modifier la structure pour avoir de meilleure perf en asm, mais ca reste assez peu face au temps que demandent les multiplication par vigule flottante. Cette opération demande au max log_2(Puissance) multiplications, là ou la tienne demandait Puissance mutliplication. Une multiplciation flottante demande 20 à 30 cycles, la puissance en demande 400 à 500 au fpu, donc, a moins que la puissance ne soit 0xffffffffff ce sera toujours plus rapide.

    Calcul de l'erreur, attention, l'erreur n'est pas égale à la plus grosse erreur ! Notons A et B deux approximations :

    A = a + EpsilonA
    B = b + EpsilonB

    a et b étant les valeurs exactes, et EpsilonA l'erreur au signe près. Alors l'erreur comise après calcul de A * B est donnée par :

    A * B = a*b + [a*EpsilonB + b*EpsilonA + EpsilonA*EpsilonB]

    L'erreur est entre crochets ! (si je ne me trompe pas)
    Les nombres a virgule floattante ont 6 chiffres significatifs, donc, retiré l'erreur c'est normal que tu voies apparaitres des décimales incorrectes.

Discussions similaires

  1. Précision sur Oracle 9iAS r2
    Par Patmane dans le forum Oracle
    Réponses: 9
    Dernier message: 18/03/2007, 04h41
  2. fin de contrat duree determinee, précisions Help !!!
    Par Godulle dans le forum Contrat
    Réponses: 6
    Dernier message: 08/07/2004, 13h50
  3. [EJB]Précision de la datasource (Mysql)
    Par cameleon2002 dans le forum JBuilder
    Réponses: 2
    Dernier message: 11/09/2003, 17h55
  4. Réponses: 8
    Dernier message: 13/01/2003, 17h45
  5. Timer de précision
    Par guigui dans le forum MFC
    Réponses: 1
    Dernier message: 04/12/2002, 15h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo