CPU-Latenz-Durchsatz-Messung

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.
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

CPU-Latenz-Durchsatz-Messung

Beitrag von Helle »

Es ist sicher nicht nur für Assembler-Programmierer interessant, wie schnell denn ein bestimmter Befehl von der verfügbaren CPU abgearbeitet wird. Zur Messung von Latenz und Durchsatz dient nachfolgendes Programm, das sich beliebig erweitern lässt (weitere Kombinationen).
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
Die benötigte PBI-Datei:

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
Gruß
Helle

Edit: 26.08.2008: REG32_IMMFEST hinzugefügt
Zuletzt geändert von Helle am 26.08.2008 09:34, insgesamt 1-mal geändert.
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Cool :allright:
Sowas ähnliches hatte ich auch mal gemacht aber simpler im Umfang und komplizierter in der Umsetzung. :freak:

Thx, kann das gut gebrauchen.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Habe auf http://www.mdcc-fun.de/k.helbing/CPU-Latenz/ eine DeLuxe-( :mrgreen: )Version bereitgestellt (5.3kB ZIP). Auszuführen ist Start.pb. Diese "manipuliert" dann die eigentliche Haupt-Datei.

Gruß
Helle
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Unter o.g. Link liegt eine komplett neue Version bereit. Es wird jetzt automatisch eine Liste mit vielen Befehls-Kombinationen erzeugt (keine manuelle Eingabe mehr). Erweiterungen sind leicht im Code nachzutragen.

Gruß
Helle
Antworten