FindString für 2 GB per ASM optimieren, ABER Syntax??

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Re: FindString für 2 GB per ASM optimieren, ABER Syntax??

Beitrag von Helle »

Was ist denn los, FindString ist auf einmal DER Renner :lol: !
Mit SSE4.2 kann ich im englichen Forum wohl nicht punkten (läuft ja nicht auf 10 Jahre alten Notebooks :mrgreen: ), deshalb hier für Win64 und Unicode Test-Codes jeweils für FindString und FindChar (also nur 1 Zeichen wird gesucht).

Code: Alles auswählen

String$ = Space(1000000) + "8!#"
FindString$ = "8!"
;FindString$ = "                          8!" ;längeren FindString sollte man auch mal testen :-) !
FindChar$ = "!"
StartPos.q = 1;2345
#Loops = 1000

Procedure.q FindString_SSE42_64Bit_Uni(pString, pFindString, Start)
  ;hier mal testweise eingefügt
  !cmp dword[PB_Compiler_Debugger],0   ;Debugger aus?
 !je @f                                ;ja
  ;Debug "Mach aus das Ding!"
  MessageRequester("Debugger", "Mach aus das Ding!")
  !mov r8,[p.v_Start]                  ;für 32-Bit wäre dies (mit 32-Bit-Registern) notwendig
  !mov rdx,[p.v_pFindString]
  !mov rcx,[p.v_pString]
 !@@:
  !cmp r8,1                            ;r8=StartPos
 !jge @f
  !mov r8,1                            ;oder Ende oder Error (?)
 !@@:
  !mov rax,r8                          ;rax=Rückgabe-Wert Pos
  !dec r8
  !shl r8,1
  !mov r12,rcx                         ;rcx=pString, ecx wird aber von pcmpistri verwendet
  !add r12,r8
  !cmp word[rcx],0                     ;Test auf Null-String hier mal eingefügt
 !je .NoFound  
  !cmp word[rdx],0                     ;rdx=pFindString
 !je .NoFound
  !movdqu xmm0,[rdx]                   ;ersten max.16 Bytes (8 Words) von FindString
  !xor rcx,rcx
 !.Search:
  !add rax,rcx
  !add r12,rcx
  !add r12,rcx
  !movdqu xmm2,[r12]                   ;wegen StartPos, 2.Parameter von pcmpistri muss align16 sein
  !pcmpistri xmm0,xmm2,00001101b       ;Least Significant Index, Positive Polarity (IntRes2=IntRes1), Equal Ordered, Unsigned Words (=Unicode)
 !jno .Search
 !js .Find$End
 !jz .Base$End
  !mov r9,r12
  !mov r10,rdx
 !@@:
  !add r10,16                          ;nächste 8 Words von FindString
  !add r9,16                           ;nächste 8 Words von String
  !movdqu xmm1,[r10]
  !movdqu xmm2,[r9]
  !pcmpistri xmm1,xmm2,00001101b
 !js .Find$End
 !jz .Base$End
 !jo @b
 !jmp .Search
 !.Base$End:
  !cmp rcx,8
 !je .NoFound
 !jmp .Found
 !.Find$End:
  !or rcx,rcx                          ;rcx Zero? 
 !jne .Search
 !.Found:
  !add rax,rcx
 ProcedureReturn                       ;rax 
 !.NoFound:
  !xor rax,rax
 ProcedureReturn                       ;rax 
EndProcedure 

Procedure.q FindCharSSE42_64Bit_Uni(pString, pFindChar, Start)
  ;hier mal testweise eingefügt
  !cmp dword[PB_Compiler_Debugger],0   ;Debugger aus?
 !je @f                                ;ja
  ;Debug "Mach aus das Ding!"
  MessageRequester("Debugger", "Mach aus das Ding!")
  !mov r8,[p.v_Start]                  ;für 32-Bit wäre dies (mit 32-Bit-Registern) notwendig
  !mov rdx,[p.v_pFindString]
  !mov rcx,[p.v_pString]
 !@@:
  !cmp r8,1                            ;r8=StartPos
 !jge @f
  !mov r8,1                            ;oder Ende oder Error (?)
 !@@:
  !mov rax, -16
  !shl r8,1
  !add rax,r8
  !movdqu xmm1,[rdx]                   ;rdx=pFindChar
  !mov r9,rcx                          ;rcx=pString, ecx wird aber von pcmpistri verwendet
 !@@:
  !add rax,16
  !movdqu xmm0,[r9+rax]                ;wegen StartPos, 2.Parameter von pcmpistri muss align16 sein
  !pcmpistri xmm1,xmm0,00000001b       ;Bit0 = 1 und Bit1 = 0, also String-Chars werden als unsigned Words (=Unicode) interpretiert, Bit2 = 0 und Bit3 = 0, also Test auf equal any
 !ja @b                                ;C=0, Z=0
  !cmp rcx,8
 !je @f
  !shr rax,1                           ;Pointer in String muss hier halbiert werden
  !add rax,rcx
  !inc rax 
 ProcedureReturn                       ;rax = Pos., beginnt bei 1
 !@@:
  !xor rax,rax
 ProcedureReturn                       ;rax = 0, Char nicht gefunden
EndProcedure 

;PB 
TA = ElapsedMilliseconds() 
For i = 1 To #Loops
  PosPB = FindString(String$, FindString$, StartPos) 
Next
TE = ElapsedMilliseconds() - TA 
PB$ = "PB : Time = " + Str(TE) + " ms    Result : " + Str(PosPB)
;SSE4.2
TA = ElapsedMilliseconds() 
For i = 1 To #Loops
  PosSSE = FindString_SSE42_64Bit_Uni(@String$, @FindString$, StartPos) 
Next
TE = ElapsedMilliseconds() - TA 
FindString_SSE42_64Bit_Uni$ = "SSE4.2 : Time = " + Str(TE) + " ms    Result : " + Str(PosSSE)
MessageRequester("FindString 64-Bit Unicode", PB$ + #CRLF$ + FindString_SSE42_64Bit_Uni$)

;PB 
TA = ElapsedMilliseconds() 
For i = 1 To #Loops
  PosPB = FindString(String$, FindChar$, StartPos) 
Next
TE = ElapsedMilliseconds() - TA 
PB$ = "PB : Time = " + Str(TE) + " ms    Result : " + Str(PosPB)
;SSE4.2
TA = ElapsedMilliseconds() 
For i = 1 To #Loops
  PosSSE = FindCharSSE42_64Bit_Uni(@String$, @FindChar$, StartPos) 
Next
TE = ElapsedMilliseconds() - TA 
FindChar_SSE42_64Bit_Uni$ = "SSE4.2 : Time = " + Str(TE) + " ms    Result : " + Str(PosSSE)
MessageRequester("FindChar 64-Bit Unicode", PB$ + #CRLF$ + FindChar_SSE42_64Bit_Uni$)


Ist aber noch nicht ganz durchgetestet!
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: FindString für 2 GB per ASM optimieren, ABER Syntax??

Beitrag von Mijikai »

Wow! :o
Vielen Dank :allright:

Hab noch was gefunden -> FindCharSSE42_64Bit_Uni():

Code: Alles auswählen

;!mov rdx,[p.v_pFindString] statt mov rdx,[p.v_pFindChar]
sonst kann ich nicht weiter helfen/testen dazu ist mein ASM Wissen zu gering :)
Antworten