Page 2 sur 2
Publié : dim. 22/mai/2005 9:25
par erix14
Droopy a écrit :Cette procédure sert à mesurer le temps que met un bout de code à s'exécuter.
Une fois le code optimisé, on n'utilise plus cette procédure !
En fait pour qui n'est pas d'ambiguïté, tu devrais faire deux procédures :
- StartMeasureInterval()
- StopMeasureInterval()
Publié : dim. 22/mai/2005 9:25
par Droopy
Le code du Soldat est le même que Fred !

Publié : dim. 22/mai/2005 9:27
par Droopy
T'as raison Erix je vais faire 2 procédures
- StartMeasureInterval()
- StopMeasureInterval()
très bonne idée !
Publié : dim. 22/mai/2005 9:59
par Dr. Dri
Faut arrêter d'abuser de GetTickCount ^^
y'a ElapsedMilliseconds() Maintenant
Dri
Publié : dim. 22/mai/2005 10:05
par Anonyme2
djes a écrit :En regardant le code assembleur avec PureASM, je suis quand même surpris de la taille de la procédure (et de ses initialisations). L'opération en elle-même ne prend au pire que trois instructions, par contre le reste de la procédure (initialisation et restauration de la pile), plus d'une vingtaine, dont une boucle et deux sauts! Autant dire que parler d'optimisation dans ces conditions me laisse un peu... perplexe!
Je me demande si on ne pourrait pas inventer une nouvelle instruction de procedure dont on créerait entièrement le code, sans que pure ne le génére. On pourrait demander à Fred... On pourrait l'appeler ProcedureASM(params) par exemple.
C'est un des gros avantage d'écrire une librairie en asm (voire en C mais là je n'y connais que dalle) car PB ne permet pas de le faire directement.
Tu as remarqué, PB alloue de la place qur la pile pour toutes les variables et tous les paramètres; ensuite PB recopie l'ensemble des paramètres sur la pile puis initialise les variables locales à 0, le tout en ayant sauvegardé tous les registres sauf eax et edx. Ce n'est pas une critique, il faut bien avoir des règles.
Le code PB
Code : Tout sélectionner
; Procedure.b SignedBinaryToUnsigned(Byte.b)
JMP _EndProcedure0
_Procedure0:
PUSH ebx
PUSH ecx
PUSH ebp
PUSH esi
PUSH edi
MOV esi,esp
SUB esp,4
MOV eax,esp
MOV edx,eax
ADD edx,4
_ClearLoop0:
MOV dword [eax],0
ADD eax,4
CMP eax,edx
JNE _ClearLoop0
MOV eax, dword [esi+24]
MOV byte [esp+0],al
; ProcedureReturn Byte & $FF
MOVSX ebx,byte [esp]
AND ebx,255
MOV eax,ebx
JMP _EndProcedure1
; EndProcedure
XOR eax,eax
_EndProcedure1:
ADD esp,4
POP edi
POP esi
POP ebp
POP ecx
POP ebx
RET 4
_EndProcedure0:
et l'équivalent avec PureASMTools (intégré à PureASM) pour la génération du squelette asm
Code : Tout sélectionner
format MS COFF
public PB_SignedBinaryToUnsigned_ASM
; -------------------------------------------;
; Paramètres d'entrée ;
; -------------------------------------------;
; Byte.b
Byte equ esp+4
; -------------------------------------------;
; Section code ;
; -------------------------------------------;
section '.text' code readable executable
PB_SignedBinaryToUnsigned_ASM:
; **************************************************
; Mettez votre code asm perso après cette ligne
MOVSX eax,byte [Byte]
AND eax,255
; fin de la zone de votre code asm perso
; **************************************************
_Retour:
RET 4
J'espère que PureASMTools donnera envie à certains de faire des libs en asm (Bon, tout n'est pas parfait mais je travaille un peu dessus tous les jours, surtout la doc en ce moment)
Publié : dim. 22/mai/2005 10:23
par djes
Denis> Effectivement, là, ça devient intéressant! J'avoue que je n'avais pas trop regardé tout ça... La création de libs ne m'intéresse pas vraiment, mais apparemment cet outil peut être très utile!!! Personnellement, je vais y jeter un oeil attentif.
Droopy> Pourquoi t'essayes pas QueryPerformanceCounter_(@time) ?

