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 ! :D

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 :oops:

Publié : dim. 22/mai/2005 12:09
par Backup
J'ai l'air ridicule face aux procédures en assembleur de Denis Embarassed
tu avait deja l'air ridicule avec ton images de pseudo !! :lol: :lol:
franchement ! un chien qui pilote un avion jaune :lol:




:lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol:
:lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol:

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 :lol:

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