Schneller Len(String$) Befehl
-
- Beiträge: 476
- Registriert: 23.03.2005 23:19
Also ich denke trotzdem, dass:
schneller ist als
Code: Alles auswählen
@LOOP:
INC EBX
SHR EAX,1
JNC @LOOP
DEC EBX
Code: Alles auswählen
!sub ebx,16 ;Zeiger in String 16 Byte zurück und Ende suchen
W1:
!mov eax,[ebx] ;ab hier muss Byte-weise gesucht werden
!test eax,0ffh
!jz l_w2
!inc ebx
!test eax,0ff00h
!jz l_w2
!inc ebx
!test eax,0ff0000h
!jz l_w2
!inc ebx
!test eax,0ff000000h
!jz l_w2
!inc ebx
!jmp l_w1
W2:
Optimismus ist ein Mangel an Information.
Ich hab´s ausprobiert, Alignments gesetzt, andere Abfragen - hat nicht überzeugt. Es sieht allerdings viel eleganter aus. Zum Selbertesten:
Gruss
Helle
Code: Alles auswählen
;- Helle 08.10.2006 PB4.00
;- Zeigt Einsatz von SSE zur Ermittlung von Len(String)
;- Auf Feinheiten wie Überprüfung auf Verfügbarkeit und Sicherungen der Umgebung wurde verzichtet
Global X.l
Global Y.l
Global Len.l
Global String.s = "Ich bin ein fieser Teststaksjdfasdfkajslödfjaslkdjflöalöaksjdflkasjdlkfjasölkdfjlaksdjfing"
;Global string.s = "Ich bin ein fieser Teststring"
TestZeit.l = ElapsedMilliseconds()
X = @String ;Zeiger auf den String
For i = 1 To 20000000
!mov ebx,[v_X]
W0:
!movdqu xmm0,[ebx] ;16 Byte des Strings einlesen
!add ebx,16
!pxor xmm1,xmm1 ;xmm1 auf Null setzen
!pcmpeqb xmm0,xmm1 ;jedes der 16 Byte von xmm0 mit Null (xmm1) vergleichen und auf 0 oder 255 (bei Gleichheit) setzen
!pmovmskb eax,xmm0 ;die Vorzeichen-Bits der einzelnen Bytes nach eax kopieren
!or ax,ax ;auf Null testen. Waren in xmm1 Null-Bytes, ist ax nicht mehr Null
!jz l_w0 ;weiter einlesen, wenn Null-Byte (String-Ende) noch nicht gefunden
!sub ebx,16 ;Zeiger in String 16 Byte zurück und Ende suchen
W1:
!inc ebx ;das erste gesetzte Bit (= Null-Byte des Strings suchen)
!shr ax,1
!jnc l_w1 ;weitersuchen, wenn Bit nicht gesetzt
!dec ebx
;!mov eax,[ebx]
;!test eax,0ffh
;!jz l_w2
;!inc ebx
;!test eax,0ff00h
;!jz l_w2
;!inc ebx
;!test eax,0ff0000h
;!jz l_w2
;!inc ebx
;!test eax,0ff000000h
;!jz l_w2
;!inc ebx
;!jmp l_w1
W2:
Next
!mov [v_Y],ebx ;"nur" für Anzeige der Stringlänge
Zeit = ElapsedMilliseconds() - TestZeit
!mov edx,[v_Y]
!sub edx,[v_X]
!mov [v_Len],edx
MessageRequester("Len(String) mit SSE","Stringlänge = " + Str(Len) + Chr(13) + "Testzeit = " + Str(Zeit) + " ms")
End
Helle
-
- Beiträge: 476
- Registriert: 23.03.2005 23:19
Das hier wird dich aber freuen:
Code: Alles auswählen
;- Helle 08.10.2006 PB4.00
;- Zeigt Einsatz von SSE zur Ermittlung von Len(String)
;- Auf Feinheiten wie Überprüfung auf Verfügbarkeit und Sicherungen der Umgebung wurde verzichtet
Global X.l
Global Y.l
Global Len.l
Global String.s = "Ich bin ein fieser Teststaksjdfasdfkajslödfjasl"
;Global string.s = "Ich bin ein fieser Teststring"
TestZeit.l = ElapsedMilliseconds()
X = @String ;Zeiger auf den String
For i = 1 To 60000000
!MOV Ebx,[v_X]
!pxor xmm1,xmm1 ;xmm1 auf Null setzen
W0:
!MOVDQU xmm0,[Ebx] ;16 Byte des Strings einlesen
!ADD Ebx,16
!pcmpeqb xmm0,xmm1 ;jedes der 16 Byte von xmm0 mit Null (xmm1) vergleichen und auf 0 oder 255 (bei Gleichheit) setzen
!pmovmskb Eax,xmm0 ;die Vorzeichen-Bits der einzelnen Bytes nach eax kopieren
!OR Eax,Eax ;auf Null testen. Waren in xmm1 Null-Bytes, ist ax nicht mehr Null
!JZ l_w0 ;weiter einlesen, wenn Null-Byte (String-Ende) noch nicht gefunden
!SUB Ebx,16 ;Zeiger in String 16 Byte zurück und Ende suchen
!BSF Edx,Eax
!ADD Ebx,Edx
W2:
Next
!MOV [v_Y],Ebx ;"nur" für Anzeige der Stringlänge
Zeit = ElapsedMilliseconds() - TestZeit
!MOV Edx,[v_Y]
!SUB Edx,[v_X]
!MOV [v_Len],Edx
MessageRequester("Len(String) mit SSE","Stringlänge = " + Str(Len) + Chr(13) + "Testzeit = " + Str(Zeit) + " ms")
End
Optimismus ist ein Mangel an Information.
Auch nicht schlecht
! Da mir die Bitsuch-Befehle aber ein Graus sind (Taktzyklen-Fresser, aber offensichtlich noch besser als viele kurze Rücksprünge - Pipeline?) habe ich folgendes probiert und siehe da, ist noch schneller:
Gruss
Helle

