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
|