Code-Beispiel
Counter.Bas von MichaelW
Lizenz: | Erster Autor: | Letzte Bearbeitung: |
k. A. | ytwinky | 14.01.2015 |
Hier finden Sie neuere Macros: Neue "Cycle count macros for 32 and 64-bit code"
''=============================================================================
#Include "windows.bi"
''=============================================================================
Dim Shared As LongInt counter_cycles
Dim Shared As Integer _counter_loopcount_, _counter_loopcounter_
Dim Shared As Integer _process_priority_class_, _thread_priority_
#Macro COUNTER_BEGIN( loop_count, process_priority, thread_priority )
_counter_loopcount_ = loop_count
_process_priority_class_ = GetPriorityClass(GetCurrentProcess())
_thread_priority_ = GetThreadPriority(GetCurrentProcess())
SetPriorityClass(GetCurrentProcess(), process_priority)
SetThreadPriority(GetCurrentProcess(), thread_priority)
_counter_loopcounter_ = _counter_loopcount_
Asm
Xor eax, eax
cpuid '' serialize
rdtsc '' get reference loop start count
push edx '' preserve msd (most significant dword)
push eax '' preserve lsd
Xor eax, eax
cpuid '' serialize
.balign 16
0: '' start of reference loop
Sub DWORD Ptr _counter_loopcounter_, 1
jnz 0b '' end of reference loop
Xor eax, eax
cpuid '' serialize
rdtsc '' get reference loop end count
pop ecx '' recover lsd of start count
Sub eax, ecx '' calc lsd of reference loop count
pop ecx '' recover msd of start count
sbb edx, ecx '' calc msd of reference loop count
push edx '' preserve msd of reference loop count
push eax '' preserve lsd of reference loop count
Xor eax, eax
cpuid '' serialize
rdtsc '' get test loop start count
push edx '' preserve msd
push eax '' preserve lsd
End Asm
_counter_loopcounter_ = _counter_loopcount_
Asm
Xor eax, eax
cpuid '' serialize
.balign 16
1: '' start of test loop
End Asm
#EndMacro
''=============================================================================
#Macro COUNTER_END()
Asm
Sub DWORD Ptr _counter_loopcounter_, 1
jnz 1b '' end of test loop
Xor eax, eax
cpuid '' serialize
rdtsc
pop ecx '' recover lsd of start count
Sub eax, ecx '' calc lsd of test loop count
pop ecx '' recover msd of start count
sbb edx, ecx '' calc msd of test loop count
pop ecx '' recover lsd of reference loop count
Sub eax, ecx '' calc lsd of corrected loop count
pop ecx '' recover msd of reference loop count
sbb edx, ecx '' calc msd of corrected loop count
mov DWORD Ptr [counter_cycles], eax
mov DWORD Ptr [counter_cycles+4], edx
End Asm
SetPriorityClass(GetCurrentProcess(),_process_priority_class_)
SetThreadPriority(GetCurrentProcess(),_thread_priority_)
counter_cycles /= _counter_loopcount_
#EndMacro
''=============================================================================
Alte Version:
'====================================================================
'' The COUNTER_BEGIN and COUNTER_END macros provide a convenient
'' method of measuring the processor clock cycle count for a block
'' of code. These macros must be called in pairs, and the block of
'' code must be placed in between the COUNTER_BEGIN and COUNTER_END
'' macro calls. The clock cycle count for a single loop through the
'' block of code, corrected for the test loop overhead, is returned
'' in the shared variable COUNTER_CYCLES.
''
'' These macros capture the lowest cycle count that occurs in a
'' single loop through the block of code, on the assumption that
'' the lowest count is the correct count. The higher counts that
'' occur are the result of one or more context switches within the
'' loop. Context switches can occur at the end of a time slice, so
'' to minimize the possibility of the loop overlapping the time
'' slice the COUNTER_BEGIN macro starts a new time slice at the
'' beginning of the loop. If the execution time for a single loop
'' is greater than the duration of a time slice (approximately 20ms
'' under Windows), then the loop will overlap the time slice, and
'' if another thread of equal priority is ready to run, then a
'' context switch will occur.
''
'' A higher-priority thread can “preempt” a lower priority thread,
'' causing a context switch to occur before the end the time slice.
'' Raising the priority of the process (thread) can reduce the
'' frequency of these context switches. To do so, specify a higher
'' than normal priority class in the priority_class parameter of
'' the COUNTER_BEGIN macro. REALTIME_PRIORITY_CLASS specifies the
'' highest possible priority, but using it involves some risk,
'' because your process will preempt *all* other processes,
'' including critical Windows processes, and if the timed code
'' takes too long to execute then Windows may hang, even the NT
'' versions. HIGH_PRIORITY_CLASS is a safer alternative that in
'' most cases will produce the same cycle count.
''
'' You can avoid the bulk of the context switches by simply
'' inserting a few second delay in front of the first macro
'' call, to allow the system disk cache activity to subside.
''
'' For the loop_count parameter of the COUNTER_BEGIN macro, larger
'' values increase the number of samples and so tend to improve
'' the consistency of the returned cycle counts, but in most cases
'' you are unlikely to see any improvement beyond a value of about
'' 1000.
''
'' Note that the block of code must be able to withstand repeated
'' looping, and that this method will not work for timing a loop
'' because the lowest cycle count that occurs will be when the
'' loop falls through.
''
'' These macros require a Pentium-class processor that supports
'' the CPUID (function 0 only) and RDTSC instructions.
'====================================================================
#include once "windows.bi"
Dim Shared _counter_tsc1_ As Ulongint, _counter_tsc2_ As Ulongint
Dim Shared _counter_overhead_ As Ulongint, counter_cycles As Ulongint
Dim Shared _counter_loop_counter_ As Uinteger
Sub _counter_code1_
asm
'
' Use same CPUID input value for each call.
'
Xor eax, eax
'
' Flush pipe and wait for pending ops to finish.
'
cpuid
'
' Read Time Stamp Counter.
'
rdtsc
'
' Save count.
'
mov [_counter_tsc1_], eax
mov [_counter_tsc1_+4], edx
End asm
End Sub
Sub _counter_code2_
asm
Xor eax, eax
cpuid
rdtsc
mov [_counter_tsc2_], eax
mov [_counter_tsc2_+4], edx
End asm
End Sub
'' Unlike the #define directive, the #macro directive
'' allows inline asm.
''
#macro COUNTER_BEGIN( loop_count, priority_class )
_counter_overhead_ = 2000000000
counter_cycles = 2000000000
SetPriorityClass( GetCurrentProcess(), priority_class )
Sleep_(0) '' Start a new time slice
''
'' The nops compensate for the 10-byte instruction (that
'' initializes _counter_loop_counter_) between the alignment
'' directive and the loop label, which ideally needs to be
'' aligned on a 16-byte boundary.
''
asm
.balign 16
nop
nop
nop
nop
nop
nop
End asm
For _counter_loop_counter_ = 1 To loop_count
_counter_code1_
_counter_code2_
If (_counter_tsc2_ - _counter_tsc1_) < _counter_overhead_ Then
_counter_overhead_ = _counter_tsc2_ - _counter_tsc1_
Endif
Next
Sleep_(0) '' Start a new time slice
asm
.balign 16
nop
nop
nop
nop
nop
nop
End asm
For _counter_loop_counter_ = 1 To loop_count
_counter_code1_
#endmacro
''
'' *** Note the open FOR loop ***
''
#define COUNTER_END _
_counter_code2_ :_
If (_counter_tsc2_ - _counter_tsc1_) < counter_cycles Then :_
counter_cycles = _counter_tsc2_ - _counter_tsc1_ :_
Endif :_
Next :_
SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS ) :_
counter_cycles -= _counter_overhead_
Zusätzliche Informationen und Funktionen | |||||||
---|---|---|---|---|---|---|---|
|