Code: Alles auswählen
;- Helle 09.10.2006 PB4.00
;- Zeigt Einsatz von SSE zur Ermittlung von Len(String)
;- Auf Feinheiten wie Überprüfung auf Verfügbarkeit und Sicherungen der Umgebung wurde verzichtet
Global X.l
Global Y.l
Global Len.l
Global String.s = "Ich bin ein fieser Teststaksjdfasdfkajslödfjaslkdjflöalöaksjdflkasjdlkfjasölkdfjlaksdjfing"
TestZeit.l = ElapsedMilliseconds()
X = @String ;Zeiger auf den String
For i = 1 To 20000000
!mov ebx,[v_X]
!pxor xmm1,xmm1 ;xmm1 auf Null setzen, natürlich ausserhalb der Schleife
W0:
!movdqu xmm0,[ebx] ;16 Byte des Strings einlesen
!add ebx,16
!pcmpeqb xmm0,xmm1 ;jedes der 16 Byte von xmm0 mit Null (xmm1) vergleichen und auf 0 oder 255 (bei Gleichheit) setzen
!pmovmskb eax,xmm0 ;die Vorzeichen-Bits der einzelnen Bytes nach eax kopieren
!or eax,eax ;auf Null testen. Waren in xmm1 Null-Bytes, ist ax nicht mehr Null
!jz l_w0 ;weiter einlesen, wenn Null-Byte (String-Ende) noch nicht gefunden
!sub ebx,17 ;Zeiger in String 17 Byte zurück und Ende suchen
!test al,255
!jnz l_w1
!xchg ah,al
!add ebx,8
W1:
!inc ebx ;das erste gesetzte Bit (= Null-Byte des Strings suchen)
!shr ax,1
!jnc l_w1 ;weitersuchen, wenn Bit nicht gesetzt
Next
!mov [v_Y],ebx ;"nur" für Anzeige der Stringlänge
Zeit = ElapsedMilliseconds() - TestZeit
!mov edx,[v_Y]
!sub edx,[v_X]
!mov [v_Len],edx
MessageRequester("Len(String) mit SSE","Stringlänge = " + Str(Len) + Chr(13) + "Testzeit = " + Str(Zeit) + " ms")
End
Helle
-
- Beiträge: 476
- Registriert: 23.03.2005 23:19
Jaein. Du hast den String deinem Testmuster angepasst ^^
Dieser geht vom schlimmsten Fall aus Len%16=15. Probier da mal meine Variante, du wirst sehen, da ist sie schneller. Jetzt bleibt uns nur noch zu ermitteln, welche Strings relativ häufiger vorkommen, um sagen zu können, welche Methode sinnvoller ist ^^.
Code: Alles auswählen
Global String.s = "Ich bin ein fieser Teststaksjdfasdfkajslödfjasl"
Optimismus ist ein Mangel an Information.
-
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
-
- Beiträge: 476
- Registriert: 23.03.2005 23:19
-
- Beiträge: 17389
- Registriert: 10.11.2004 03:22