From: Stephen t. <st...@to...> - 2004-10-22 23:21:08
|
On Fri, 2004-10-22 at 17:54, Mike Melanson wrote: > Stephen torri wrote: > > Here is a simple program that grabs a time stamp from the TSC. > > Yes, I know all about the TSC register. There is not much to it, just > call the 'rdtsc' instruction to get the 64-bit tick count since the CPU > powered on. However, just knowing that n ticks have transpired since the > counter was last read is hardly adequate for keeping time. How do we > know precisely how many ticks transpire in a second? Well we both know that the math for this is to take a second and divide it by the frequency of the machine. What is better is to take a period of time (N seconds) and measure the cpu tick at the start and a cpu tick. I found some code on the net that does that but I fixed it so that it works correctly. The code reports for me the following after a 1 and 10 second test: CPU Frequency: 451023079.0000 hz (451.0231 Mhz) # of ticks in a 1 period: 451023031 ticks CPU Frequency: 451022581.2000 hz (451.0226 Mhz) # of ticks in a 10 period: 4510225763 ticks I believe the accuracy can only be improved by finding any bugs in what I modified. Run it on your machine and tell me the results: Stephen -------------- #include <asm/msr.h> #include <inttypes.h> #include <sys/time.h> struct cpu_data { double frequency; uint64_t ticks_per_sec; }; typedef struct cpu_data cpu_data_t; uint64_t get_timestamp (void) { uint64_t time; rdtscll(time); return time; } // Return time in usecs uint64_t timeGetTime( void ) { //=================================================== // Using Linux Time Functions To Determine Time //=================================================== struct timeval tv; gettimeofday( &tv, 0 ); uint64_t time = (tv.tv_sec * 1000000) + tv.tv_usec; } /************** * Code influed by code found at * http://www.devmaster.net/forums/lofiversion/index.php?t369.html * * Written by zenogais on Aug 9 2004, 09:34 AM * * The prinicple algorithm of zenogais's code was used by modified * to calculate time with microseconds rather than seconds. **************/ cpu_data_t measureCPU (uint32_t nTime) { //=================================================== // Check If Process Time Stamp Counter Is Supported //=================================================== uint64_t timeStart, timeStop; uint64_t startTick, endTick; uint64_t overhead, ovhd_start, ovhd_end; //=================================================== // Calculate CPU Tick Function Call Overhead //=================================================== ovhd_start = get_timestamp (); ovhd_end = get_timestamp (); overhead = ovhd_end - ovhd_start; //=================================================== // Calculate Starting Time And Start Tick //=================================================== timeStart = timeGetTime(); while(timeGetTime() == timeStart) { timeStart = timeGetTime(); } // Wait 1 second before starting the measurement. while(1) { timeStop = timeGetTime(); if((timeStop - timeStart) > 1000000) { startTick = get_timestamp(); break; } } //=================================================== // Calculate Stop Time And End Tick //=================================================== timeStart = timeStop; while(1) { timeStop = timeGetTime(); if((timeStop - timeStart) > (nTime * 1000000)) { endTick = get_timestamp(); break; } } //=================================================== // Return The Processors Speed In Hertz //=================================================== cpu_data_t data; data.frequency = ((double)((endTick - startTick) + overhead)) / nTime ; data.ticks_per_sec = (endTick - startTick) / nTime; printf("CPU Frequency: %.4f hz (%.4f Mhz)", data.frequency, (data.frequency/1000000)); printf(" # of ticks in a %li period: %llu ticks\n", nTime, (endTick - startTick)); return data; } int main () { // Check the CPU frequency (1 second collection period) cpu_data_t cpu; cpu = measureCPU(1); cpu = measureCPU(10); return 0; } -- Email: st...@to... |