lib memory

Programmation d'applications complexes
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

Message par hardy »

@Dri : pas de problème. Je ferai un swap qui ne crée pas de zone mémoire temporaire.
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

hardy a écrit : @denis : oui, je connais le code. déjà vu sur divers sites, dont intel.
Pour un maximum de compatibilité je vais faire sans mmx. J'ai testé : n'augmente pas considérablement la vitesse pour ce que je fais.
Maintenant le jeu de commandesMMX est integré dans les processeurs.
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

hardy a écrit :@Dri : pas de problème. Je ferai un swap qui ne crée pas de zone mémoire temporaire.
Ah bah ca rien que pou le principe ca m'intéresse !!

Dri :D
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

Message par hardy »

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é)
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

Message par hardy »

Ajouté:

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.
Disponible aux mêmes adresses.
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

Message par hardy »

Pour le soldat inconnu :

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).
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:

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

Dispo toujours au même lien.
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

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

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
et le fichier descripteur devient

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

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)
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.
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

Message par hardy »

Merci bien pour tout ça! :D
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 :mad:


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...
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Si tu veux , je peux convertir en fichier asm et faire le desc correspondant.
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

Message par hardy »

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)
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Ok,

pour comparememorystring, je n'ai pas d'idée et je n'ai pas testé le noveau code AMD
Répondre