__rdtsc frequency
Using rdtsc is a bad idea in general (there are a lot of pitfalls). On Windows QueryPerformanceCounter and QueryPerformanceFrequency are your best bet, it's the easiest thing to use and works on multi-core systems.
If you must, then you can wait for a known length of time (Using Sleep() or something) and call rdtsc before and after it. Although Sleep() isn't incredibly accurate.
Alternatively, read it from the registry:
Although that's just an estimate (So is what you'd get with Sleep()).
DWORD CalculateCPUSpeed(){DWORD dwTimerLo, dwTimerHi;const DWORD dwDelay = 500; // We want absolute maximum priority DWORD dwPriorityClass = GetPriorityClass(GetCurrentProcess()); int nPriority = GetThreadPriority(GetCurrentThread()); SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS); SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL); Sleep(0); // Give up the rest of our timeslice so we don't get a context switch // Get the current time stamp counter __asm { rdtsc mov dwTimerLo, eax mov dwTimerHi, edx } // Sleep for a while Sleep(dwDelay); // Get the elapsed time __asm { rdtsc sub eax, dwTimerLo sbb edx, dwTimerHi mov dwTimerLo, eax mov dwTimerHi, edx } // Reset priority and get speed SetThreadPriority(GetCurrentThread(),nPriority); SetPriorityClass(GetCurrentProcess(),dwPriorityClass); return dwTimerLo / (1000*dwDelay);}
Alternatively, read it from the registry:
DWORD ReadCPUSpeedFromRegistry(){HKEY hKey;DWORD dwSpeed; // Open the key if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\",0, KEY_QUERY_VALUE,&hKey) != ERROR_SUCCESS) { return 0; } // Read the value DWORD dwLen = 4; if(RegQueryValueEx(hKey,"~MHz",NULL,NULL,(LPBYTE)&dwSpeed,&dwLen) != ERROR_SUCCESS) { RegCloseKey(hKey); return 0; } // Cleanup and return RegCloseKey(hKey); return dwSpeed;}
Although that's just an estimate (So is what you'd get with Sleep()).
While not a direct answer to your question, I think this is a very good read:
Game Timing and Multicore Processors. Basically if you're intending your timing to also work on multicore targets, don't use RDTSC.
Game Timing and Multicore Processors. Basically if you're intending your timing to also work on multicore targets, don't use RDTSC.
It seems not to be a good idea but you can do that on intel
( it will give you an approximation of the cpu proc using rdtsc ).
good luck [rolleyes]
( it will give you an approximation of the cpu proc using rdtsc ).
#include <iostream>#include <cstdlib>using namespace std ;static unsigned int hi = 0;static unsigned int lo = 0;void set_asm_counter( unsigned & hi , unsigned int & lo ){ __asm__ ( " rdtsc ; movl %%edx , %0 ; movl %%eax , %1" : "=r" (hi) , "=r" (lo) : :"%edx","%eax" );}double get_asm_counter(const unsigned & hi_old , const unsigned & lo_old){ unsigned int new_hi = 0 ; unsigned int new_lo = 0 ; set_asm_counter(new_hi,new_lo) ; unsigned int diff_hi = new_hi - hi_old ; unsigned int diff_lo = new_lo - lo_old ; unsigned int overflow_lo = lo_old > diff_lo ; diff_hi -= overflow_lo ; return static_cast<double> (diff_hi) * ( 0x1 << 30 ) * 4 + static_cast<double>(diff_lo ) ;}// purpose of main is here to give you a approximation of the proc freq int main(int argc,char * argv[]){ double res = 0 ;// = get_asm_counter(hi,lo) ; set_asm_counter(hi,lo) ; cout << " timing value = " << res << endl ; sleep(1) ; res = get_asm_counter(hi,lo) ; cout << " timing value = " << res << endl ; return EXIT_SUCCESS ;}
good luck [rolleyes]
Check on www.intel.com for a doc on getting the cpu speed in MHZ.
That's what you need to convert rdtsc-ticks to seconds (or milliseconds).
rdtsc is not dualcore safe - but with a little effort can be made safe (I'm
using it on various machines, including amd 64 x2, intel-dualcore and
intel-HT)
It's a bit easier to use QueryPerformanceCounter, it will work with the
latest winXp patch installed (small patch released after sp2 if I remember
correctly), no idea about support for win2k though) - beware that not
everyone has this patch installed though!
rdtsc and queryPerformanceCounter are NOT speedstep-safe - you have to add
some additional code to see if the frequency changed (or ignore it -
especially laptops will have problem then, but speedstep is also coming
to the desktop pc's now).
That's what you need to convert rdtsc-ticks to seconds (or milliseconds).
rdtsc is not dualcore safe - but with a little effort can be made safe (I'm
using it on various machines, including amd 64 x2, intel-dualcore and
intel-HT)
It's a bit easier to use QueryPerformanceCounter, it will work with the
latest winXp patch installed (small patch released after sp2 if I remember
correctly), no idea about support for win2k though) - beware that not
everyone has this patch installed though!
rdtsc and queryPerformanceCounter are NOT speedstep-safe - you have to add
some additional code to see if the frequency changed (or ignore it -
especially laptops will have problem then, but speedstep is also coming
to the desktop pc's now).
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement