EntropySink
Technical & Scientific => Programming => Topic started by: Ken Fitlike on April 08, 2005, 09:09:21 PM
-
I was fiddling around with timers for some original reason that I've since forgotten - something to do with trying to find something accurate for both windows and linux but I think that platform specific solutions are probably better (QueryPerformanceCounter and QueryPerformanceFrequency for windows, gettimeofday for linux). Anyway for what it's worth, I did this which sort of does a cpu speed check but is not too accurate.
/*---------------------------------------------------------------------------*/
/*
CPU SPEED using RDTSC asm instruction
copyright (c) Ken Fitlike 2005
Free to good home
Disclaimer: Any problems you have with this code are just that:
your problems.
Notes:
Function overhead seems insignificant when calculating cpu speed but should,
ideally, be corrected for when attempting to use the highest resolution timer
possible with this approach. The testing was not exhaustive ie. was limited
to a single machine.
Rejecting the lower 25% of multiple results of GetCPUSpeed results in a
slight improvement in cpu speed accuracy when compared with, eg. results
from wcpuid.
RDTSC is non-serialising ie. it may not wait for all previous instructions
to execute and may begin subsequent instructions prior to reading the
counter. Thus, before its use the seralising cpuid is called; since the
first call to cpuid is documented as slower than subsequent ones, three
calls are made in an effort to 'normalise' behaviour.
*/
/*---------------------------------------------------------------------------*/
#include
#include
/*---------------------------------------------------------------------------*/
long long GetCPUSpeed()
{
unsigned int hiLowPart=0,hiHighPart=0;
unsigned int loLowPart=0,loHighPart=0;
unsigned long long start=0,end=0;
double t=0;
clock_t timer_start=0,timer_stop=0;
__asm__ ("xor %eax, %eax");
__asm__ ("xor %ebx, %ebx");
__asm__ ("xor %ecx, %ecx");
__asm__ ("xor %edx, %edx");
__asm__ ("cpuid");
__asm__ ("cpuid");
__asm__ ("cpuid");
__asm__ ("rdtsc": "=a"(hiLowPart), "=d"(hiHighPart));
timer_start=clock();
for (;;)
{
timer_stop=clock();
if ((timer_stop-timer_start)>CLOCKS_PER_SEC) /*1 second*/
{
__asm__ ("xor %eax, %eax");
__asm__ ("xor %ebx, %ebx");
__asm__ ("xor %ecx, %ecx");
__asm__ ("xor %edx, %edx");
__asm__ ("cpuid");
__asm__ ("cpuid");
__asm__ ("cpuid");
__asm__ ("rdtsc": "=a"(loLowPart), "=d"(loHighPart));
break;
}
}
/*this gets a more precise measure of that '1 second' interval above*/
t=(double)(timer_stop-timer_start)/(double)CLOCKS_PER_SEC;
start|=hiHighPart;
start<<=32;
start|=hiLowPart;
end|=loHighPart;
end<<=32;
end|=loLowPart;
/*ensure no div-by-zero error*/
t=t!=0?t:1;
return (end - start)/(unsigned long long)(1000000*t);
}
/*---------------------------------------------------------------------------*/
int main()
{
int i;
const int NUM=20;
long long speed=0,mean_speed=0;
printf("CPU Speed\n\n");
printf("%s%u\n\n","CLOCKS_PER_SEC: ",(unsigned int)CLOCKS_PER_SEC);
for (i=NUM;i>0;--i)
{
speed=GetCPUSpeed();
mean_speed+=speed;
printf("%d%s\n",(int)speed," MHz");
}
printf("%s%d\n","Average cpu speed: ",(int)(mean_speed/NUM));
return 0;
}
/*---------------------------------------------------------------------------*/
-
What compiler did you use for this?
-
gcc.