Ich bin mir nicht sicher, ob du meine Ausführung mit der Sprungvorhersage verstanden hast, wenn du eine aufsteigende Sequenz zwischen x und y testest, ist das witzlos, denn die Daten bei einer reellen Berechnung liegen nicht in dieser Form vor. In den Daten im Test, wo du von -111 bis 366 gehst hast du nun 112 mal jle jump taken, 366 mal non taken, und dann 255 mal jbe jump taken, 111 mal non taken, immer hintereinander, da ist die Sprungvorhersage immernoch fast immer richtig.
Realistische Werte erhälst du nur, wenn du die Werte nicht in auf- oder absteigender Reihenfolge an die Funktion fütterst sondern in einer realistischen Verteilung durchgemischt.
Danke Stevie,
tschuldi, dass ich so spät antworte. Ich hatte diesen Text schon vor 2 Wochen geschrieben, mich dann aber um andere Themen gekümmert.
Ich bin mir sicher, dass ich Deine Ausführungen verstanden hatte und ich bin mir auch sicher, dass ich das auch schon vorher wusste.
Ich habe die CMOV-Instruktion immer gemieden, weil sie nicht von allen Prozessoren unterstützt wird, was allerdings eine recht alte Information ist.
Ich habe die Testprozeduren noch einmal überarbeitet.
Die zu vergleichenden Werte kommen jetzt aus einem Daten-Array, das mit Zufallswerten, und bei einem zweiten Testlauf mit aufsteigenden Werten gefüllt ist.
Die Laufzeiten sind immer recht unterschiedlich, typische Werte waren:
Code:
Zufallswerte
1,360 2,184 3,926 CPU-Ticks TestCMovShort
2,602 4,243 20,340 CPU-Ticks TestMov
1,242 2,059 16,414 CPU-Ticks Differenz
Aufsteigende Werte
1,360 1,501 27,828 CPU-Ticks TestCMovShort
1,614 1,755 27,457 CPU-Ticks TestMov
254 254 -371 CPU-Ticks Differenz
Der fragliche Code wird für jedes Pixel der Bitmap 4 Mal ausgeführt.
Ausgehend von dem Gewinn von 1242 CPU-Ticks für 478 Vergleiche, einer Bitmap mit 2.4 MPixel, und einer CPU-Frequenz von 3.4GHz ergibt sich ein Gewinn von
1242/478*2.4M/3.4G*4*1000 = 7.3 ms.
Bei einer Laufzeit von 63 ms für die Umwandlung der Bitmap ist der Gewinn von 7 ms nicht unbedeutend.
Delphi-Quellcode:
var
Data:Array[0..366+111] of Integer;
Delphi-Quellcode:
procedure TestCMovShort;
const HI=High(Data);
asm
push esi
// Save ESI
push 0
// Memory
mov esi,255
// Max-Value
mov ecx,HI
// Index from High(Data) downto 0
@Loop: mov edx,[ecx*4+Data]
// Value
mov eax,0
// Min-Value
cmp edx,esi
// Value vs. Max-Value
cmovg eax,esi
// Load Max-Value if Value > Max-Value
cmovbe eax,edx
// Load Value if Value <= Max-Value
mov [esp],al
// Store New Value
dec ecx
// Index - 1
jns @Loop
// Loop until Index = 0
pop ecx
// Remove Memory from Stack
pop esi
// Restore ESI
end;
Delphi-Quellcode:
PROCEDURE TestMov;
const HI=High(Data);
asm
push 0
// Memory
mov ecx,HI
// Index from High(Data) downto 0
@Loop: mov eax,[ecx*4+Data]
// Value
cmp eax,0
// Value vs. 0
jle @Zero
// Jump if New-Value <= 0
cmp eax,255
// Value vs. 255
jbe @Store
// Jump if Value <= 255
mov byte[esp],255
// Store 255 as New Value
jmp @Next
// Next Index
@Zero: mov byte[esp],0
// Store 0 as New Value
jmp @Next
// Next Index
@Store: mov [esp],al
// Store New Value
@Next:
dec ecx
// Index - 1
jns @Loop
// Loop until Index < 0
pop ecx
// Remove Memory from Stack
end;