for ... next : rapidité !

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
jerexgrz
Messages : 279
Inscription : dim. 05/juin/2005 20:27

for ... next : rapidité !

Message par jerexgrz »

Je suis surpris, j'ai fait ce petit prog pour voir le temps que prenait un : for... next :

Code : Tout sélectionner

InitKeyboard()
InitSprite()

Structure uni
X.l
y.l
EndStructure

Global Dim unite.uni (999)

unite(1)\x = 304
unite(1)\y = 304

OpenScreen(640,480,16,"")

Procedure evenement1(nbx.l)
cx = 16 : cy = 16

For tt=1 To nbx

      If unite(quan)\x % 32 > 0 
         a = Round((unite(quan)\x+cx)/32,0)
     
         If a*32 <= unite(quan)\x+cx And (a*32)+32 >= unite(quan)\x+cx
            posx = a
      
         ElseIf (a-1)*32 <= unite(quan)\x+cx And (a-1)*32+32 >= unite(quan)\x+cx
            posx = a-1
      
         ElseIf (a+1)*32 <= unite(quan)\x+cx And (a+1)*32+32 >= unite(quan)\x+cx
            posx = a+1      
   
         EndIf

       ElseIf unite(quan)\x % 32 = 0
          posx = (unite(quan)\x) /32
   
       EndIf

       If unite(quan)\y % 32 > 0 
          b = Round((unite(quan)\y+cy)/32,0)
       
          If b*32 <= unite(quan)\y+cy And (b*32)+32 >= unite(quan)\y+cy
             posy = b
      
          ElseIf (b-1)*32 <= unite(quan)\y+cy And (b-1)*32+32 >= unite(quan)\y+cy
             posy = b-1
      
          ElseIf (b+1)*32 <= unite(quan)\y+cy And (b+1)*32+32 >= unite(quan)\y+cy
             posy = b+1
   
          EndIf

       ElseIf unite(quan)\y % 32 =0
          posy = (unite(quan)\y) /32
      
       EndIf

Next tt

EndProcedure

Procedure evenement2(nbx.l)
cx = 16 : cy = 16
coef.l
position.l
reX.l
reY.l

For tt=1 To nbx

    For u = 1 To 2  
      
          If u = 1 
             position = unite(quan)\x
             coef = cx         
      
          ElseIf u = 2 
             position = unite(quan)\y
             coef = cy              
     
          EndIf
            
            If position % 32 > 0 
               a = Round((position+coef)/32,0)
     
               If a*32 <= position+coef And (a*32)+32 >= position+coef
                  posx = a
      
               ElseIf (a-1)*32 <= position+coef And (a-1)*32+32 >= position+coef
                  posx = a-1
      
               ElseIf (a+1)*32 <= position+coef And (a+1)*32+32 >= position+coef
                  posx = a+1      
   
               EndIf

            ElseIf position % 32 = 0
              If u = 1 : rex = (position /32) : EndIf
              If u = 2 : rey = (position /32) : EndIf
   
            EndIf
       
    Next u  

Next tt

EndProcedure

Repeat
timer1.f = ElapsedMilliseconds()
        
  evenement1(1000000)

timer2.f =  ElapsedMilliseconds() - timer1

Debug timer2

ExamineKeyboard()
FlipBuffers()

