News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

CPU Frequency Program

Started by dedndave, August 06, 2009, 02:10:47 AM

Previous topic - Next topic

dedndave

on one of the other threads, we were discussing how to measure CPU freq
Edgar had a routine and i wanted to test it, so i put it with a CPU enum routine and made a program
it seems to work pretty well
we'd like to know if it works for you
http://www.masm32.com/board/index.php?action=dlattach;topic=12010.0;id=6547

JayPee

Greetings From New Zealand
(Land of the Long White Cloud)

Damos

Works well for me too. Thanks.
Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius -- and a lot of courage -- to move in the opposite direction. - Albert Einstien

ecube

it works but it freezes my system everytime I grabs the speed, which isn't enjoyable. I have some C code somewhere that doesn't freeze your system and accuracy is the same I believe, i'll look for it, thanks for contributing.

dedndave

i know how to fix that
i am surprised it freezes though
if you use crt functions __kbit and __getch and get rid of my InKyb routine, it should fix it
i have been trying to find a solution to that

sinsi

Works good here, even if I switch affinity to all 4 cores. CPU usage spikes from 8% to 25% and looking at it with 'process explorer' the
priority switches between 15 and 8.

Why not a window or dialog box instead of the console?
Light travels faster than sound, that's why some people seem bright until you hear them.

dedndave

lol - i haven't got that far yet, Sinsi
i have much to learn  :'(

ecube

Problem seems to be donkeys cpu speed function.

here's 1 that doesnt freeze made by Petroizki, from this thread http://www.masm32.com/board/index.php?topic=3970.0
note I changed FREQ_DIVIDE_POWER_OF_2 to 2 from 4 as MichaelW suggested, and that fixed its slight inaccuracy.

.586
.model flat, stdcall
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\kernel32.inc
include \masm32\include\msvcrt.inc

includelib \masm32\lib\masm32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\msvcrt.lib

include \masm32\macros\macros.asm
.data
DIVIDOR REAL4 1000000.0
.data?
SPEED dq ?
.code
GetCPUSpeed proc uses ebx edi esi
LOCAL qwCycles:QWORD, qwTimer:QWORD
LOCAL dwPriority:DWORD, hProcess:HANDLE

FREQ_DIVIDE_POWER_OF_2 EQU <2>

lea ebx, [qwTimer]

invoke GetCurrentProcess
mov hProcess, eax
invoke GetPriorityClass, eax
mov dwPriority, eax
invoke SetPriorityClass, hProcess, HIGH_PRIORITY_CLASS

invoke QueryPerformanceFrequency, ebx
test eax, eax
jz @no_timer

mov esi, dword ptr [ebx + 4]
mov edi, dword ptr [ebx]

mov eax, esi
shr edi, FREQ_DIVIDE_POWER_OF_2
shl eax, 32-FREQ_DIVIDE_POWER_OF_2
shr esi, FREQ_DIVIDE_POWER_OF_2
or edi, eax

push ebx
rdtsc
mov dword ptr [qwCycles], eax
mov dword ptr [qwCycles + 4], edx

call QueryPerformanceCounter
add edi, dword ptr [ebx]
adc esi, dword ptr [ebx + 4]

@@: invoke QueryPerformanceCounter, ebx
cmp esi, dword ptr [ebx + 4]
jb @F
cmp edi, dword ptr [ebx]
jnb @B

@@: rdtsc

sub eax, dword ptr [qwCycles]
sbb edx, dword ptr [qwCycles + 4]

mov ecx, eax
shl edx, FREQ_DIVIDE_POWER_OF_2
shr ecx, 32-FREQ_DIVIDE_POWER_OF_2
shl eax, FREQ_DIVIDE_POWER_OF_2
or edx, ecx

mov edi, eax
mov esi, edx

invoke SetPriorityClass, hProcess, dwPriority

mov eax, edi
mov edx, esi

@no_timer:
ret
GetCPUSpeed endp

start:
print chr$("CPU Speed: ")
invoke GetCPUSpeed

mov dword ptr [SPEED], eax
mov dword ptr [SPEED + 4], edx

fild qword ptr [SPEED]
fdiv dword ptr [DIVIDOR]

fstp qword ptr [SPEED]

mov eax, dword ptr [SPEED]
mov edx, dword ptr [SPEED + 4]

invoke crt_printf,chr$("%.2f MHz%c"),edx::eax,10

inkey chr$(13,10,"Press any key to exit...")

ret
end start

dedndave

i suppose it could be adopted to plug into our current program to test it
we could also replace InKyb with __kbhit and __getch to be on the safe side
you want to do that E^cube - or would you like me to ?

i had formulated another plan for running the measurement, but Edgar's seemed to work
the thing about Edgar's code is, it runs QueryPerformanceCounter in a loop to wait for time to elapse
that hogs CPU time
my plan was to use Sleep to consume the time (which allows the system to execute other code)
then, place a QueryPerformanceCounter before and after the Sleep to get the time (accurate measurement of time)
kind of a "hybrid" approach

initialization
1) use GetProcessAffinityMask, GetPriorityClass, and GetThreadPriority to save the initial settings
2) use pushfd/popfd to test bit 21 of the eflags register to verify the cpu supports cpuid
3) test cpuid function 1, edx bit 4 to verify the cpu supports rdtsc
4) test the rdtsc to verify it updates
5) use QueryPerformanceFrequency to get the frequency of the performance counter

measurement
1) use SetProcessAffinityMask to select core 0
2) use SetPriorityClass and SetThreadPriority as Edgar suggested to elevate priority
3) use cpuid function 0 to serialize instructions
4) use rdtsc to get an initial clock count (save values on the stack)
5) use QueryPerfmanceCounter to get the start time (save values on the stack)
6) use Sleep to consume some specific amount of linear time
7) use cpuid function 0 to serialize instructions
8) use rdtsc to get a terminal clock count (save values on the stack)
9) use QueryPerfmanceCounter to get the stop time (save values on the stack)
10) set thread and process priority back to initial settings
11) set affinity back to initial setting
12) recall the values from the stack

i was going to run the measurement steps repeatedly, alternating between short and long Sleep periods
then, and use the deltas to calculate frequency
it should provide great accuracy; as good as can be obtained by this type of measurement/calculation, i suspect

jj2007

Quote from: E^cube on August 06, 2009, 09:44:14 AM
here's 1 that doesnt freeze made by Petroizki

CPU Speed: 1600.07 MHz

Works fine but only after I replaced all the includes on top with
include \masm32\include\masm32rt.inc
.586

With the includes by Petroizki, I get loads of error messages, e.g.

\masm32\include\windows.inc(129) : error A2004:symbol type conflict : bool
BOOL typedef DWORD

\masm32\include\windows.inc(7804) : error A2179:structure improperly initialized
SYSTEM_AUDIT_ACE STRUCT
  Header    ACE_HEADER <>
  imask     DWORD      ?
  SidStart  DWORD      ?
SYSTEM_AUDIT_ACE ENDS

bruce1948


Slugsnack

works nicely, calculates speed of one of the cores quite accurately but does take like 30% CPU

GregL

Quoteit works but it freezes my system everytime I grabs the speed, which isn't enjoyable.

It's doing this to me too, but not every time, just once in a while.


Slugsnack

oh i'm guessing it's not freezing my system cause i'm on dual-core but i'm experiencing similar effects. 1 core being almost completely maxed and lagging up the whole system but not to the point of freezing as it would on single-core

GregL

Slugsnack,

Well, by freezing I mean maxing out the CPU to where nothing is happening in other programs. I just happened to have some video running when I ran the program and it froze and stuttered for a second or two. I have a dual-core too.