Librairie pour optimisation

Pour discuter de l'assembleur
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

erix14 a écrit :..A moins que tu n'es effectivement pas de SSE 8O
Tu as quoi comme microprocesseur ?
J'ai un AMD Athlon 1,4Ghz :lol:
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Cool, Pour une fois qu'un code marche mieux sur mon pentium 4 que sur un AMD :)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

Je viens de réaliser une nouvelle version de la librairie (à télécharger sur mon site RX14). Maintenant, on peut connaître le rapport de vitesse à partir d'un test de référence (voir les explications de Flype quelques messages avant). La méthode Display a maintenant un paramètre pour indiquer le test à prendre en référence. Et pour avoir le calcul le plus juste possible, il faut retrancher le nombre de cycles « à vide », cette valeur est passée par la fonction New_Test(NombreCyclesAVide). C'est à chacun de régler cette valeur, car elle est certainement différente pour chaque configuration. J'ai aussi ajouté l'envoi automatique des résultats dans le presse-papier pour faciliter la diffusion sur le forum, il y a en entête la configuration de l'ordi. Voici un autre petit exemple, l'optimisation de la fonction Mid(), codée par Trond.

Code : Tout sélectionner

Macro Mid2(String, StartPos, length)
  MidAscii(@String, StartPos, length)
EndMacro
Procedure.s MidAscii(String, StartPos, Longueur)
; Codé par Trond
  !MOV    Eax, [p.v_String]
  !ADD    Eax, [p.v_StartPos]
  !DEC    Eax
  !MOV    Edx, Eax
  !ADD    Eax, [p.v_Longueur]
  !MOV    cl, byte [Eax]
  !PUSH   Ecx
  !MOV    byte [Eax], 0
  !MOV    Ebx, Eax
  !PUSH   dword [_PB_StringBasePosition]
  !CALL  _SYS_CopyString@0
  !POP    Eax
  !ADD    Eax, [PB_StringBase]
  !POP    Ecx
  !MOV    byte [Ebx], cl
  ProcedureReturn
  ProcedureReturn ""
EndProcedure

TailleChaine = 30
VeryLongString.s = Space(TailleChaine)+"AAAABBBBCCCCDDDD"
TailleChaine + 5

*Test.ITest = New_Test(256)
For t=0 To #ITest
	*Test\Start(1)
	Mid(VeryLongString, TailleChaine, 4)
   *Test\Stop(1)
Next
*Test\SetTitle(1, "Mid() = "+Mid(VeryLongString, TailleChaine, 4))

For t=0 To #ITest
	*Test\Start(2)
	Mid2(VeryLongString, TailleChaine, 4)
   *Test\Stop(2)
Next
*Test\SetTitle(2, "Mid2() = "+Mid2(VeryLongString, TailleChaine, 4))

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.43 GHz, 768Mo de RAM
NVIDIA GeForce4 Ti 4800 SE - 128Mo
Microsoft Windows XP Professionnel Service Pack 2
-----------------------------------
Mid() = BBBB
480 cycles CPU (minimum)
530 cycles en moyenne
X 1.00
-----------------------------------
Mid2() = BBBB
240 cycles CPU (minimum)
302 cycles en moyenne
X 2.00
-----------------------------------
Test à vide
0 cycles CPU (minimum)
20 cycles en moyenne
X ???
-----------------------------------
Comme j'ai utilisé ma classe WMI et qu'elle est incluse dans la librairie, voici un exemple d'utilisation :

Code : Tout sélectionner

Global WMI.IWMI = New_WMI()
If WMI\ExecQuery("Select Name,CurrentClockSpeed from Win32_Processor") = #S_OK
   Debug WMI\GetS("Name") + "   ( " + StrF(WMI\GetL("CurrentClockSpeed")/1000, 2) + " GHz )"
   WMI\ReleaseQuery()
EndIf
If WMI\ExecQuery("SELECT Name,AdapterRAM FROM Win32_VideoController") = #S_OK
   Debug WMI\GetS("Name") + " - " + Str(WMI\GetL("AdapterRAM")/$100000)+"Mo"
   WMI\ReleaseQuery()
EndIf
If WMI\ExecQuery("Select Caption,CSDVersion from Win32_OperatingSystem") = #S_OK
   Debug WMI\GetS("Caption") + " " + WMI\GetS("CSDVersion")
   WMI\ReleaseQuery()