Until KeyboardPushed(#PB_Key_Escape)
Avec le 1er evenement, je suis à environ 297 ms alors que le 2eme evenement est à 812ms voire 828ms !! 8O
C'est ahurissant, le temps d'execution que prend un for ... next (surtout pour faire 1 à 2 !!!)

J'ai peut-etre mal programmé, mais apparement c'est très lent un for... next (quelque soit le nombre).
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

mouais, faire un test de rapidité en mode Debugger n'est pas du tout objectif.
wolfjeremy
Messages : 1202
Inscription : sam. 31/déc./2005 23:52

Message par wolfjeremy »

Tout dépend de ton pc en même temps, moi je tourne plus dans les 400 avec le debugger. Sans le debugger je suis a ~105 pour le premier et ~90 pour les suivant.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

j'avais fait des test a une epoque qui montraient qu'un For-next
etait plus rapide qu'un While-wend , faudrai le refaire pour voir si cela a changer avec la V4.xx :D
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

Tu aurais dû utiliser ma librairie ITest pour faire tes tests, elle est très précise. Tu aurais vu que les résultats sont très proche, et en regardant le code, on voit bien qu'il y a plus de conditions "If" à exécuter dans ta deuxième procédure. C'est la faute à tes : If u = 1 / If u = 2

Code : Tout sélectionner

Structure uni
	X.l
	y.l
EndStructure

Global Dim unite.uni (999)

unite(1)\X = 304
unite(1)\y = 304

Procedure evenement1(nbx.l)
	cx = 16 : cy = 16
	For tt=1 To nbx
		If unite(quan)\X % 32 > 0
			a = Round((unite(quan)\X+cx)/32,0)
			If a*32 <= unite(quan)\X+cx And (a*32)+32 >= unite(quan)\X+cx
				posx = a
			ElseIf (a-1)*32 <= unite(quan)\X+cx And (a-1)*32+32 >= unite(quan)\X+cx
				posx = a-1
			ElseIf (a+1)*32 <= unite(quan)\X+cx And (a+1)*32+32 >= unite(quan)\X+cx
				posx = a+1     
			EndIf
		ElseIf unite(quan)\X % 32 = 0
			posx = (unite(quan)\X) /32
		EndIf
		If unite(quan)\y % 32 > 0
			b = Round((unite(quan)\y+cy)/32,0)
			If b*32 <= unite(quan)\y+cy And (b*32)+32 >= unite(quan)\y+cy
				posy = b
			ElseIf (b-1)*32 <= unite(quan)\y+cy And (b-1)*32+32 >= unite(quan)\y+cy
				posy = b-1
			ElseIf (b+1)*32 <= unite(quan)\y+cy And (b+1)*32+32 >= unite(quan)\y+cy
				posy = b+1
			EndIf
		ElseIf unite(quan)\y % 32 =0
			posy = (unite(quan)\y) /32
		EndIf
	Next tt
EndProcedure

Procedure evenement2(nbx.l)
	cx = 16 : cy = 16
	coef.l
	Position.l
	reX.l
	reY.l
	For tt=1 To nbx
		For u = 1 To 2 
			If u = 1
				Position = unite(quan)\X
				coef = cx         
			ElseIf u = 2
				Position = unite(quan)\y
				coef = cy             
			EndIf
			If Position % 32 > 0
				a = Round((Position+coef)/32,0)
				If a*32 <= Position+coef And (a*32)+32 >= Position+coef
					posx = a
				ElseIf (a-1)*32 <= Position+coef And (a-1)*32+32 >= Position+coef
					posx = a-1
				ElseIf (a+1)*32 <= Position+coef And (a+1)*32+32 >= Position+coef
					posx = a+1     
				EndIf
			ElseIf Position % 32 = 0
				If u = 1 : reX = (Position /32) : EndIf
				If u = 2 : reY = (Position /32) : EndIf
			EndIf
		Next u 
	Next tt
EndProcedure

*Test.ITest = New_Test(0)
For t=0 To #ITest
	*Test\Start(1)
	evenement1(10000)
	*Test\Stop(1)
Next
*Test\SetTitle(1, "evenement1")

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

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

*Test\Display(2) 
Intel(R) Pentium(R) 4 CPU 2.40GHz
2.52 GHz, 768Mo de RAM
NVIDIA GeForce4 Ti 4800 SE - 128Mo
Microsoft Windows XP Professionnel Service Pack 2
-----------------------------------
evenement1
1110452 cycles CPU (minimum)
1116171 cycles en moyenne
X 1.02
-----------------------------------
evenement2
1130536 cycles CPU (minimum)
1139030 cycles en moyenne
X 1.00
-----------------------------------
Test à vide
296 cycles CPU (minimum)
313 cycles en moyenne
X 3819.38
-----------------------------------
jerexgrz
Messages : 279
Inscription : dim. 05/juin/2005 20:27

Message par jerexgrz »

Je viens de télécharger et d'installer ta lib test, c du bon travail (tres propre, tres professionnel, precis aussi !! :o ).
Concernant l'evenement 1 :
je suis à 7 320 085 mini, -722388 moy et le X 2.92

pour l'evenement 2:
je suis à 21 340 976 mini, - 3513423 moy et le X 1 8O 8O 8O

a vide:
279 mini, 299 moy et X 76490.95

Il y a donc une enorme difference entre le code pas trop optimisé que j'ai fait avec le calcul des X en 1er et le calcul des Y en 2nd. Et l'utilisation, d'une boucle pour eviter de réécrire 2X la meme chose !!!
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

Tu sais, le résultat du test est copié automatiquement dans le presse-papier, c'est pour éviter de les entrer à la main sur le forum. :wink:
Voici mes résultats avec le Debogueur :
Intel(R) Pentium(R) 4 CPU 2.40GHz
2.52 GHz, 768Mo de RAM
NVIDIA GeForce4 Ti 4800 SE - 128Mo
Microsoft Windows XP Professionnel Service Pack 2
-----------------------------------
evenement1
13656360 cycles CPU (minimum)
-2937086 cycles en moyenne
X 2.99
-----------------------------------
evenement2
40884432 cycles CPU (minimum)
-374451 cycles en moyenne
X 1.00
-----------------------------------
Test à vide
464 cycles CPU (minimum)
544 cycles en moyenne
X 88113.00
-----------------------------------
On ne fait jamais de test de vitesse avec le débogueur sur ON, les résultats ne veulent rien dire!
jerexgrz
Messages : 279
Inscription : dim. 05/juin/2005 20:27

Message par jerexgrz »

oui, il y a une grosse difference quand le debuggeur est activé !
j'avais pris le bloc note traditionnel au lieu d'utiliser wordpad ...
AMD Athlon(tm) 64 X2 Dual Core Processor 5200+
2.61 GHz, 2048Mo de RAM (par contre moi c'est 4go et non 2go !!)
NVIDIA GeForce 7950 GT - 512Mo
Microsoft Windows XP Professionnel Service Pack 2
-----------------------------------
evenement1
1160172 cycles CPU (minimum)
1177879 cycles en moyenne
X 1.10
-----------------------------------
evenement2
1280284 cycles CPU (minimum)
1298296 cycles en moyenne
X 1.00
-----------------------------------
Test à vide
95 cycles CPU (minimum)
117 cycles en moyenne
X 13476.67
-----------------------------------
Mais, l'evenement 1 est toujours + rapide que l'evenement 2 : grosso modo c'est de l'ordre de 10% (quand meme une difference avec avant de l'ordre de 290%).
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

Oui, une différence tout à fait normale en raison des conditions supplémentaires que l'événement 2 doit exécuter. Pour conclure, la boucle For en PureBasic est tout ce qu'il y a de plus normal :
Code PureBasic :

Code : Tout sélectionner

For t=0 To 9
	; Code
Next
Code ASM :

Code : Tout sélectionner

; For t=0 To 9
	MOV	 dword [v_t],0
_For1:
	MOV	 eax,9
	CMP	 eax,dword [v_t]
	JL	 _Next2
; Code
; Next
_NextContinue2:
	INC	 dword [v_t]
	JMP	 _For1
_Next2:
jerexgrz
Messages : 279
Inscription : dim. 05/juin/2005 20:27

Message par jerexgrz »

Procedure evenement2(nbx.l)
cx = 16 : cy = 16
Position.l
reX.l
reY.l
posu.l

For tt=1 To nbx

For u = 1 To 2
If u = 1
Position = unite(quan)\X
posu = unite(quan)\x + cx

ElseIf u = 2
Position = unite(quan)\y
posu = unite(quan)\y + cy

EndIf

If Position % 32 > 0
a = Round((Posu)/32,0)
b = a*32

If b <= Posu And b+32 >= Posu
posx = a
ElseIf b-32 <= Posu And b >= Posu
posx = a-1
ElseIf b+32 <= Posu And b+64 >= Posu
posx = a+1
EndIf
ElseIf Position % 32 = 0
If u = 1 : reX = (Position /32) : EndIf
If u = 2 : reY = (Position /32) : EndIf

EndIf
Next u

Next tt
EndProcedure
C'est hyper surprenant, j'ai amélioré la boucle pour qu'elle prenne - de temps, et resultat c'est le contraire ! Aussi, une multiplication est vraiment tres gourmande en cycle : mieux vaut faire : a*32+32 que (a+1)*32 !! 8O
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

Comme tu travailles avec des nombres entiers, voilà comment on optimise avec des entiers :

Code : Tout sélectionner

Structure uni
   x.l
   y.l
EndStructure

Global Dim unite.uni (999)

unite(1)\x = 304
unite(1)\y = 304

Procedure evenement2(nbx.l)
   cx = 16 : cy = 16
   coef.l
   Position.l
   reX.l
   reY.l
   For tt=1 To nbx
      For u = 1 To 2
         If u = 1
            Position = unite(quan)\x
            coef = cx         
         ElseIf u = 2
            Position = unite(quan)\y
            coef = cy             
         EndIf
         If Position % 32 > 0
            a = Round((Position+coef)/32,0)
            If a*32 <= Position+coef And (a*32)+32 >= Position+coef
               posx = a
            ElseIf (a-1)*32 <= Position+coef And (a-1)*32+32 >= Position+coef
               posx = a-1
            ElseIf (a+1)*32 <= Position+coef And (a+1)*32+32 >= Position+coef
               posx = a+1     
            EndIf
         ElseIf Position % 32 = 0
            If u = 1 : reX = (Position /32) : EndIf
            If u = 2 : reY = (Position /32) : EndIf
         EndIf
      Next u
   Next tt
EndProcedure
Procedure evenement2_RX(nbx.l)
	cx = 16 : cy = 16
	Position.l
	reX.l
	reY.l
	posu.l
	
	For tt=1 To nbx
		
		For u = 1 To 2
			If u = 1
				Position = unite(quan)\x
				posu = unite(quan)\x + cx
				
			ElseIf u = 2
				Position = unite(quan)\y
				posu = unite(quan)\y + cy
				
			EndIf
			
			If Position & $1F ; Position % 32 > 0
				a = posu >> 5  ;Round((posu)/32,0)
				b = a << 5 ;*32
				
				If b <= posu And b+32 >= posu
					posx = a
				ElseIf b-32 <= posu And b >= posu
					posx = a-1
				ElseIf b+32 <= posu And b+64 >= posu
					posx = a+1
				EndIf
			ElseIf Position & $1F = 0 ;Position % 32 = 0
				If u = 1 : reX = Position >> 5 : EndIf;(Position /32) : EndIf
				If u = 2 : reY = Position >> 5 : EndIf;(Position /32) : EndIf
				
			EndIf
		Next u
		
	Next tt
EndProcedure 

*Test.ITest = New_Test(0)

For t=0 To #ITest
   *Test\Start(1)
   evenement2(10000)
   *Test\Stop(1)
Next
*Test\SetTitle(1, "evenement2")

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

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

*Test\Display(1)
Intel(R) Pentium(R) 4 CPU 2.40GHz
2.52 GHz, 768Mo de RAM
NVIDIA GeForce4 Ti 4800 SE - 128Mo
Microsoft Windows XP Professionnel Service Pack 2
-----------------------------------
evenement2
1130488 cycles CPU (minimum)
1142284 cycles en moyenne
X 1.00
-----------------------------------
evenement2_RX
460680 cycles CPU (minimum)
466956 cycles en moyenne
X 2.45
-----------------------------------
Test à vide
284 cycles CPU (minimum)
327 cycles en moyenne
X 3980.59
-----------------------------------
jerexgrz
Messages : 279
Inscription : dim. 05/juin/2005 20:27

Message par jerexgrz »

:lol: Merci, Merci, pour la version optimisé ! En faite, je travaille dans un monde 3D iso, mais il faut un maximum de precision !
Ce sont de nouvelles fonctions que je viens d'apprendre ! Par contre, c comme meme bizarre, que lorsque les calculs sont faits, ca prends plus de temps ???
Répondre