Pour alléger le prg comme il est toujours nécessaire d’avoir un registre
Voici une solution particulière pour ce type de données
Code : Tout sélectionner
;JE teste LES fonctionnalités SIMD,LES bases pour débuter LES additions de vecteurs/tableau
;avec des entiers. (vecteur/tableau étant des éléments contigue de meme longueur/aligné).
;
; ADDITION_SIMD_MMX_SSE_
; 1=> test Vecteur//Tableau
; long.l = 7 // = 8*8 = 64 bits
; long.l = 15 //= 16*8 = 128 bits
long.l=7
;
Dim veca.b(long) ;// Source 1
Dim vecb.b(long) ;// Source 2
Dim vecc.b(long) ;// Destination
; Define.l r1, r2, r3,r10,r12,r13
a.l=@veca()
b.l=@vecb()
c.l=@vecc()
Debug b-a
Debug c-b
Debug c-a
; Remplir Vecteur
;
For i=0 To long
;
veca(i)=i+1
vecb(i)=i+10
vecc(i)=0
Debug"======================"
Debug "Adresse "+Str(i)
Debug "Vecteur A contient = "+Str(veca(i))
Debug "Vecteur B contient = "+Str(vecb(i))
Debug "Vecteur C contient = "+Str(vecc(i))
;
Next i
;
Debug"_______________________"
Debug"_______________________"
;***** adition tableau_vecteur
!mov ecx, [v_a] ;// source Vecteur a en memoire eax = 64 bits = 8 valeur
!movq xmm0, [ecx] ;// copie en memoire xmm0/128_bits contenu eax/64_bits
!movq xmm1,[ecx+40]
;
!movq xmm2,[ecx+80]
;
!paddq xmm2, xmm0 ;// adition regitres xmm2 et xmm0 / vecc + veca
!paddq xmm2, xmm1 ;// adition regitres xmm2 et xmm1 / vecc + vecb
!movq [ecx+80],xmm2 ; résultat dans vecc ecx+80
;*******
; Debug "r1="+Str(r1)+" r2="+Str(r2)
For i=0 To long
Debug"________SSE_ADITION_RESULTAT_________"
Debug "Adresse "+Str(i)
Debug "Vecteur A contient = "+Str(veca(i))
Debug "Vecteur B contient = "+Str(vecb(i))
Debug "Vecteur C contient = "+Str(vecc(i))
Next i
;
Debug""
Toutefois il est très intéressante d'utiliser ces instructions.
A titre d'exemple voici un programme résumant les performances entre une instruction PB un prg ASM simple et un Prg avec instructions SSE..
L'instruction Pb est 'Resultat = CountString(Chaine$, ChaineATrouver$)'
Code : Tout sélectionner
Procedure CountChars(*B.Ascii,L,Char.a)
;posted by Trond
!mov ecx, [p.v_L]
!mov dl, [p.v_Char]
!mov eax, [p.p_B]
!push edi
!push ebp
!mov ebp, eax
!xor edi, edi
!lp:
!xor eax, eax
!cmp byte [ecx+ebp-1], dl
!sete al
!add edi, eax
!add ecx, -1
!jnz lp
!mov eax, edi
!pop ebp
!pop edi
ProcedureReturn
EndProcedure
Procedure CountCharAsmSSE2_x86(*B.Ascii,Length,Char.a)
;Windows, 32-Bit
;based on posts by Road Runner. Excellent!
;without prefetch
;"old" loop, sorry
;not full tested!
; Le nom de @ @ signifie étiquette anonyme,vous pouvez avoir défini un grand nombre d'entre eux dans la source.
;Symbole @ b(ou l'équivalent @ r)le plus proche des références du label précédent anonyme
;,symbole @ f références plus proche de l'étiquette suivante anonyme.
;Ces symboles spéciaux sont insensibles à la casse.
!mov ecx,[p.v_Length]
!movzx edx,byte[p.v_Char]
!push esi
!mov esi,[p.p_B+4]
!push edi
!push ebx
;Duplicate Char (Byte to Dqword)
!mov dh,dl
!mov eax,edx
!shl edx,10h
!mov dx,ax
!movd xmm0,edx
!shufps xmm0,xmm0,0 ;xmm0=16x Char
;Check Length
!xor eax,eax ;eax=0, General-Counter
!mov edx,ecx ;ecx=Length
!shr ecx,4 ;div.16
!or ecx,ecx ;ecx=Number of 16-Byte-Chunks
!jz Rest ;Length<16, edx=Length
!mov ebx,esi ;Test for 16-Byte-Alignment
!and ebx,0fh
!jz IsAli16 ;is 16-Byte-Alignment
!dec ecx ;Chunk-1
!mov edi,10h
!sub edi,ebx ;Alignment-Diff
!sub edx,edi ;Length-edi
!movd ebx,xmm0 ;Char
!Rest0:
!cmp byte[esi],bl
!jne @f
!inc eax
!@@:
!inc esi
!dec edi
!jnz Rest0
!IsAli16: ;Alignment16
!or ecx,ecx ;ecx=Number of 16-Byte-Chunks
!jz Rest ;Length<16 or Chunk set to Zero, edx=Length
!mov ebx,ecx
!shl ebx,4 ;mul.16
!sub edx,ebx ;edx=Rest-Bytes without 16-Byte-Chunks
!movdqa xmm1,xmm0 ;Save Char
!pxor xmm2,xmm2 ;Counter in Chunk-Loop
!mov edi,ecx
!cmp ecx,0ffh
!jbe @f
!mov edi,0ffh
!@@:
!pcmpeqb xmm0,[esi]
!paddb xmm2,xmm0
!movdqa xmm0,xmm1 ;Restore Char
!add esi,16
!dec edi
!jnz @b ; jump si Non Zero au précédent label anonyme @@
!pxor xmm3,xmm3 ;xmm3=0
!psubb xmm3,xmm2 ;neg -> pos
!pxor xmm4,xmm4 ;xmm4=0
!psadbw xmm4,xmm3 ;add the 8 upper and 8 lower Bytes, Results in Bits 0-15 and Bits 64-79
!movdqa xmm3,xmm4 ;take a copy
!psrldq xmm4,8 ;shift right 8 Bytes
!paddw xmm3,xmm4 ;add the 2 8 byte sums to give a 16 byte sum
!movd ebx,xmm3
!add eax,ebx ;add to General-Counter
!sub ecx,0ffh
!jna @f ;zero or less, no Chunks more Jump si Non Egal au label anonyme @@ suivant
!pxor xmm2,xmm2
!mov edi,0ffh
!cmp ecx,0ffh
!ja @b
!mov edi,ecx
!jmp @b
!@@:
!movdqa xmm0,xmm1 ;Restore Char in xmm0
!Rest:
!or edx,edx ;edx=Rest-Bytes
!jz Ende
!movd ecx,xmm0 ;Char
!Rest1:
!cmp byte[esi],cl
!jne @f
!inc eax
!@@:
!inc esi
!dec edx
!jnz Rest1
!Ende:
!pop ebx
!pop edi
!pop esi
ProcedureReturn
EndProcedure
B.s
B="abcdefabcdefaaaaaffffbdddffff1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
; b="1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
B=ReplaceString(Space(1000)," ",B) ;thousand copies of B
L=Len(B)
#Tries=100000
time=ElapsedMilliseconds()
For U=0 To #Tries
NumHelle=CountCharAsmSSE2_x86(@B,L,'a')
Next
TimeHelle=ElapsedMilliseconds()-time
Helle$="NumHelle : "+Str(NumHelle)+" Time : "+Str(TimeHelle)
time=ElapsedMilliseconds()
For U=0 To #Tries
NumTrond=CountChars(@B,L,'a')
Next
TimeTrond=ElapsedMilliseconds()-time
time=ElapsedMilliseconds()
For U=0 To #Tries
NumPB=CountString(B,"a")
Next
TIMEPB=ElapsedMilliseconds()-time
PB$="NumPB : "+Str(NumPB)+" Time : "+Str(TimePB)
Trond$="NumTrond : "+Str(NumTrond)+" Time : "+Str(TimeTrond)
MessageRequester("Results","Long="+Str(l)+#CRLF$+Helle$+#CRLF$+Trond$+#CRLF$+PB$)
Les 2 Prg ASM sont de Trond pour le plus simple ASM et de Road Runner avec instructions SSE
Les résultats sont sans appel.