Optimisation ASM

Souvent en programmation nous devons optimiser des morceaux de code. Par exemple, dans des programmes de statistique, de traitements de texte ou d'images qui demandent des temps de calcul importants. Et il est bon de connaitre le plus précisément possible le temps d"exécution de ces morceaux de codes pour évaluer les améliorations qu’on leurs a apportées. C'est pourquoi j'ai créé une librairie pour faciliter cette tâche. Pour l'utiliser, vous devez placer le fichier ITest dans le répertoire PureBasic\PureLibraries\UserLibraries et le fichier ITest.res dans le répertoire PureBasic\Residents. (Bouton de téléchargement en bas de cette page)

Description et fonctionnalités :

Ce n'est pas une librairie comme vous avez l'habitude d'en utiliser avec PureBasic, elle contient une classe. Il n'y a qu'une seule fonction New_Test(ValeurAVide) qui permet d'instancier des objets. Et à partir de ces objets, vous avez accès à leurs méthodes :

  • Start(Numero)
  • Stop(Numero)
  • Display(TestDeReference)
  • SetTitle(Numero, Titre)

Chaque objet peut réaliser des tests de vitesse sur 1 à 4 codes différents. La variable TestDeReference indique le test à prendre en référence pour calculer le coefficient de vitesse entre lui et les autres.

Exemple d'utilisation :

*Test.ITest = New_Test(0) ; Instanciation de l'objet *Test

*Test\SetTitle(1, "Test 1") ; Affectation d'un titre pour l'affichage du résultat.
For t=0 To #ITest ; La constante #ITest contient le nombre de tests à effectuer obligatoirement (512).
*Test\Start(1) ; Début du test pour le code 1.

; code à tester

*Test\Stop(1) ; Fin du test pour le code 1.
Next

*Test\SetTitle(2, "Test 2")
For t=0 To #ITest
*Test\Start(2)

; code à tester

*Test\Stop(2)
Next

*Test\SetTitle(3, "Test 3")
For t=0 To #ITest
*Test\Start(3)

; code à tester

*Test\Stop(3)
Next

*Test\Display(1) ; Affiche la fenêtre avec les résultats des tests.

Après avoir exécuté le code ci-dessus, vous obtiendrez une fenêtre comme l'image ci-dessous. Vous remarquerez qu'avec l'absence de code à tester les nombres de cycles d'horloge du CPU ne sont pas égaux à zéro. Eh oui, la fonction ASM qui permet de récupérer la valeur du compteur consomme beaucoup de cycles. C'est pourquoi, la fonction New_Test() prend comme argument une variable ValeurAVide, c'est à chacun de la déterminer en fonction du test et de la configuration de son ordinateur. Cette valeur sera retranchée automatiquement de tous les tests, ainsi le résultat sera au plus proche de la réalité, car les cycles consommés par la procédure de test seront décomptés. Il est aussi important de réaliser des tests sans avoir des logiciels qui s'exécutent en tâche de fond. J'ai aussi ajouté l'envoi automatique des résultats dans le presse-papier pour faciliter la diffusion sur les forums de PureBasic, il y a en entête la configuration de l'ordinateur (CPU, fréquence, RAM, carte graphique, système d'exploitation).
Les coefficients de vitesse sont calculés par rapport au nombre de cycles minimums obtenus, car ce sont ceux-là qui ont été les moins perturbés par le multitâche de Windows.

Exemple concret : optimisation de la fonction Len() (n'oubliez pas d'activer l'assembleur en ligne)

Procedure LenMot_RX14(*ptr.Character)
!XOR Eax,Eax

CMP *ptr\c, 0
!JZ LenMot_End

!LenMot_Encore:
INC Eax
!CMP byte [Ebp+1], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+2], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+3], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+4], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+5], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+6], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+7], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+8], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+9], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+10], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+11], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+12], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+13], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+14], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+15], 0
!JZ LenMot_End

INC Eax
!CMP byte [Ebp+16], 0
!JZ LenMot_End
!ADD Ebp,16
!JMP LenMot_Encore

!LenMot_End:
POP Ebp
RET 4
EndProcedure

Mot.s = "UnMot"
*Test.ITest = New_Test(272) ; J'ai obtenu 272 comme nombre de cycles à vide.

Resultat = 0
For t=0 To #ITest
*Test\Start(1)
Resultat = Len(Mot)
*Test\Stop(1)
Next
*Test\SetTitle(1, "Test avec la fonction PureBasic : Len() = "+Str(Resultat))

Resultat = 0
For t=0 To #ITest
*Test\Start(2)
Resultat = LenMot_RX14(@Mot)
*Test\Stop(2)
Next
*Test\SetTitle(2, "Test avec la fonction RX14 : LenMot_RX14() = "+Str(Resultat))

Resultat = 0
For t=0 To #ITest
*Test\Start(3)
Resultat = lstrlen_(Mot)
*Test\Stop(3)
Next
*Test\SetTitle(3, "Test avec la fonction API : lstrlen_() = "+Str(Resultat))

For t=0 To #ITest
*Test\Start(4)
; à vide
*Test\Stop(4)
Next
*Test\SetTitle(4, "Test à vide")

*Test\Display(1)

Ben voilà! On peut remarquer avec les résultats ci-dessous que la fonction la plus lente est celle de chez Microsoft. Que mettent-ils dedans ? Mystère... Quant à ma fonction, elle est très performante sur les mots courts, mais l'écart se réduit ensuite avec la fonction de PureBasic. Elle est donc à utiliser seulement pour le traitement des mots.

Retour Télécharger

© 2017 - www.rx14.info - 0.117 sec.