cs_CALAMS
Messages postés3Date d'inscriptionmercredi 28 février 2007StatutMembreDernière intervention 3 janvier 2009 3 janv. 2009 à 12:28
BRAVO
cs_cam91
Messages postés19Date d'inscriptiondimanche 9 juin 2002StatutMembreDernière intervention 4 février 2006 27 juil. 2002 à 22:47
je viens de découvrir que pour la routine NB il y avait moyen d'accélerer beaucoup le code en remplacant la division par une multiplication:
@b1:
mov edx,dword [edi] //edx:8*0 8*r 8*v 8*b
xor eax,eax;xor ecx,ecx;mov al,dl;mov cl,dh
add ax,cx;shr edx,16;mov cl,dl
add ax,cx //ax=cr+cv+cb
// à la place de xor edx,edx;mov ecx,3;idiv ecx on écrit
imul eax,21845
shr eax,16 //multiplication par 0,33333
imul edx,eax,$010101
mov dword [esi],edx //edx:8*0 8*cnb 8*cnb 8*cnb
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim //boucle jusqu'à edi=lim
jne @b1
En fait au lieu de diviser par 3 on multiplie par 21845/(2^16)=0,333328 Très éfficace quand on sait la lourdeur d'une division en assembleur.
cs_Nono40
Messages postés962Date d'inscriptionmercredi 3 avril 2002StatutMembreDernière intervention12 septembre 20062 1 juil. 2002 à 22:06
Merci, mais je viens de vérifier un peu la différence de vitesse car j'étais resté sur les souvenirs d'un 386. Or il apparait que de travailler sur les registres et mémoires 8 bits est beaucoup plus long. Ainsi ce que je t'ai dis pour le bleu est faux :
@b1:
mov edx,dword [edi]
shl edx,24
shr edx,24
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1
( 16,8 secondes pour 1000 boucles )
est plus rapide que
xor edx,edx
@b1:
mov dl,byte [edi]
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1
( 19,3 secondes pour 1000 boucles )
Amusant non ?
Note que le source le plus court ( en taille ) pour le bleu serait le suivant :
asm
push edi
push esi
mov ecx,npix
mov esi,addrsource
mov edi,addrDest
xor eax,eax
@b1:
mov al,byte [ecx*4+esi-4]
mov dword [ecx*4+edi-4],eax
loop @b1
pop esi
pop edi
end;
( 19,7 secondes pour 1000 boucles )
Et le plus rapide que j'ai trouvé est le suivant :
asm
push edi
push esi
mov eax,npix
shl eax,2
add eax,addrsource
mov lim,eax
mov esi,addrsource // j'ai inversé ESI et EDI
mov edi,addrDest
cld // pour incrémenter EDI et ESI
@b1:
lodsd
shl eax,24
shr eax,24
stosd
cmp edi,lim
jne @b1
pop esi
pop edi
end;
( 16,1 secondes pour 1000 boucles )
Il est surprenant de constater que le source le plus court en ligne ( 3 lignes pour la boucle ) est le plus long à l'exécution !!!
On pourrait discuter encore longtemps sur le sujet, mais on va finir me dire que le site est un site Delphi et non assembleur... Ton source à de toute façon sa place ici, car c'est la seule manière d'avoir une procédure optimisée. Il suffit de regarder dans les sources des unités de Delphi pour voir que l'assembleur est très présent...
Bonne continuation.
Nono.
cs_cam91
Messages postés19Date d'inscriptiondimanche 9 juin 2002StatutMembreDernière intervention 4 février 2006 1 juil. 2002 à 00:29
Merci pour tous vos commentaires, surtout à nono40 qui semble vraiment bien maitriser l'assembleur intégré.
Quant à fabiin, je suis désolé mais je ne maitrise pas du tout l'anti-aliasing, je sais à peine de quoi il s'agit!
J'ai tenu à mettre cette source sur le site de Delphi pour montrer l'importance et la simplicité de l'assembleur intégré.
cs_Bestiol
Messages postés833Date d'inscriptiondimanche 6 janvier 2002StatutMembreDernière intervention 3 novembre 20051 28 juin 2002 à 13:31
euh... Y a quand même un site assembleur, maintenant...
Pasque moi, j'y comprends rien !!!
Mais c'est toute fois assez intéressant à utiliser !
Bye !
fabiin
Messages postés329Date d'inscriptionmercredi 4 avril 2001StatutMembreDernière intervention 8 décembre 20096 28 juin 2002 à 12:49
ca serait cool de faire pareil mais avec l'effet, anti-aliasing, enfin ca m'arrangerai bien :)
fabiin
Messages postés329Date d'inscriptionmercredi 4 avril 2001StatutMembreDernière intervention 8 décembre 20096 28 juin 2002 à 09:35
tès interessant !
cs_Nono40
Messages postés962Date d'inscriptionmercredi 3 avril 2002StatutMembreDernière intervention12 septembre 20062 28 juin 2002 à 06:31
C'est effectivement très rapide, mais en assembleur point de limite ! En creusant un peu on trouve presque toujours quelques cycles à gagner :
** Pour la procédure Negatif
On peut aller plus vite en tolérant une erreur de 1/256 sur les couleurs. En effet NEG et XOR $FF ne font une différence que de 1 sur le poids faible. Par contre le XOR n'ayant pas de retenue, on peut traiter les trois couleurs en même temps :
mov edx,dword [edi] //edx:8*0 8*r 8*v 8*b
xor edx,$00FFFFFF
mov dword [esi],edx //b'=256-b,v'=256-v,r'=256-r
C'est d'ailleurs plus juste car pour le noir ($000000) XOR donne blanc ($FFFFFF) tandis que NEG reste noir
** RVB
Le XOR eax,eax en début de boucle n'est pas utile, car tout est mis à zéro par le calcul de R
Pour le calcul de V tu écris trois lignes là ou une seule suffit :
shr dx,8
shl dx,8
add eax,edx
Peut être remplacé par
Mov ah,dh
Car en fait seul DH importe et on doit le caser dans AH
De même pour le calcul de B
shr dx,8
add eax,edx //eax:8*0 8*r' 8*v' 8*b'
Peut être remplacé par
Mov al,dh
** NB
Le XOR CX,CX n'est pas utile car CH est déjà zéro et CL est écrit juste après.
Ensuite j'ai doute car je n'ai pas les temps de cycle CPU, mais
mov dl,al
shl edx,16
mov dl,al
mov dh,al
peut être remplacé par :
imul edx,eax,$010101
C'est plus court mais ce n'est plus rapide que la multiplication entière est cablèe dans le processeur ( c'est pour ça que j'ai un doute car je sais pas... )
** Bleu
On peut simplifier la boucle
xor edx,edx // une seule fois pour toute l'image
@b1:
mov dl,byte [edi] // on ne lit que DL
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1
** Vert
On peut simplifier la boucle :
xor edx,edx
@b1:
mov dh,byte [edi+1] // On ne lit que DH
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1
** Rouge
On peut remplacer
shr edx,16
shl edx,16
Par
xor dx,dx
Voila, c'est tout. Ton programme montre une chose importante : l'assembleur en ligne est vraiement simple à utiliser et dans ce cas beaucoup plus rapide qu'une procédure en pur Pascal.
3 janv. 2009 à 12:28
27 juil. 2002 à 22:47
@b1:
mov edx,dword [edi] //edx:8*0 8*r 8*v 8*b
xor eax,eax;xor ecx,ecx;mov al,dl;mov cl,dh
add ax,cx;shr edx,16;mov cl,dl
add ax,cx //ax=cr+cv+cb
// à la place de xor edx,edx;mov ecx,3;idiv ecx on écrit
imul eax,21845
shr eax,16 //multiplication par 0,33333
imul edx,eax,$010101
mov dword [esi],edx //edx:8*0 8*cnb 8*cnb 8*cnb
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim //boucle jusqu'à edi=lim
jne @b1
En fait au lieu de diviser par 3 on multiplie par 21845/(2^16)=0,333328 Très éfficace quand on sait la lourdeur d'une division en assembleur.
1 juil. 2002 à 22:06
@b1:
mov edx,dword [edi]
shl edx,24
shr edx,24
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1
( 16,8 secondes pour 1000 boucles )
est plus rapide que
xor edx,edx
@b1:
mov dl,byte [edi]
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1
( 19,3 secondes pour 1000 boucles )
Amusant non ?
Note que le source le plus court ( en taille ) pour le bleu serait le suivant :
asm
push edi
push esi
mov ecx,npix
mov esi,addrsource
mov edi,addrDest
xor eax,eax
@b1:
mov al,byte [ecx*4+esi-4]
mov dword [ecx*4+edi-4],eax
loop @b1
pop esi
pop edi
end;
( 19,7 secondes pour 1000 boucles )
Et le plus rapide que j'ai trouvé est le suivant :
asm
push edi
push esi
mov eax,npix
shl eax,2
add eax,addrsource
mov lim,eax
mov esi,addrsource // j'ai inversé ESI et EDI
mov edi,addrDest
cld // pour incrémenter EDI et ESI
@b1:
lodsd
shl eax,24
shr eax,24
stosd
cmp edi,lim
jne @b1
pop esi
pop edi
end;
( 16,1 secondes pour 1000 boucles )
Il est surprenant de constater que le source le plus court en ligne ( 3 lignes pour la boucle ) est le plus long à l'exécution !!!
On pourrait discuter encore longtemps sur le sujet, mais on va finir me dire que le site est un site Delphi et non assembleur... Ton source à de toute façon sa place ici, car c'est la seule manière d'avoir une procédure optimisée. Il suffit de regarder dans les sources des unités de Delphi pour voir que l'assembleur est très présent...
Bonne continuation.
Nono.
1 juil. 2002 à 00:29
Quant à fabiin, je suis désolé mais je ne maitrise pas du tout l'anti-aliasing, je sais à peine de quoi il s'agit!
J'ai tenu à mettre cette source sur le site de Delphi pour montrer l'importance et la simplicité de l'assembleur intégré.
28 juin 2002 à 13:31
Pasque moi, j'y comprends rien !!!
Mais c'est toute fois assez intéressant à utiliser !
Bye !
28 juin 2002 à 12:49
28 juin 2002 à 09:35
28 juin 2002 à 06:31
** Pour la procédure Negatif
On peut aller plus vite en tolérant une erreur de 1/256 sur les couleurs. En effet NEG et XOR $FF ne font une différence que de 1 sur le poids faible. Par contre le XOR n'ayant pas de retenue, on peut traiter les trois couleurs en même temps :
mov edx,dword [edi] //edx:8*0 8*r 8*v 8*b
xor edx,$00FFFFFF
mov dword [esi],edx //b'=256-b,v'=256-v,r'=256-r
C'est d'ailleurs plus juste car pour le noir ($000000) XOR donne blanc ($FFFFFF) tandis que NEG reste noir
** RVB
Le XOR eax,eax en début de boucle n'est pas utile, car tout est mis à zéro par le calcul de R
Pour le calcul de V tu écris trois lignes là ou une seule suffit :
shr dx,8
shl dx,8
add eax,edx
Peut être remplacé par
Mov ah,dh
Car en fait seul DH importe et on doit le caser dans AH
De même pour le calcul de B
shr dx,8
add eax,edx //eax:8*0 8*r' 8*v' 8*b'
Peut être remplacé par
Mov al,dh
** NB
Le XOR CX,CX n'est pas utile car CH est déjà zéro et CL est écrit juste après.
Ensuite j'ai doute car je n'ai pas les temps de cycle CPU, mais
mov dl,al
shl edx,16
mov dl,al
mov dh,al
peut être remplacé par :
imul edx,eax,$010101
C'est plus court mais ce n'est plus rapide que la multiplication entière est cablèe dans le processeur ( c'est pour ça que j'ai un doute car je sais pas... )
** Bleu
On peut simplifier la boucle
xor edx,edx // une seule fois pour toute l'image
@b1:
mov dl,byte [edi] // on ne lit que DL
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1
** Vert
On peut simplifier la boucle :
xor edx,edx
@b1:
mov dh,byte [edi+1] // On ne lit que DH
mov dword [esi],edx
add edi,4;add esi,4 //saut de 32 bit, pixel suivant
cmp edi,lim
jne @b1
** Rouge
On peut remplacer
shr edx,16
shl edx,16
Par
xor dx,dx
Voila, c'est tout. Ton programme montre une chose importante : l'assembleur en ligne est vraiement simple à utiliser et dans ce cas beaucoup plus rapide qu'une procédure en pur Pascal.
Nono