[GD-Windows] RE: [Algorithms] calibrating the TSC
Brought to you by:
vexxed72
From: Jon W. <hp...@mi...> - 2004-05-04 23:01:56
|
I wrote up the problems with these timers at http://www.mindcontrol.org/~hplus/pc-timers.html a long time ago, it might be of some service. We use QueryPerformanceCounter()/QueryPerformanceFrequency() to get the initial two measurements, putting a Sleep(50) in the middle, and looping back if QPC says we slept for more than 200 milliseconds. There's a watch-dog, so after 5 tries, it gives up, and accepts whatever numbers we got as true. Also, the QPC call itself isn't allowed to take more than some number of RDTSC cycles (I think we settled on 100,000) to avoid pre-emption or interrupts during the timing from throwing us off. As I've said before on this list, we use rdtsc during intra-frame measurements, but once a second or so, we re-calibrate the timers by calling timeGetTime() and QueryPerformanceCounter() to vote about who slipped the least, and update the baseline. We also use these measurements to update the estimate for CPU frequency. We use the highest CPU frequency ever detected, because of SpeedStep; this means that during CPU idle, time using RDTSC will advance more slowly, and then skip to catch up when we next re-calibrate the clock. For us, this is better than sometimes returning time values that are ahead, because the CPU slowed down and we don't know it yet. No, there are no good real-time timers on current laptops. The next generation of chip sets will support the "advanced timer" feature, which will hopefully make this better -- but that was the idea with the PCI timers (QPC), too, and bugs in implementation made them much less useful than they should have been. Thus, the code looks something like: void read_counters( __int64 * otsc, __int64 * opc ) { __int64 rdtsc_a, rdtsc_b; __int64 pca; int cnt = 0; again: rdtsc_a = rdtsc(); QueryPerformanceCounter( &pca ); rdtsc_b = rdtsc(); if( rdtsc_b - rdtsc_a > READING_THRESHOLD && cnt++ < 5 ) goto again; *otsc = (rdtsc_a + rdtsc_b)/2; *opc = pca; } __int64 calibrate_rdtsc() { __int64 pca, pcb, pcf, tsca, tscb; double interval; QueryPerformanceFrequency( &pcf ); for( int ix = 0; ix < 5; ++ix ) { read_counters( &tsca, &pca ); Sleep( 50 ); read_counters( &tscb, &pcb ); interval = double(pcb-pca)/double(pcf); if( interval < 0.2 ) { break; } } return (tscb-tsca) / interval; } -----Original Message----- From: gda...@li... [mailto:gda...@li...]On Behalf Of Charles Bloom Sent: Monday, May 03, 2004 9:48 PM To: gda...@li... Subject: [Algorithms] calibrating the TSC On the PC you have do this horrible thing to calibrate the TSC where you do a timeGetTime then stall a while and take the time again and look at the difference in clocks & real-time. You have to do this for a second or more to get an accurate measure. Is there a better standard way to do this now? Is there any kind of tsc rate counter you can get that's reliable, like by doing cpuid and look at the mhz or something? ---------------------------------------------------------------------------- ---------------- Charles Bloom email "cb" http://www.cbloom.com ------------------------------------------------------- This SF.Net email is sponsored by: Oracle 10g Get certified on the hottest thing ever to hit the market... Oracle 10g. Take an Oracle 10g class now, and we'll give you the exam FREE. http://ads.osdn.com/?ad_id=3149&alloc_id=8166&op=click _______________________________________________ GDAlgorithms-list mailing list GDA...@li... https://lists.sourceforge.net/lists/listinfo/gdalgorithms-list Archives: http://sourceforge.net/mailarchive/forum.php?forum_id=6188 |