lib memory
Voilà où ça en est :
Toutes les tailles et longueurs sont en octets (bytes)
MoveMem(*source,*dest,taille):
comme rtlmovememory_, mais un peu plus rapide.
CompareMem(*mem1,*mem2,taille):
comme comparememory de PB, mais 4 fois plus rapide.
CompareMemL(*mem1,*mem2,taille)
compare, selon l'ordre lexicographique, par zones de 32bits (long) les zones mémoires
commençant aux adresses *mem1 et *mem2, et de longueur taille.
renvoit -1, 0, ou 1 selon que la zone 1 est <, =, >, à la zone 2
la comparaison des nombres 32 bits est signée.
taille devrait être un multiple de 4. (sinon, arrondie au multiple de 4 précédent)
Environ même rapidité que CompareMem.
CompareMemLU(*mem1,*mem2,taille)
Comme CompareMemL, mais avec une comparaison des nombres 32 bits non signée.
CompareMemW(*mem1,*mem2,taille)
Comme CompareMemL, mais des nombres 16 bits (words) signés.
taille devrait être un multiple de 2. (sinon arrondie au multiple de 2 précédent)
CompareMemWU(*mem1,*mem2,taille)
Comme CompareMemW, mais des nombres 16 bits (words) non signés.
CompareMemB(*mem1,*mem2,taille)
Comme CompareMemL, mais des nombres 8 bits (bytes) signés.
CompareMemBU(*mem1,*mem2,taille)
Comme CompareMemB, mais des nombres 8 bits (bytes) non signés.
CompareMemString(*mem1,*mem2)
Comme comparememstring de PB (option 0), sensible à la casse. 1/3 plus rapide environ.
FindL(*mem,n.l,taille)
Cherche, de 4 octets en 4 octets, l'ocurrence de n dans la zone commençant à *mem, de longueur
taille.
taille devrait être un multiple de 4. (sinon, arrondie au multiple de 4 précédent).
Renvoit -1 si n n'apparait pas, ou pos, où pos est l'offset par rapport à *mem de la première
apparition de n. (ie que n apparait a l'adresse *mem+pos)
FindW(*mem,n.w,taille)
Cherche, de 2 octets en 2 octets, l'ocurrence de n dans la zone commençant à *mem, de longueur
taille.
taille devrait être un multiple de 2. (sinon, arrondie au multiple de 2 précédent).
Renvoit -1 si n n'apparait pas, ou pos, où pos est l'offset par rapport à *mem de la première
apparition de n. (ie que n apparait a l'adresse *mem+pos)
FindB(*mem,n.b,taille)
Cherche, d' octet en octet, l'ocurrence de n dans la zone commençant à *mem, de longueur
taille.
Renvoit -1 si n n'apparait pas, ou pos, où pos est l'offset par rapport à *mem de la première
apparition de n. (ie que n apparait a l'adresse *mem+pos)
ReplaceL(*mem,a.l,b.l,taille)
Cherche, de 4 octets en 4 octets, les ocurrences de a dans la zone commençant à *mem, de longueur
taille et remplace les a par b.
taille devrait être un multiple de 4. (sinon, arrondie au multiple de 4 précédent).
ReplaceW(*mem,a.w,b.w,taille)
Cherche, de 2 octets en 2 octets, les ocurrences de a dans la zone commençant à *mem, de longueur
taille et remplace les a par b.
taille devrait être un multiple de 2. (sinon, arrondie au multiple de 2 précédent).
ReplaceB(*mem,a.b,b.b,taille)
Cherche, d'octet en octet, les ocurrences de a dans la zone commençant à *mem, de longueur
taille et remplace les a par b.
librairie actuelle ici
Manuel ici
Je continue...
Merci d'avance à ceux qui pourraient déjà tester ça (fonctionnement et rapidité)
Toutes les tailles et longueurs sont en octets (bytes)
MoveMem(*source,*dest,taille):
comme rtlmovememory_, mais un peu plus rapide.
CompareMem(*mem1,*mem2,taille):
comme comparememory de PB, mais 4 fois plus rapide.
CompareMemL(*mem1,*mem2,taille)
compare, selon l'ordre lexicographique, par zones de 32bits (long) les zones mémoires
commençant aux adresses *mem1 et *mem2, et de longueur taille.
renvoit -1, 0, ou 1 selon que la zone 1 est <, =, >, à la zone 2
la comparaison des nombres 32 bits est signée.
taille devrait être un multiple de 4. (sinon, arrondie au multiple de 4 précédent)
Environ même rapidité que CompareMem.
CompareMemLU(*mem1,*mem2,taille)
Comme CompareMemL, mais avec une comparaison des nombres 32 bits non signée.
CompareMemW(*mem1,*mem2,taille)
Comme CompareMemL, mais des nombres 16 bits (words) signés.
taille devrait être un multiple de 2. (sinon arrondie au multiple de 2 précédent)
CompareMemWU(*mem1,*mem2,taille)
Comme CompareMemW, mais des nombres 16 bits (words) non signés.
CompareMemB(*mem1,*mem2,taille)
Comme CompareMemL, mais des nombres 8 bits (bytes) signés.
CompareMemBU(*mem1,*mem2,taille)
Comme CompareMemB, mais des nombres 8 bits (bytes) non signés.
CompareMemString(*mem1,*mem2)
Comme comparememstring de PB (option 0), sensible à la casse. 1/3 plus rapide environ.
FindL(*mem,n.l,taille)
Cherche, de 4 octets en 4 octets, l'ocurrence de n dans la zone commençant à *mem, de longueur
taille.
taille devrait être un multiple de 4. (sinon, arrondie au multiple de 4 précédent).
Renvoit -1 si n n'apparait pas, ou pos, où pos est l'offset par rapport à *mem de la première
apparition de n. (ie que n apparait a l'adresse *mem+pos)
FindW(*mem,n.w,taille)
Cherche, de 2 octets en 2 octets, l'ocurrence de n dans la zone commençant à *mem, de longueur
taille.
taille devrait être un multiple de 2. (sinon, arrondie au multiple de 2 précédent).
Renvoit -1 si n n'apparait pas, ou pos, où pos est l'offset par rapport à *mem de la première
apparition de n. (ie que n apparait a l'adresse *mem+pos)
FindB(*mem,n.b,taille)
Cherche, d' octet en octet, l'ocurrence de n dans la zone commençant à *mem, de longueur
taille.
Renvoit -1 si n n'apparait pas, ou pos, où pos est l'offset par rapport à *mem de la première
apparition de n. (ie que n apparait a l'adresse *mem+pos)
ReplaceL(*mem,a.l,b.l,taille)
Cherche, de 4 octets en 4 octets, les ocurrences de a dans la zone commençant à *mem, de longueur
taille et remplace les a par b.
taille devrait être un multiple de 4. (sinon, arrondie au multiple de 4 précédent).
ReplaceW(*mem,a.w,b.w,taille)
Cherche, de 2 octets en 2 octets, les ocurrences de a dans la zone commençant à *mem, de longueur
taille et remplace les a par b.
taille devrait être un multiple de 2. (sinon, arrondie au multiple de 2 précédent).
ReplaceB(*mem,a.b,b.b,taille)
Cherche, d'octet en octet, les ocurrences de a dans la zone commençant à *mem, de longueur
taille et remplace les a par b.
librairie actuelle ici
Manuel ici
Je continue...
Merci d'avance à ceux qui pourraient déjà tester ça (fonctionnement et rapidité)
Ajouté:
Disponible aux mêmes adresses.
Code : Tout sélectionner
Swap(*mem1,*mem2,taille)
Echange des zones mémoires. Ne doivent pas s'intersecter.
EliminateL(*mem,n.l,taille)
Cherche, de 4 octets en 4 octets, l'ocurrence de n dans la zone commençant à *mem, de longueur
taille et les élimine
taille devrait être un multiple de 4. (sinon, arrondie au multiple de 4 précédent).
renvoit la taille de la zone mémoire obtenue, commençant toujours à l'adresse *mem.
EliminateW(*mem,n.W,taille)
Cherche, de 2 octets en 2 octets, l'ocurrence de n dans la zone commençant à *mem, de longueur
taille et les élimine.
taille devrait être un multiple de 2. (sinon, arrondie au multiple de 2 précédent).
renvoit la taille de la zone mémoire obtenue, commençant toujours à l'adresse *mem.
EliminateB(*mem,n.b,taille)
Cherche, d'octet en octet, l'ocurrence de n dans la zone commençant à *mem, de longueur
taille et les élimine.
renvoit la taille de la zone mémoire obtenue, commençant toujours à l'adresse *mem.
Pour le soldat inconnu :
N'est rentable que sur une zone mémoire. (pour convertir un seul long, ce qu'on gagne en asm, on le perd en sauvegarde/restauration de registre lors de l'appel et du retour de proc.
exemple:
Dispo toujours au même lien.
Code : Tout sélectionner
RGBtoBGR(*mem,taille)
convertit les longs de la zone mémoire commençant à mem, et de longueur taille, du format
00RRGGBB au format 00BBGGRR.
taille devrait être un multiple de 4. (sinon, arrondie au multiple de 4 précédent).
exemple:
Code : Tout sélectionner
#nb = 10000000
Dim couleur.l(10000000)
couleur(0) = RGB(200, 100, 50); pour vérifier...
couleur(10000000) = RGB(33, 17, 18)
If OpenLibrary(0,"c:\memory.dll")
*convert=IsFunction(0,"RGBtoBGR")
If *convert
temps1 = ElapsedMilliseconds()
For i = 1 To #nb
couleur(i) = RGB(Blue(couleur(i)), Green(couleur(i)), Red(couleur(i)))
Next
temps2 = ElapsedMilliseconds()
CallFunctionFast(*convert,@couleur(),4*10000001)
Temps3 = ElapsedMilliseconds()
MessageRequester("Test rapidité", "Solution 1 : " + Str(temps2 - temps1) +Chr(10)+ " Solution 2 : " + Str(Temps3 - temps2), 0)
EndIf
EndIf
Je vais faire des tests avec ta Dll cette semaine.
Que penses-tu de faire un librairie format PB plutôt qu'un Dll ou en plus d'une Dll, au choix ?
Je préfère la création d'une lib directement en asm
J'ai adapté ton code asm suivant pour en faire une librairie PB que l'on appelle diretement depuis PB
Je n'ai pas modifié le code en soi, j'ai simplement adapté les adresses des paramètres pour que ça fonctionne en lib et j'ai fait un fichier descripteur et un petit code PB pour tester la vitesse
Ton code
devient (avec les quelques commentaires)
et le fichier descripteur devient
enregistre le fichier descripteur dans un dossier avec le nom que tu veux suivi de l'extension desc
(je l'ai appelé memory.desc)
enregistre le fichier asm avec le nom que tu veux (je l'ai appelé CompareMemString.asm)
Ces deux fichiers doivent être dans le même dossier et utilise mon outil PureLibcompiler pour créer la librairie
Compilateur de librairie PB
Lance PureLibcompiler et clique sur créer une librairie et coche si ce n'est pas fait sur les cases suivantes:
Compresser la librairie
Effacer les fichiers obj
Effacer le fichier lib
créer la lib à partir des asm
tu cliques sur compiler la lib et tu sélectionne le fichier desc que tu as créé.
La lib est faite et mise directement dans le dossier correspondant.
Ouvre PureBasic ou s'il est déjà ouvert redémarre le compilateur.
Voici le code PB de comparaison, y a pas à dire, ton code est très bon
J'ai fait les tests avec le debugger off. Ca prend bien 1 minute ou pas loin sur ma bécane avant d'avoir les résultats; d'ailleurs, la messagerequester ne s'affiche pas au premier plan, j'entend le son correspondant à son pouverture et je bascule vers elle.
Que penses-tu de faire un librairie format PB plutôt qu'un Dll ou en plus d'une Dll, au choix ?
Je préfère la création d'une lib directement en asm
J'ai adapté ton code asm suivant pour en faire une librairie PB que l'on appelle diretement depuis PB
Je n'ai pas modifié le code en soi, j'ai simplement adapté les adresses des paramètres pour que ça fonctionne en lib et j'ai fait un fichier descripteur et un petit code PB pour tester la vitesse
Ton code
Code : Tout sélectionner
ProcedureDLL CompareMemString(source,dest,flag)
Select flag
Case 0 ; case sensitive
MOV esi,source
MOV edi,dest
!MOV eax,0
!bouclecms:
!MOV ebx,[esi]
!MOV edx,[edi]
!CMP bl,0
!JE fincms1
!CMP dl,0
!JE fincms2
!CMP bl,dl
!JA cmssup
!JB cmsinf
!CMP bh,0
!JE fincms1h
!CMP dh,0
!JE fincms2h
!CMP bh,dh
!JA cmssup
!JB cmsinf
!ROL ebx,16
!ROL edx,16
!CMP bl,0
!JE fincms1
!CMP dl,0
!JE fincms2
!CMP bl,dl
!JA cmssup
!JB cmsinf
!CMP bh,0
!JE fincms1h
!CMP dh,0
!JE fincms2h
!CMP bh,dh
!JA cmssup
!JB cmsinf
!ADD esi,4
!ADD edi,4
!JMP bouclecms
!fincms1:
!CMP dl,0
!JE fincms
!MOV eax,-1
!JMP fincms
!fincms2:
!CMP bl,0
!JE fincms
!MOV eax,1
!JMP fincms
!fincms1h:
!CMP dh,0
!JE fincms
!MOV eax,-1
!JMP fincms
!fincms2h:
!CMP bh,0
!JE fincms
!MOV eax,1
!JMP fincms
!cmssup:
!MOV eax,1
!JMP fincms
!cmsinf:
!MOV eax,-1
!fincms:
ProcedureReturn
Case 1
EndSelect
EndProcedure
devient (avec les quelques commentaires)
Code : Tout sélectionner
format MS COFF
public PB_CompareMemString
; --------------------------------------;
; Syntaxe PureBasic ;
; ;
; CompareMemString(source,dest,flag) ;
; ;
; --------------------------------------;
; --------------------------------------;
; équivalence ;
; --------------------------------------;
Decalage = (Fin_Decalage-Debut_Decalage)*4
; --------------------------------------;
; Paramètres d'entrée ;
; --------------------------------------;
; flag.l
flag equ dword [esp+Decalage+12]
; dest.l
dest equ dword [esp+Decalage+8]
; source.l
source equ dword [esp+Decalage+4]
; --------------------------------------;
; Section code ;
; --------------------------------------;
section '.text' code readable executable
PB_CompareMemString:
Debut_Decalage:
PUSH ebx
PUSH esi
PUSH edi
Fin_Decalage:
MOV eax, flag
TEST eax, eax
JNZ fincms
; Case 0 ; case sensitive
MOV esi,source
MOV edi,dest
MOV eax,0
bouclecms:
MOV ebx,[esi]
MOV edx,[edi]
CMP bl,0
JE fincms1
CMP dl,0
JE fincms2
CMP bl,dl
JA cmssup
JB cmsinf
CMP bh,0
JE fincms1h
CMP dh,0
JE fincms2h
CMP bh,dh
JA cmssup
JB cmsinf
ROL ebx,16
ROL edx,16
CMP bl,0
JE fincms1
CMP dl,0
JE fincms2
CMP bl,dl
JA cmssup
JB cmsinf
CMP bh,0
JE fincms1h
CMP dh,0
JE fincms2h
CMP bh,dh
JA cmssup
JB cmsinf
ADD esi,4
ADD edi,4
JMP bouclecms
fincms1:
CMP dl,0
JE fincms
MOV eax,-1
JMP fincms
fincms2:
CMP bl,0
JE fincms
MOV eax,1
JMP fincms
fincms1h:
CMP dh,0
JE fincms
MOV eax,-1
JMP fincms
fincms2h:
CMP bh,0
JE fincms
MOV eax,1
JMP fincms
cmssup:
MOV eax,1
JMP fincms
cmsinf:
MOV eax,-1
fincms:
POP edi
POP esi
POP ebx
RET 12
Code : Tout sélectionner
; Langage utilisé pour coder la librairie ASM ou C
ASM
; Nombre de Dll windows utilisée par la lib
0
; Type de librairie
LIB
; Aucune librairies PureBasic & utilisateur utilisé par la librairie
0
; Nom du fichier d'aide de notre libraire, OBLIGATOIRE !
CompareMemString.chm
; Enumération des nouvelles fonctions crées
CompareMemString, String, String, Long, ()
Long | StdCall
(je l'ai appelé memory.desc)
enregistre le fichier asm avec le nom que tu veux (je l'ai appelé CompareMemString.asm)
Ces deux fichiers doivent être dans le même dossier et utilise mon outil PureLibcompiler pour créer la librairie
Compilateur de librairie PB
Lance PureLibcompiler et clique sur créer une librairie et coche si ce n'est pas fait sur les cases suivantes:
Compresser la librairie
Effacer les fichiers obj
Effacer le fichier lib
créer la lib à partir des asm
tu cliques sur compiler la lib et tu sélectionne le fichier desc que tu as créé.
La lib est faite et mise directement dans le dossier correspondant.
Ouvre PureBasic ou s'il est déjà ouvert redémarre le compilateur.
Voici le code PB de comparaison, y a pas à dire, ton code est très bon

Code : Tout sélectionner
source$ = "DenisDenisDenisDenisDenisDenisDenisDenisDenisDenis"
dest$ = source$
temp=GetTickCount_()
For i = 0 To 50000000
a = CompareMemString(source$,dest$,0)
Next i
Valeur$ = "Résultat de CompareMemString() : "+Str(GetTickCount_()-temp)+Chr(10)
temp=GetTickCount_()
For i = 0 To 50000000
a = CompareMemoryString(source$,dest$,0)
Next i
Valeur$ + "Résultat de la fonction PureBasic : "+Str(GetTickCount_()-temp)+Chr(10)+Chr(10)
source$ = "DenisDenisDenisDenisDenisDenisDenisDenisDenisDenis"
dest$ = "aenisDenisDenisDenisDenisDenisDenisDenisDenisDenis"
temp=GetTickCount_()
For i = 0 To 50000000
a = CompareMemString(source$,dest$,0)
Next i
Valeur$ + "Résultat de CompareMemString() : "+Str(GetTickCount_()-temp)+Chr(10)
temp=GetTickCount_()
For i = 0 To 50000000
a = CompareMemoryString(source$,dest$,0)
Next i
Valeur$ + "Résultat de la fonction PureBasic : "+Str(GetTickCount_()-temp)+Chr(10)+Chr(10)
source$ = "DenisDenisDenisDenisDenisDenisDenisDenisDenisDenis"
dest$ = "DenisDenisDenisDenisDenisDenisDenisDenisDenisDenas"
temp=GetTickCount_()
For i = 0 To 50000000
a = CompareMemString(source$,dest$,0)
Next i
Valeur$ + "Résultat de CompareMemString() : "+Str(GetTickCount_()-temp)+Chr(10)
temp=GetTickCount_()
For i = 0 To 50000000
a = CompareMemoryString(source$,dest$,0)
Next i
Valeur$ + "Résultat de la fonction PureBasic : "+Str(GetTickCount_()-temp)
MessageRequester("Résultats pour 50000000 itérations",valeur$,16)
Merci bien pour tout ça!
J'ai fait diverses modifs, mais pas à jour sur le lien : les pages perso wanadoo sont en travaux jusqu'au 17.
Je vais m'y remettre.
Là, le "seul" pb, c'est que j'ai deux services sur le dos, à cause de ma collègue malade. L'enfer... Des semaines de 70h mini
A propos, c'est bien ce que je pensais : le copymemoryAMD de EL_Choni était buggé : ne copiait qu'1/8ème des données!
Le nouveau publié marche 1,7 fois (environ) plus vite sur AMD pour une taille >1Mo, mais moins vite sur pentium (?!)
Le MoveMemory que j'ai fait a la même vitesse que le copymemory PB pour une taille <=1Mo (pas de prelecture, ça ralentit), mais 1,5 fois plus rapide à partir de 2-3Mo.
Même pb que pour le code AMD : si c'est trop petit, les opérations de prélectures prennent plus de temps qu'elles n'en font gagner après!
J'ai encore pas mal de tests à faire avec diverses fonctions pour voir ce qui fonctionne le mieux.
Souvent, la "tactique" à adopter varie selon la taille des données.
Alors il faut tester...

J'ai fait diverses modifs, mais pas à jour sur le lien : les pages perso wanadoo sont en travaux jusqu'au 17.
Je vais m'y remettre.
Là, le "seul" pb, c'est que j'ai deux services sur le dos, à cause de ma collègue malade. L'enfer... Des semaines de 70h mini

A propos, c'est bien ce que je pensais : le copymemoryAMD de EL_Choni était buggé : ne copiait qu'1/8ème des données!
Le nouveau publié marche 1,7 fois (environ) plus vite sur AMD pour une taille >1Mo, mais moins vite sur pentium (?!)
Le MoveMemory que j'ai fait a la même vitesse que le copymemory PB pour une taille <=1Mo (pas de prelecture, ça ralentit), mais 1,5 fois plus rapide à partir de 2-3Mo.
Même pb que pour le code AMD : si c'est trop petit, les opérations de prélectures prennent plus de temps qu'elles n'en font gagner après!
J'ai encore pas mal de tests à faire avec diverses fonctions pour voir ce qui fonctionne le mieux.
Souvent, la "tactique" à adopter varie selon la taille des données.
Alors il faut tester...
Ca serait chouette si tu faisais ça : j'ai peu de temps en ce moment.
Dans la semaine, je fais un peu de ménage, et je t'envoie les codes déjà faits.
Y'aura qu'à modifier le début et la fin (sauvegarde/restauration des registres via la pile, récupération des données d'entrée).
Et puis voir quelles améliorations apporter!
Faut que je mette des prélectures un peu partout pour accélérer un peu.
Dis-moi : pourquoi comparememorystring tourne-t-il plus vite en n'étant pas sensible à la casse?
A priori, ça engendre plus de travail...
Chez toi, que donne le "nouveau" copymemoryAMD (dispo au même "topic" qu'avant sur forum anglais)? (si tu as un Pentium)
Dans la semaine, je fais un peu de ménage, et je t'envoie les codes déjà faits.
Y'aura qu'à modifier le début et la fin (sauvegarde/restauration des registres via la pile, récupération des données d'entrée).
Et puis voir quelles améliorations apporter!
Faut que je mette des prélectures un peu partout pour accélérer un peu.
Dis-moi : pourquoi comparememorystring tourne-t-il plus vite en n'étant pas sensible à la casse?
A priori, ça engendre plus de travail...
Chez toi, que donne le "nouveau" copymemoryAMD (dispo au même "topic" qu'avant sur forum anglais)? (si tu as un Pentium)