EndIf
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

Franchement c'est génial. Merci erix14. c'est bon je m'en sers à donf maintenant.

Par contre j'ai du mal avec la valeur d'init du constructeur (new).
j'ai pas tout compris en fait. si je mets 256 çà va, mais certaines valeurs font carrément planter le graphique (tout blanc ou rien) et puis je vois comment à sûr de la valeur à mettre.

Aussi, j'ai un gros plantage si j'essaye d'utiliser plusieurs fois la fonction Display() - je veux dire si je fais une 1ere serie de test, puis une 2eme dans le même source...

Stp, y a-t-il moyen d'avoir le source pour le WMI - çà m'intéresse bcp ?
par contre c'est pas compatible Win98 c'est çà ?
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

@Flype : Je viens de régler le problème du plantage, la nouvelle version est à télécharger toujours au même endroit. Par contre, je n'ai pas réussi à reproduire ton problème du graphique tout blanc. La valeur que tu dois mettre dans le constructeur c'est le nombre de cycles d'horloge à vide. Quand tu réalises des tests, fais-en un toujours à vide pour déterminer cette valeur.

Voici maintenant un autre exemple avec l'optimisation D-loop. il permet de calculer le nombre qu'une même lettre dans une phrase. (n'oubliez pas d'activer l'assembleur en ligne)

Code : Tout sélectionner

EnableExplicit
Global t.l, a.l

Procedure Count_Char(*Str.Character, LeChar.c)
	Protected NbChar.l
	While *Str\c
		If *Str\c = LeChar : NbChar + 1 : EndIf
		*Str + 1
	Wend
	ProcedureReturn NbChar
EndProcedure

Global Dim TableauChar.c(256)
TableauChar(0) = 2
Procedure Count_Char_2(*Str.Character, LeChar.c)
	Protected NbChar.l
	TableauChar(LeChar) = 1
	While *Str\c
		While TableauChar(*Str\c) = 0
			*Str + 1
		Wend
		If *Str\c = 0 : Break : EndIf
		NbChar + 1
		*Str + 1
	Wend
	TableauChar(LeChar) = 0
	ProcedureReturn NbChar
EndProcedure

Procedure Count_Char_3(*Str.Character, LeChar.c)
	Protected NbChar.l
	TableauChar(LeChar) = 1
	MOV Ecx,*Str
	!MOV Ebx,dword [a_TableauChar]
	!XOR Eax,Eax
	MOV ah,LeChar
	!Encore1:
		MOV al,byte [Ecx]
		INC Ecx
		XLATB
		CMP al,0
		JE Encore1
		CMP al,2
		JE FinCountChar
		NbChar + 1
		JMP Encore1
	!FinCountChar:
	TableauChar(LeChar) = 0
	ProcedureReturn NbChar
EndProcedure

Global MaString.s = "djfqgkjdhfgsjfgjkdnlngld fgsdjfhg dfjh gsdjfg df"

Global MonTest.ITest = New_Test(288)
For t=0 To #ITest
	MonTest\Start(1)
	a = Count_Char(@MaString, 'd')
	MonTest\Stop(1)
Next
MonTest\SetTitle(1, "Méthode traditionnelle : Count_Char() = "+Str(a))
;/
For t=0 To #ITest
	MonTest\Start(2)
	a = Count_Char_2(@MaString, 'd')
	MonTest\Stop(2)
Next
MonTest\SetTitle(2, "Méthode D-loop : Count_Char_2() = "+Str(a))
;/
For t=0 To #ITest
	MonTest\Start(3)
	a = Count_Char_3(@MaString, 'd')
	MonTest\Stop(3)
Next
MonTest\SetTitle(3, "Méthode D-loop ASM : Count_Char_3() = "+Str(a))
;/
For t=0 To #ITest
	MonTest\Start(4)
	MonTest\Stop(4)
Next
MonTest\SetTitle(4, "A vide")

MonTest\Display(1) 
Intel(R) Pentium(R) 4 CPU 2.40GHz
2.43 GHz, 768Mo de RAM
NVIDIA GeForce4 Ti 4800 SE - 128Mo
Microsoft Windows XP Professionnel Service Pack 2
-----------------------------------
Méthode traditionnelle : Count_Char() = 8
812 cycles CPU (minimum)
868 cycles en moyenne
X 1.00
-----------------------------------
Méthode D-loop : Count_Char_2() = 8
728 cycles CPU (minimum)
806 cycles en moyenne
X 1.12
-----------------------------------
Méthode D-loop ASM : Count_Char_3() = 8
528 cycles CPU (minimum)
584 cycles en moyenne
X 1.54
-----------------------------------
A vide
0 cycles CPU (minimum)
27 cycles en moyenne
X ???
-----------------------------------
Indiquez-moi vos résultats, je suis curieux de savoir ce que cela donne chez vous et de savoir si tout monde a compris le fonctionnement. :)
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

