Der zu testende Befehl ist per Hand 2x in den Code einzutragen (mehr Aufwand lohnte nicht) und wird dann in extra reservierten Speicher kopiert, dupliziert und dann dort ausgeführt.
Code: Alles auswählen
;- CPU-Latenz-Durchsatz-Messung
;- "Helle" Klaus Helbing, 26.08.2008, PB 4.20
;- Latenz: Anzahl der Taktzyklen, um den Befehl komplett abzuarbeiten
;- Durchsatz: Anzahl der Taktzyklen, bis derselbe Befehl erneut eingelesen werden kann
; (nach Beginn des Einlesens des ersten Befehles)
;- Latenzmessung: Jeder nachfolgende (gleichartige) Befehl ist abhängig vom Ergebnis des vorhergehenden Befehls
;- Durchsatzmessung: Jeder nachfolgende (gleichartige) Befehl ist unabhängig vom Ergebnis des vorhergehenden Befehls
;- Die Abarbeitung der zu testenden Befehle erfolgt in speziell reserviertem Speicher
;- Ein Wert von z.B. 2.01 ist natürlich als 2.00 zu interpretieren! (auch 0.34 = 0.33 usw.)
;- Bei Speicherzugriffen wird es (wie zu erwarten) etwas unscharf, mehrere Tests machen
;- Bei einigen Befehlen macht eine Durchsatz-Messung keinen Sinn
Global Mem.l = $100000 ;Speicher reservieren, hier 1MB
Global Looping.q = 1000
Global CodeMem.l
Global CodeMemUr.l
Global CodeA.l
Global CodeL.l
Global TimeA.q
Global TimeE.q
Global TicksL.d
Global TicksD.d
Global TicksZ.d
Global Ticks.d
Global TestVar1.l = 123456789
Global TestVar2.l = 234567890
Global TestVar3.l = 345678901
Global TestVar4.l = 456789012
Global TestVar5.l = 567890123
Global TestVar6.l = 678901234
Global TestVar7.l = 789012345
Global TestVar8.l = 890123456
XIncludeFile "LD.pbi"
hThread = GetCurrentThread_()
SetThreadAffinityMask_(hThread, 1) ;Thread nur von Core0 ausführen lassen (wenn Multi-Core-CPU)
SetThreadPriority_(hThread, #THREAD_PRIORITY_TIME_CRITICAL)
CodeMem = VirtualAllocEx_(GetCurrentProcess_(), #Null, Mem, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
If CodeMem
DisableDebugger
;Latenz-Messung ;keine Plausibilitäts-Überprüfung!
A1: ;hier zu testenden Befehl in den Macro-Aufruf einfügen
;ML_XMM_XMM(mulss)
;ML_REG32_REG32(imul)
;ML_REG32_MEM32(imul)
;ML_MEM32_REG32(adc)
;ML_REG32_IMM(sub)
ML_REG32_IMMFEST(rcl,3)
;ML_REG32(bswap)
;ML_JUMP ;hier sieht man sehr schön, daß Sprünge Gift sind. Also die
;ML_NOJUMP ; Verzweigungs-Art so wählen, das die Variante mit der zu
A2: ; erwartenden höheren Wahrscheinlichkeit keinen Sprung benötigt
CodeA = ?A1
CodeL = ?A2 - CodeA ;Codelänge des Macros
CodeMemUr = CodeMem ;sichern
LDTicks()
TicksL = Ticks
;Durchsatz-Messung ;keine Plausibilitäts-Überprüfung!
A3: ;hier zu testenden Befehl in den Macro-Aufruf einfügen
;MD_XMM_XMM(mulss)
;MD_REG32_REG32(imul)
;MD_REG32_MEM32(imul)
;MD_MEM32_REG32(adc)
;MD_REG32_IMM(sub)
MD_REG32_IMMFEST(rcl,3)
;MD_REG32(bswap)
A4:
CodeA = ?A3
CodeL = ?A4 - CodeA ;Codelänge des Macros
CodeMem = CodeMemUr
LDTicks()
TicksD = Ticks
;Fertig
VirtualFreeEx_(GetCurrentProcess_(), CodeMemUr, Mem, #MEM_DECOMMIT)
MessageRequester("Taktzyklen", "Latenz : " + StrD(TicksL, 2) + #LFCR$ + "Durchsatz : " + StrD(TicksD, 2))
Else
MessageRequester("Fehler !", "Der benötigte Speicher konnte nicht bereitgestellt werden !")
EndIf
End
Code: Alles auswählen
;LD.pbi
;==================================================================================================
Macro M_XMM_XMM_Z() ;XMM-Register auf 0 setzen
!pxor xmm0,xmm0
!movdqa xmm1,xmm0
!movdqa xmm2,xmm0
!movdqa xmm3,xmm0
!movdqa xmm4,xmm0
!movdqa xmm5,xmm0
!movdqa xmm6,xmm0
!movdqa xmm7,xmm0
EndMacro
;--------------------------------------------------------------------------------------------------
Macro ML_XMM_XMM(Befehl) ;Macro Latenz XMM - XMM-Register
!Befehl xmm0,xmm7 ;Einge Beispiele:
!Befehl xmm1,xmm0 ; DIVPD, DIVSD, MOVDQA, MOVDQU, MULPD, MULSD, ...
!Befehl xmm2,xmm1
!Befehl xmm3,xmm2
!Befehl xmm4,xmm3
!Befehl xmm5,xmm4
!Befehl xmm6,xmm5
!Befehl xmm7,xmm6
EndMacro
;--------------------------------------------------------------------------------------------------
Macro MD_XMM_XMM(Befehl) ;Beginn Macro Durchsatz XMM - XMM-Register
!Befehl xmm0,xmm1
!Befehl xmm2,xmm3
!Befehl xmm4,xmm5
!Befehl xmm6,xmm7
!Befehl xmm0,xmm1
!Befehl xmm2,xmm3
!Befehl xmm4,xmm5
!Befehl xmm6,xmm7
EndMacro
;--------------------------------------------------------------------------------------------------
Macro ML_REG32_REG32(Befehl) ;Macro Latenz 32-Bit-Register - 32-Bit-Register
!Befehl eax,edx ;Einige Beispiele:
!Befehl ebx,eax ; ADC, ADD, AND, BSF, BSR, CMOVcc, CMP, CMPXCHG
!Befehl ecx,ebx ; IMUL, MOV, OR, SBB, SUB, TEST, XADD, XCHG, XOR
!Befehl edx,ecx
!Befehl eax,edx
!Befehl ebx,eax
!Befehl ecx,ebx
!Befehl edx,ecx
EndMacro
;--------------------------------------------------------------------------------------------------
Macro MD_REG32_REG32(Befehl) ;Macro Durchsatz 32-Bit-Register - 32-Bit-Register
!Befehl eax,ebp
!Befehl ebx,ebp
!Befehl ecx,ebp
!Befehl edx,ebp
!Befehl eax,ebp
!Befehl ebx,ebp
!Befehl ecx,ebp
!Befehl edx,ebp
EndMacro
;--------------------------------------------------------------------------------------------------
Macro ML_REG32_MEM32(Befehl) ;Macro Latenz 32-Bit-Register - 32-Bit-Speicher
!Befehl eax,[v_TestVar1]
!Befehl eax,[v_TestVar2]
!Befehl eax,[v_TestVar3]
!Befehl eax,[v_TestVar4]
!Befehl eax,[v_TestVar5]
!Befehl eax,[v_TestVar6]
!Befehl eax,[v_TestVar7]
!Befehl eax,[v_TestVar8]
EndMacro
;--------------------------------------------------------------------------------------------------
Macro MD_REG32_MEM32(Befehl) ;Macro Durchsatz 32-Bit-Register - 32-Bit-Speicher
!Befehl eax,[v_TestVar1]
!Befehl ebx,[v_TestVar2]
!Befehl ecx,[v_TestVar3]
!Befehl edx,[v_TestVar4]
!Befehl eax,[v_TestVar5]
!Befehl ebx,[v_TestVar6]
!Befehl ecx,[v_TestVar7]
!Befehl edx,[v_TestVar8]
EndMacro
;--------------------------------------------------------------------------------------------------
Macro ML_MEM32_REG32(Befehl) ;Macro Latenz 32-Bit-Speicher - 32-Bit-Register
!Befehl [v_TestVar1],eax
!Befehl [v_TestVar2],eax
!Befehl [v_TestVar3],eax
!Befehl [v_TestVar4],eax
!Befehl [v_TestVar5],eax
!Befehl [v_TestVar6],eax
!Befehl [v_TestVar7],eax
!Befehl [v_TestVar8],eax
EndMacro
;--------------------------------------------------------------------------------------------------
Macro MD_MEM32_REG32(Befehl) ;Macro Durchsatz 32-Bit-Speicher - 32-Bit-Register
!Befehl [v_TestVar1],eax
!Befehl [v_TestVar2],ebx
!Befehl [v_TestVar3],ecx
!Befehl [v_TestVar4],edx
!Befehl [v_TestVar5],eax
!Befehl [v_TestVar6],ebx
!Befehl [v_TestVar7],ecx
!Befehl [v_TestVar8],edx
EndMacro
;--------------------------------------------------------------------------------------------------
Macro ML_REG32_IMM(Befehl) ;Macro Latenz 32-Bit-Register - Festwert
!Befehl eax,1 ;Einige Beispiele:
!Befehl eax,2 ; (RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR) dafür besser REG32_IMMFEST
!Befehl eax,3 ; ADD, ADC, CMP, IMUL, MOV, SBB, SUB
!Befehl eax,4
!Befehl eax,5
!Befehl eax,6
!Befehl eax,7
!Befehl eax,8
EndMacro
;--------------------------------------------------------------------------------------------------
Macro MD_REG32_IMM(Befehl) ;Macro Durchsatz 32-Bit-Register - Festwert
!Befehl eax,1
!Befehl ebx,2
!Befehl ecx,3
!Befehl edx,4
!Befehl eax,5
!Befehl ebx,6
!Befehl ecx,7
!Befehl edx,8
EndMacro
;--------------------------------------------------------------------------------------------------
Macro ML_REG32_IMMFEST(Befehl, Wert) ;Macro Latenz 32-Bit-Register - Festwert
!Befehl eax,Wert ;Einige Beispiele:
!Befehl eax,Wert ; RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR
!Befehl eax,Wert ; ADD, ADC, CMP, IMUL, MOV, SBB, SUB
!Befehl eax,Wert
!Befehl eax,Wert
!Befehl eax,Wert
!Befehl eax,Wert
!Befehl eax,Wert
EndMacro
;--------------------------------------------------------------------------------------------------
Macro MD_REG32_IMMFEST(Befehl, Wert) ;Macro Durchsatz 32-Bit-Register - Festwert
!Befehl eax,Wert
!Befehl ebx,Wert
!Befehl ecx,Wert
!Befehl edx,Wert
!Befehl eax,Wert
!Befehl ebx,Wert
!Befehl ecx,Wert
!Befehl edx,Wert
EndMacro
;--------------------------------------------------------------------------------------------------
Macro ML_REG32(Befehl) ;Macro Latenz 32-Bit-Register
!Befehl eax ;Einige Beispiele:
!Befehl eax ; BSWAP, DEC, IMUL, INC, MUL, NEG, NOT
!Befehl eax
!Befehl eax
!Befehl eax
!Befehl eax
!Befehl eax
!Befehl eax
EndMacro
;--------------------------------------------------------------------------------------------------
Macro MD_REG32(Befehl) ;Macro Durchsatz 32-Bit-Register
!Befehl eax
!Befehl ebx
!Befehl ecx
!Befehl edx
!Befehl edi
!Befehl esi
!Befehl ebp
!Befehl eax
EndMacro
;--------------------------------------------------------------------------------------------------
Macro ML_JUMP ;Macro Latenz JUMP, Sprung wird ausgeführt
!cmp ebp,0
!jne @f
!@@:
!cmp ebp,0
!jne @f
!@@:
!cmp ebp,0
!jne @f
!@@:
!cmp ebp,0
!jne @f
!@@:
!cmp ebp,0
!jne @f
!@@:
!cmp ebp,0
!jne @f
!@@:
!cmp ebp,0
!jne @f
!@@:
!cmp ebp,0
!jne @f
!@@:
EndMacro
;--------------------------------------------------------------------------------------------------
Macro ML_NOJUMP ;Macro Latenz NOJUMP, Sprung wird nicht ausgeführt
!cmp ebp,0
!je @f
!@@:
!cmp ebp,0
!je @f
!@@:
!cmp ebp,0
!je @f
!@@:
!cmp ebp,0
!je @f
!@@:
!cmp ebp,0
!je @f
!@@:
!cmp ebp,0
!je @f
!@@:
!cmp ebp,0
!je @f
!@@:
!cmp ebp,0
!je @f
!@@:
EndMacro
;==================================================================================================
Procedure LDTicks()
For i = 1 To Looping ;das Macro vom Code-Teil in den Speicher kopieren (duplizieren)
CopyMemory(CodeA, CodeMem, CodeL)
CodeMem + CodeL
Next
PokeB(CodeMem, $C3) ;zum Schluss Opcode für Return setzen
M_XMM_XMM_Z() ;um ungültige Werte in den XMM-Registern zu vermeiden (z.B. NaN)
!mov ebp,123456789 ;z.B. für Reg32-Reg32 definierter (Anfangs-)Wert für EBP
Ticks = 10000.0 ;irgend ein rel. hoher Wert
FlushInstructionCache_(GetCurrentProcess_(), #Null, #Null) ;(bisherigen) Befehls-Cache löschen
!cpuid ;für Serialisierung (Pipe(s) leerfegen)
For i = 0 To 25
!rdtsc ;Time-Stamp auslesen
!mov dword[v_TimeA],eax ;EAX = Low-DWord; diese Ticks drücken wir in den Skat
!mov dword[v_TimeA+4],edx;EDX = High-DWord
!call [v_CodeMemUr] ;Code im Speicher ausführen
!rdtsc
!mov dword[v_TimeE],eax
!mov dword[v_TimeE+4],edx
TicksZ = (TimeE - TimeA) / (Looping * 8) ;8 = Anzahl der Befehle pro Macro
If TicksZ < Ticks
Ticks = TicksZ ;der kleinste Wert wird benötigt
EndIf
Next
EndProcedure
Helle
Edit: 26.08.2008: REG32_IMMFEST hinzugefügt