Publié : dim. 22/mai/2005 11:05
par Droopy
c'est effectivement plus simple comme ça :
Code : Tout sélectionner
; Return the the number of milliseconds between two call
; Cool to Optimize your code
; Idea from Erix14
Global MeasureIntervalTime.l
ProcedureDLL MeasureIntervalStart()
MeasureIntervalTime=ElapsedMilliseconds()
EndProcedure
ProcedureDLL MeasureIntervalStop()
ProcedureReturn ElapsedMilliseconds()-MeasureIntervalTime
EndProcedure
MeasureIntervalStart()
Delay(250)
Debug MeasureIntervalStop()
J'ai utilisé ElapsedMilliseconds() : Merci Dr Dri
J'ai l'air ridicule face aux procédures en assembleur de Denis

Publié : dim. 22/mai/2005 12:09
par Backup
Publié : dim. 22/mai/2005 12:20
par djes
J'ai fait un petit test vite fait avec les timers haute résolution.
Code : Tout sélectionner
;*** Normalement, les fonctions renvoient des entiers de 64 bits. On réserve donc
; deux entiers de 32 bits pour stocker cette valeur, même si dans cet exemple,
; on ne s'en servira pas
Dim freq.l(2)
Dim time.l(2)
Procedure MeasureInterval()
If time(1)
temp=time(0)
QueryPerformanceCounter_(@time(0))
ProcedureReturn time(0)-temp
Else
QueryPerformanceCounter_(@time(0))
EndIf
EndProcedure
;*** Y-a-t-il un compteur haute résolution?
If QueryPerformanceFrequency_(@freq(0))
;*** Renvoie la fréquence de notre compteur (seuls les 32 premiers bits)
Debug freq(0)
;*** Effectue une dizaine de tests
MeasureInterval()
For i=0 To 9
Delay(1000)
Debug MeasureInterval()
Next
EndIf
End
Publié : dim. 22/mai/2005 12:20
par Anonyme2
Dobro a écrit :franchemant ! un chien qui pilote un avion jaune
Ca me rapelle un dessin animé que je ragardais il y a pas mal d'années, je ne me souviens plus du nom mais il me semble que ça repasse sur le cable
Publié : dim. 22/mai/2005 12:57
par Droopy
Code modifié avec le timer haute résolution
Code : Tout sélectionner
; Idea from Erix14
; Return the time elapsed between Start & Stop in second
; 0.001 = 1 ms
; 0.000001=1 µs
Global MeasureIntervalTime.l
ProcedureDLL MeasureIntervalStart()
QueryPerformanceCounter_(@MeasureIntervalTime)
EndProcedure
ProcedureDLL.f MeasureIntervalStop()
QueryPerformanceCounter_(@Temp)
Difference=Temp-MeasureIntervalTime
QueryPerformanceFrequency_(@HiResTimerFrequency)
Periode.f=1/HiResTimerFrequency
DureeTotale.f=Difference*Periode
ProcedureReturn DureeTotale
EndProcedure
;/ Test
MeasureIntervalStart()
Delay(150)
Debug MeasureIntervalStop()
merci Djes
Publié : dim. 22/mai/2005 14:27
par djes
Euh oui mais à mon avis il faut garder les deux : dans la doc de Microsoft, il est dit que le timer haute résolution n'est pas implémenté sur toutes les machines.
En outre, n'oublie pas que la valeur renvoyée est sur 64bits, attention donc car les fonctions écrasent certainement des données quelque part.
Publié : dim. 22/mai/2005 15:08
par Droopy
OK j'ai ajouté un test pour savoir si le matériel le supporte
Je conseillerais cette procédure pour les test < ms
et l'ancienne pour celles > ms
Code : Tout sélectionner
; Idea from Erix14 / Djes
; Return the time elapsed between Start & Stop in second
; 0.001 = 1 ms
; 0.000001=1 µs
; Caution ! : If the installed hardware supports a high-resolution performance counter
; MeasureIntervalHiResStart return 1 / 0 if no hardware support
Global MeasureIntervalTime.l
ProcedureDLL MeasureIntervalHiResStart()
QueryPerformanceFrequency_(@retour)
If retour <>0 : retour = 1 : EndIf
QueryPerformanceCounter_(@MeasureIntervalTime)
ProcedureReturn retour
EndProcedure
ProcedureDLL.f MeasureIntervalHiResStop()
QueryPerformanceCounter_(@Temp)
Difference=Temp-MeasureIntervalTime
QueryPerformanceFrequency_(@HiResTimerFrequency)
Periode.f=1/HiResTimerFrequency
DureeTotale.f=Difference*Periode
ProcedureReturn DureeTotale
EndProcedure
;/ Test
If MeasureIntervalHiResStart()
Delay(1)
Debug MeasureIntervalHiResStop()
EndIf