FPU et puissance d'un nombre

cs_AlexMAN Messages postés 1536 Date d'inscription samedi 21 décembre 2002 Statut Membre Dernière intervention 24 mai 2009 - 19 mars 2005 à 09:07
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019 - 19 mars 2005 à 12:59
Bonjour,

Voila, j'ai 'codé' 2 fonctions permettant de calculer un nombre n a une puissance exp (la fonction est bourrin, cad pas de decoupages de la fonction selon que le nombre soit pair ou impair..), une en ASM avec les instructions du CPU, et une autre avec les instructions de la FPU (celle dont j'ai vraiment besoin, pour certaines raisons..).
Et j'ai donc décidé de comparer la vitesse des 2fonctions, et la reponse est sans appel : Cpu plus rapide que Fpu (Avec mes fonctions a moi !).
Donc j'aimerais savoir comment 'optimiser' la fonction FPU ci dessous :


__declspec(
naked)
int
__stdcall PuissFPU(
int n,
int exp)


{



__asm {


mov eax, [esp + 8]
//eax == exp


fild [esp + 4]
//empile n, ST(1) == n


fild [esp + 4]
//empile n, ST(0) == n, Contiendra le resultat


sub eax, 1


Deb:


fmul ST, ST(1)


sub eax, 1


test eax, eax


jne Deb


sub esp, 4


fist dword ptr[esp]


mov eax, [esp]


add esp, 4


ret 8


}


}


__declspec(
naked)
int
__stdcall Puiss(
int n,
int exp)


{



__asm {


mov ecx, [esp + 4]


mov edx, [esp + 8]


mov eax, ecx


sub edx, 1


Deb:


imul eax, ecx


sub edx, 1


test edx, edx


jne Deb


ret 8


}


}

Voila, merci d'avance a tous ;)
Amicalement, Alex

+2(p - n)

4 réponses

BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
19 mars 2005 à 12:04
Dans tous les cas il est normal que par FPU soit plus lent qu'avec les 3 registres généraux.
Tu peux gagner un peu en passant les params en registres.
Inutile de déplacer ESP en sortie, c'est trop couteux, surtout si tu indexes sur lui l'instruction suivante.

__declspec(naked) int __fastcall PuissFPU(int n, DWORD exp){ // ECX n, EDX exp
__asm {
mov [esp-4], ecx ; n
dec edx
jle short puissExit
fild dword ptr[esp-4]
fld st(0)
boucle:
fmul st(0), st(1)
dec edx
jne short boucle
fistp dword ptr[esp-4]
fstp st(0)
puissExit:
mov eax, [esp-4]
ret 0
}
}

Je n'ai pas mesuré, je te laisse faire, pas le temps.
Si exp <= 1, je retourne n, c'est pas très orthodoxe, tu adapteras selon besoin.

ciao...
BruNews, MVP VC++
0
cs_AlexMAN Messages postés 1536 Date d'inscription samedi 21 décembre 2002 Statut Membre Dernière intervention 24 mai 2009 1
19 mars 2005 à 12:44
En fait, je ne veux pas passer toucher aux registres generaux, c'est ca la raison qui m'a poussé a utiliser le FPU...Parce que dans ma fonction appellante, je dois conserver la valeur presente dans ces registres, donc pas de __fastcall...Donc ca me rassure, merci ;)
Puis ce que je te tiens, je veux decomposer un nombre en tous ses chiffres et partie de ses chiffres de taille egale :

1634 => Soit 1, 6, 3, 4 soit 16, 34
100 => 1, 0, 0

J'utilise pour cela le reste de la division entiere par 10^x mais bien sur, c'est une division et c'est lent, donc je me demandais s'il n'existait pas une maniere de coder ca en deplacant des bits ou un truc plus rapide.

Merci Brunews
A bientot

+2(p - n)
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
19 mars 2005 à 12:55
mais non, une division par une constante, 10 ici, se fait par multiplication, va voir bnultoa dans mes sources.

ciao...
BruNews, MVP VC++
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
19 mars 2005 à 12:59
Je viens de t'envoyer ReciDiv.zip qui te donnera le code asm suivant le diviseur indiqué.

ciao...
BruNews, MVP VC++
0
Rejoignez-nous