Wie wird das Registerflagbei CMPSD gesetzt?
-
@cmovb: Das sieht ganz gut aus, was ergeben sich denn für Zeiten? Ein wenig loop-unrolling ist ggf. noch möglich.
@FrEEzE2046: Die Kommentare zu cmovbs Code beachten:
Außerdem vergleichst du hier:
test ecx,0FFFFFFFCh
ob in ECX 4294967292 steht - bedenke, in ECX steht ein DWORD-Typ (unsigned long). Ich denke du möchstest mit 4 vergleichen.
test setzt die Flags, wie sie bei and entstehen würden. Das ist also korrekt.
-
FrEEzE2046 schrieb:
@cmovb
Nicht böse gemeint: Hast du nur die Geschwindigkeit getestet oder auch die Funktionalität? Deine Funktion liefert immer 1 zurück bei mir, egal ob es wirklich größer, kleiner oder sogar gleich ist.Du möchtest beliebig große Zahlen Vergleichen? - so hab ich das verstanden. Und ja, ich hab die Funktion getestet: sowohl auf Geschwindigkeit als auch auf Funktionalität!
FrEEzE2046 schrieb:
Was machst du da eigentlich? Du hast doch vollkommen falsche Adressen im EDI und ESI Register, da du einfach die nimmst, die vorher schon drin standen. Das kann so ja nicht funktionieren
nun, ich gehe mal davon aus, das du in der Lage bist die minimalen Anpassungen selber vor zu nehmen - Welcher Parameter wo drin ist hab ich ja extra angegeben!
FrEEzE2046 schrieb:
Außerdem vergleichst du hier:
test ecx,0FFFFFFFCh
ob in ECX 4294967292 steht - bedenke, in ECX steht ein DWORD-Typ (unsigned long). Ich denke du möchstest mit 4 vergleichen.
test = and - überleg dir mal auf was geprüft wird
FrEEzE2046 schrieb:
Btw: Welche Rolle spielt der Core 2 Duo, wenn ich fragen darf.
Die Ausführungszeiten(clocks) und Latenzen der Befehle unterscheiden sich zwischen verschieden CPU-Generation und -Herstellern.
-
camper schrieb:
@cmovb: Das sieht ganz gut aus, was ergeben sich denn für Zeiten? Ein wenig loop-unrolling ist ggf. noch möglich.
@FrEEzE2046: Die Kommentare zu cmovbs Code beachten:
Habe ich, aber sie sind doch einfach falsch. Wenn hier kein Funktionsheader angegeben ist, denke ich doch, dass er die selbe annimmt, wie ich sie gestellt hatte.
Außerdem kenne ich keine Aufrufkonvention die direkt ins esi, edi Register schreibt.camper schrieb:
test setzt die Flags, wie sie bei and entstehen würden. Das ist also korrekt.
Das stimmt. Aber er möchte doch keine Konjunktion mit 4294967292 machen oder?
-
@camper: hab dazu nen kleines testbed (Konsole) in masm geschrieben, bzw immer zur Hand:
repe cmpsd vs. loop - angabe in clocks - loop count: 10000000 --------------------------- string size: 1 loop: 4 repe movsd: 88 string size: 2 loop: 11 repe movsd: 93 string size: 4 loop: 5 repe movsd: 89 string size: 8 loop: 12 repe movsd: 94 string size: 16 loop: 24 repe movsd: 105 string size: 32 loop: 48 repe movsd: 125 string size: 64 loop: 97 repe movsd: 165 string size: 128 loop: 193 repe movsd: 245 string size: 256 loop: 387 repe movsd: 406
Zum Testen hab ich hier zwei gleiche Strings (0) gewählt - dass zwingt beide Algo‘s den gesamten String zu scannen. Der Cache spielt hier keine Rolle, da die Strings von beiden Funktionen gleich abgegriffen werden (hier gibt es also keine Benachteiligung).
Wenn Interesse besteht, kann ich den Quellcode Posten.
-
cmovb schrieb:
Wenn Interesse besteht, kann ich den Quellcode Posten.
Ich bin sehr interessiert
@cmovb: Übrigens, Du hast guten Stil, habe mir sogar die Zeit genommen, Deine Funktion zu lesen. Kannst Du bitte den vollständigen Code der Funktion posten?
-
abc.w schrieb:
Du hast guten Stil
Dann wirs du gleich deine Meinung ändern (sag nur macros...)
include masm32rt.inc include C:\masm32\macros\timers.asm .686p .mmx .xmm .code start: print "repe cmpsd vs. loop",10,13 print " - angabe in clocks",10,13 print " - loop count: 10000000 ",10,13 print "---------------------------",10,13 .data align 16 s1 dd 64 dup (0) s2 dd 64 dup (0) .code _size = 1 REPEAT 9 print " string size: " print str$(_size),10,13 counter_begin 10000000, REALTIME_PRIORITY_CLASS mov esi,OFFSET s1 mov edi,OFFSET s2 mov ecx,_size ; esi = lho ; edi = rho ; ecx = size test ecx,0FFFFFFFCh lea edi,[edi+ecx-1] lea esi,[esi+ecx-1] jz @CatStr(<@bytes>,%(_size)) lea edi,[edi-3] lea esi,[esi-3] @CatStr(<@dwords>,%(_size),<:>) mov eax,DWORD ptr [esi] mov edx,DWORD ptr [edi] lea edi,[edi-4] lea esi,[esi-4] lea ecx,[ecx-4] cmp eax,edx mov eax,0 seta al sbb eax,0 jnz @CatStr(<@fin>,%(_size)) test ecx,0FFFFFFFCh jnz @CatStr(<@dwords>,%(_size)) test ecx,ecx jz @CatStr(<@fin>,%(_size)) lea edi,[edi+3] lea esi,[esi+3] @CatStr(<@bytes>,%(_size),<:>) movzx eax,BYTE ptr [esi] movzx edx,BYTE ptr [edi] lea edi,[edi-1] lea esi,[esi-1] cmp eax,edx mov eax,0 seta al sbb eax,0 jnz @CatStr(<@fin>,%(_size)) dec ecx jnz @CatStr(<@bytes>,%(_size)) @CatStr(<@fin>,%(_size),<:>) counter_end push eax print " loop: " pop eax print udword$(eax),10,13 counter_begin 10000000, REALTIME_PRIORITY_CLASS mov eax,OFFSET s1 mov edx,OFFSET s2 mov ecx,_size std lea esi, DWORD PTR [eax+ecx-1] lea edi, DWORD PTR [edx+ecx-1] xor eax, eax mov edx, ecx shr ecx, 2 jz @CatStr(<@Rest>,%(_size)) lea esi, DWORD PTR [esi-3] lea edi, DWORD PTR [edi-3] repe cmpsd jne @CatStr(<@Exit>,%(_size)) @CatStr(<@Rest>,%(_size),<:>) mov ecx, edx and ecx, 3 jz @CatStr(<@Exit>,%(_size)) lea esi, DWORD PTR [esi+3] lea edi, DWORD PTR [edi+3] repe cmpsb @CatStr(<@Exit>,%(_size),<:>) cld seta al sbb eax, 0 counter_end push eax print " repe movsd: " pop eax print udword$(eax),10,13 ,10,13 _size = _size*2 ENDM inkey exit end start
-
@cmovbs
So, ich hatte jetzt auch mal die Zeit mir deinen Code zu Gemüte zu führen. Und er ist tatsächlich 6 Sekunden schneller als meiner (nach meinen Tests mit 4294967295 (MAX_UINT) vergleichen über 16 Byte identische Operanden.Ich habe mal deinen Code etwas verändert und war nochmals 7 Sekunden (!) und damit um die Hälfte schneller.
push edi push esi push ebx //mov ebx, 0 xor ebx, ebx test ecx, $FFFFFFFC lea esi, DWORD PTR [eax+ecx-1] lea edi, DWORD PTR [edx+ecx-1] jz @@Bytes //lea esi, [esi-3] //lea edi, [edi-3] sub esi, 3 sub edi, 3 @@DWORDs: mov eax, DWORD PTR [esi] mov edx, DWORD PTR [edi] cmp eax, edx //mov eax, 0 jnz @@Exit //lea esi, [esi-4] //lea edi, [edi-4] //lea ecx, [ecx-4] sub esi, 4 sub edi, 4 sub ecx, 4 test ecx, $FFFFFFFC jnz @@DWORDs test ecx, ecx jz @@Exit //lea esi, [esi+3] //lea edi, [edi+3] add esi, 3 add edi, 3 @@Bytes: movzx eax, BYTE PTR [esi] movzx edx, BYTE PTR [edi] //lea edi, [edi-1] //lea esi, [esi-1] dec edi dec esi cmp eax, edx //mov eax, 0 jnz @@Exit dec ecx jnz @@Bytes @@Exit: seta bl sbb ebx, 0 mov eax, ebx pop ebx pop esi pop edi
-
gut
Auf die Idee, die Conditionals aus der Schleife zu ziehen, hätte ich Ansicht auch kommen sollen
-
BTW: Wie groß sind den die Zahlen maximal - bei 16 Byte vergleicht man ohne Schleife. Des weiteren wäre es interessant zu wissen, wie die Zahlen im Speicher ausgerichtet sind (align).
-
Hallo,
in meiner Testumgebung hatte ich ein Alignment von 4. Das erste Bit eines jeden Bytes habe ich testweise gesetzt. Der Byte loop wurde nicht gebraucht, dass ist richtig.
Gestern war es aber schon spät. Ich denke ich werde heute noch ein paar Tests machen und ggf. optimieren.
Durch die Verwendung des EBX Registers spart man noch etwas Zeit ein, da man auf ein lästiges mov verzichten kann. Ist aber natürlich Ansichtssache das EBX Register hier unberührt zu lassen.