on va tester çà....

et ma question sur WMI ? :oops:
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

Regarde tes MP :wink:
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

Here is the results for flaith
Processor: AMD Athlon(TM)Processor, ~1.4GHz
Memory: 1024MB RAM
Operating System: Windows 2000 Professional (5.0, Build 2195) Service Pack 4
Card name: NVIDIA GeForce FX 5500 - 128Mo
Current Mode: 1280 x 1024 (32 bit) (85Hz)
-----------------------------------
Méthode traditionnelle : Count_Char() = 8
641 cycles CPU (minimum)
647 cycles en moyenne
X 1.00
-----------------------------------
Méthode D-loop : Count_Char_2() = 8
787 cycles CPU (minimum)
790 cycles en moyenne
X 0.81
-----------------------------------
Méthode D-loop ASM : Count_Char_3() = 8
316 cycles CPU (minimum)
334 cycles en moyenne
X 2.03
-----------------------------------
A vide
0 cycles CPU (minimum)
0 cycles en moyenne
X ???
-----------------------------------
:)
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

et les miens - merci au fait :wink:
AMD Athlon(tm) XP 2800+
2.08 GHz, 512Mo de RAM
NVIDIA GeForce 6800 GT - 256Mo
Microsoft Windows XP Professionnel Service Pack 2
-----------------------------------
Méthode traditionnelle : Count_Char() = 8
634 cycles CPU (minimum)
670 cycles en moyenne
X 1.00
-----------------------------------
Méthode D-loop : Count_Char_2() = 8
819 cycles CPU (minimum)
2159 cycles en moyenne
X 0.77
-----------------------------------
Méthode D-loop ASM : Count_Char_3() = 8
383 cycles CPU (minimum)
408 cycles en moyenne
X 1.66
-----------------------------------
A vide
0 cycles CPU (minimum)
0 cycles en moyenne
X ???
-----------------------------------
la commande ASM XLATB fait planter le debugger chez moi (invalid access memory) - un conflit avec le debugger (qui doit lui aussi faire des petits sauts mémoire et des bidouillages de piles ?

et le test à vide ne retourne pas de résultat - donc pas possible d'affiner le new().


intéressant ce D-loop en tout cas.
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

Bien, les résultats sont cohérents entre AMD et Intel. Il y a plus de cycle d'horloge chez Intel, car ils ont privilégié la fréquence... Si une autre personne pouvait faire un test avec un autre Pentium?

Les problèmes de débogueur avec l'assembleur ne sont pas nouveaux, moi qui fais pas mal d'assembleur, c'est la plaie!

Le principe du débogueur c’est :
1) récupérer les erreurs, comme la fonction OnErrorGosub(@Procedure())
2) faire un appel au débogueur entre chaque ligne PureBasic pour suivre l'état des registres, variables, etc. ou faire un arrêt... Le problème, c'est que l'état des registres n'est pas bien restitué au retour du débogueur. XLATB utilise le registre Ebx qui contient l'adresse du tableau, et avec le débogueur Ebx perd cette adresse.

PS : Vous devez mettre une valeur plus petite dans New_Test(), car vous avez gardé la mienne et comme je suis sous Intel Pentium elle est trop élevée pour vous (AMD) c'est pour cela que vous obtenez 0 en valeurs moyennes à vide.
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

J'en avais pas parlé, mais j'avais inclus l'affichage des pages default dans le graphique. Voici un code qui en provoque :

Code : Tout sélectionner

Global MonTest.ITest = New_Test(0)
For t=0 To #ITest
	MonTest\Start(1) 
	AllocateMemory(500)
	MonTest\Stop(1)
Next
MonTest\SetTitle(1, "AllocateMemory")
;/
For t=0 To #ITest
   MonTest\Start(2)
   MonTest\Stop(2)
Next
MonTest\SetTitle(2, "A vide")

MonTest\Display(2)
Répondre