CPU clock speed
#1
Posted 11 July 2003 - 12:47 PM
I need some help, ¿ someone knows how to obtain the CPU clock speed ( Programing WinX ) ? I think that Win32API don't have a api function to resolve it, but i saw very much programs that obtain it.
Thanks.
#2
Posted 11 July 2003 - 04:49 PM
#include <stdio.h>
#include <windows.h>
DWORD GetCPUSpeed();
int main() {
DWORD TheSpeed;
if (TheSpeed = GetCPUSpeed())
printf("CPU Speed: %u MHz\n", TheSpeed);
else
printf("Your hardware does not support a high-resolution counter.\n");
return 0;
}
DWORD GetCPUSpeed() {
LARGE_INTEGER ulFreq, ulTicks, ulValue, ulStartCounter, ulEAX_EDX;
// Query for high-resolution counter frequency (this is not the CPU frequency):
if (QueryPerformanceFrequency(&ulFreq)) {
// Query current value:
QueryPerformanceCounter(&ulTicks);
// Calculate end value (one second interval); this is (current + frequency)
ulValue.QuadPart = ulTicks.QuadPart + ulFreq.QuadPart;
// Read CPU time-stamp counter:
__asm RDTSC
// And save in ulEAX_EDX:
__asm mov ulEAX_EDX.LowPart, EAX
__asm mov ulEAX_EDX.HighPart, EDX
// Store starting counter value:
ulStartCounter.QuadPart = ulEAX_EDX.QuadPart;
// Loop for one second (measured with the high-resolution counter):
do {
QueryPerformanceCounter(&ulTicks);
} while (ulTicks.QuadPart <= ulValue.QuadPart);
// Now again read CPU time-stamp counter:
__asm RDTSC
// And save:
__asm mov ulEAX_EDX.LowPart, EAX
__asm mov ulEAX_EDX.HighPart, EDX
// Calculate number of cycles done in interval; 1000000 Hz = 1 MHz
return (DWORD) ((ulEAX_EDX.QuadPart - ulStartCounter.QuadPart) / 1000000);
} else {
// No high-resolution counter present:
return 0;
}
}
#3
Posted 11 July 2003 - 05:24 PM
by dividing through some value, we can make it run much faster (1sec is so slow... at least, to just wait and do nothing..)
..ulValue.QuadPart = ulTicks.QuadPart + ulFreq.QuadPart/16;..
..return (DWORD)((ulEAX_EDX.QuadPart - ulStartCounter.QuadPart)*16/1000000);..
for example.. i tested it by dividing trough 256, and still got 2209 MHz.. and you could call it 256 times per second.. quite fine, not?..
just a suggestion..
you should store the value in the end anyways, and use it directly.. if you need to.
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
#4
Posted 15 July 2003 - 08:27 AM
Maybe u can explain me how works 'rdtsc' instruction, my assembler is old ( 8086 :P ).
I need to bring up to date about asm, some URL, pdf ?
thanks.
#5
Posted 15 July 2003 - 08:31 AM
Quote
Mnemonic: RDTSC
Opcode : 0F 31
Bug in : Poorly documented for Pentium Processor
Function:
RDTSC reads a Pentium internal 64 bit register which is being incremented
from 0000 0000 0000 0000 at every CPU internal clockcycle. Note that this
gives a clockcycle-accurate timer with a range of more than 8800 years at
66 Mhz...
The instruction places the counter in the EDX:EAX register pair.
source
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
#6
Posted 30 July 2003 - 06:51 AM
#include <limits.h>
#include <time.h>
static const unsigned g_uClocksPerSec = CLOCKS_PER_SEC;
#if UINT_MAX == 0xFFFFFFFF
typedef unsigned uint32_t;
#else
#error can't define uint32_t
#endif
uint32_t __declspec(naked) GetCPUSpeed(void)
{
_asm
{
push ebp
call clock
mov ebp, eax
clock_align:
call clock
cmp ebp, eax
je clock_align
mov ebp, eax
rdtsc
push eax
push edx
clock_wait:
call clock
cmp ebp, eax
je clock_wait
//calculate speed
sub eax, ebp
mul g_uClocksPerSec
xchg eax, ebx
rdtsc
pop ecx
sub edx, ecx
pop ecx
sub eax, ecx
div ebx
pop ebp
ret
}
}
It doesn't require highperformance counters and at least for me it retains the
same accurcy. Also if you split it up so you put the prototype in one file and the
implementation in a seprate file the static keywords effectivly gets rid of the global outside that unit so that won't be a problem.
#7
Posted 30 July 2003 - 08:29 AM
there are such a big amount of timers out there.. though.. :D i always loved to use timeGetTime..
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
#8
Posted 30 July 2003 - 08:56 AM
#9
Posted 30 July 2003 - 09:09 AM
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
#10
Posted 30 July 2003 - 11:22 AM
say what? the hard part about making it cross-platform is
the inline asm I guess doesn't GCC use AT&T syntax
I think the easiest part would actually be to port it over to
nasm and change the function prototype to:
uint32_t GetCPUSpeed( uint32_t (*timer_fun), uint32_t uScaleFactor);
then the user can freely choose to use clock, timeGetTime, SDL_Ticks
or whatnot, and also have full control (via his/her own timer function) over
how long time it takes to execute and precision.
Looking forward to see what you come up with
#11
Posted 30 July 2003 - 11:52 AM
hehe:D
i just write a clean version, and i'll use the sdl timer for it.. there is not much not clean here, but why not rewriting while i don't have anything else to do? :D
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
#12
Posted 30 July 2003 - 12:10 PM
But Im eagerly awaiting your new version
#13
Posted 30 July 2003 - 12:22 PM
no, sure.. but i think every modern compiler should allow __asm {} blocks. they are so handy..
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
#14
Posted 30 July 2003 - 12:25 PM
the problem being that it uses AT&T syntax
but stop posting and get working on that updated version Im curious ;)
#15
Posted 30 July 2003 - 12:40 PM
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
#16
Posted 30 July 2003 - 12:44 PM
everywhere.
In general Intel syntax look like this:
mnemoic dst, src
while AT&T looks like this:
mnemonic src, dst
most motorola assemblers tend to use the AT&T syntax GAS and GCC does
to, or at least did the last time I checked.
#17
Posted 30 July 2003 - 12:51 PM
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
#18
Posted 30 July 2003 - 01:29 PM
davepermen said:
#19
Posted 30 July 2003 - 01:41 PM
(*URGH*)
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....
#20
Posted 09 August 2004 - 04:41 PM
// Type Definitions (From Header)
#if defined(__WIN32__)
...
typedef __int32 ChipRec_s32; ///< 32 bit signed integer
typedef __int64 ChipRec_s64; ///< 64 bit signed integer
...
typedef unsigned __int32 ChipRec_u32; ///< 32 bit unsigned integer
typedef unsigned __int64 ChipRec_u64; ///< 64 bit unsigned integer
...
#elif defined(__LINUX__)
...
typedef long ChipRec_s32; ///< 32 bit signed integer
typedef long long ChipRec_s64; ///< 64 bit signed integer
...
typedef unsigned long ChipRec_u32; ///< 32 bit unsigned integer
typedef unsigned long long ChipRec_u64; ///< 64 bit unsigned integer
...
#endif
// Source File
ChipRec_s64 getCPUTick() const
{
//===================================================
// Use RDTSC To Read CPU Time Stamp Counter
//===================================================
#if defined (__WIN32__)
__asm rdtsc;
#elif defined (__LINUX__)
ChipRec_s64 s64Ret;
__asm__ __volatile__ ("rdtsc" : "=A"(s64Ret):);
return s64Ret;
#endif
}
#ifdef __LINUX__
#include <sys/time.h>
ChipRec_u32 timeGetTime( void )
{
//===================================================
// Using Linux Time Functions To Determine Time
//===================================================
struct timeval tv;
gettimeofday( &tv, 0 );
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
#endif
int getCPUSpeed(ChipRec_s32 nTime)
{
//===================================================
// Check If Process Time Stamp Counter Is Supported
//===================================================
ChipRec_s64 timeStart, timeStop;
ChipRec_s64 startTick, endTick;
ChipRec_s64 overhead;
if(!sX86ProcessorInfo.hasTimeStampCounter)
{
return 0;
}
//===================================================
// Calculate CPU Tick Function Call Overhead
//===================================================
overhead = getCPUTick() - getCPUTick();
//===================================================
// Calculate Starting Time And Start Tick
//===================================================
timeStart = timeGetTime();
while(timeGetTime() == timeStart)
{
timeStart = timeGetTime();
}
while(1)
{
timeStop = timeGetTime();
if((timeStop - timeStart) > 1)
{
startTick = getCPUTick();
break;
}
}
//===================================================
// Calculate Stop Time And End Tick
//===================================================
timeStart = timeStop;
while(1)
{
timeStop = timeGetTime();
if((timeStop - timeStart) > nTime)
{
endTick = getCPUTick();
break;
}
}
//===================================================
// Return The Processors Speed In Hertz
//===================================================
return (int)((endTick - startTick) + (overhead));
}
The variable sX86ProcessorInfo.hasTimeStampCounter is read from the processor using the CPUID instruction. It doesn't really have to be checked, as the only CPUs without the time-stamp counter, are pre-pentium chips IIRC.
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users












