Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Bei Unicode ergibts immer 1
Das machen die langsameren besser
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
ouch, ein speedvergleich anhand ElapsedMilliseconds(). verwende lieber timeGetTime_() und benütze timeBeginPeriod_(1) am anfang deines programms und timeEndPeriod_(1) am ende deines programms.
auf meinem p4 ist deine variante etwa ~5ms schneller.
c ya,
nco2k
~|__/
..o.o.. <--- This is Einkaufswagen. Copy Einkaufswagen into your signature to help him on his way to world domination.
;- Zeigt Einsatz von MMX und 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 Teststring"
TestZeit.l = ElapsedMilliseconds()
X = @String ;Zeiger auf den String
For i = 1 To 10000000
!mov ebx,[v_X]
W0:
!movq mm0,[ebx] ;8 Byte des Strings einlesen
!add ebx,8
!pxor mm1,mm1 ;mm1 auf Null setzen
!pcmpeqb mm0,mm1 ;jedes der 8 Byte von mm0 mit Null (mm1) vergleichen
!cvtpi2pd xmm0,mm0 ;Konvertierung von Integer in Double für nachfolgenden Vergleich
!pxor xmm2,xmm2 ;xmm2 auf Null setzen
!ucomisd xmm0,xmm2 ;vergleicht die 2 Doubles in den unteren Quad-Words
!jz l_w0
!sub ebx,8 ;Zeiger in String 8 Byte zurück und Ende suchen
!mov edx,[v_X]
!sub edx,ebx
!jnc l_w1
!sub ebx,4
W1:
!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 und MMX","Stringlänge = " + Str(Len) + Chr(13) + "Testzeit = " + Str(Zeit) + " ms")
End
Gruss
Helle
/Edit: Mindestlänge String aufgehoben und optimiert, FAsm-Data-Section eingespart
Hier noch eine Version ohne MMX, nur mit SSE2. Greift gut bei längeren Strings, deshalb wurde als Teststring ein aktuelles Beispiel aus der PureBasic-Lounge genommen. Werte bei mir: "Denise": 1.030ms, SSE2: 610ms.
;- Helle 08.10.2006 PB4.00
;- Zeigt Einsatz von SSE2 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]
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
!cvtdq2ps xmm2,xmm0 ;Konvertierung von Integer in 4 Singles für nachfolgenden Vergleich
!ucomiss xmm2,xmm1 ;vergleicht die 4 Singles mit Null
!jz l_w0 ;Null-Byte (String-Ende) noch nicht gefunden
!sub ebx,16 ;Zeiger in String 16 Byte zurück und Ende suchen
!mov edx,[v_X]
!sub edx,ebx
!jnc l_w1
!sub ebx,12
W1:
!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 SSE2","Stringlänge = " + Str(Len) + Chr(13) + "Testzeit = " + Str(Zeit) + " ms")
End
Nachdem meine obigen Beispiele schamlos den Speicher-Verwaltungsmodus für Strings von PB ausgenutzt haben und mein SSE-Buch auch etwas unklar war, hier eine "saubere" Variante, die sogar noch etwas schneller ist.
;- 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"
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 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:
!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:
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 SSE2","Stringlänge = " + Str(Len) + Chr(13) + "Testzeit = " + Str(Zeit) + " ms")
End