0

I implemented a fast function which returns time (using rdtsc), let's call it fast_time(). I have for reference the original function which uses a system call, let's call it system_time(). My program uses fast_time() but in a separate thread I'm constantly running a while loop to check if the difference between the time returned from the my function and the original function is greater than a predefined threshold. Something like

while (true)
{
    if (abs((fast_time() - system_time()).microseconds()) > MICROSECONDS_THRESHOLD)
    {
        report error
    }
}

Usually I don't see errors but sometimes I do get them and I would like to understand this problem better. My first suspicion is that the call to system_time() doesn't happen immediately after fast_time() returns. How can I force the program to execute fast_time() - system_time() "atomically" as possible?

e271p314
  • 3,841
  • 7
  • 36
  • 61
  • Hi before I answer, do you have your code locked to a single CPU? It's okay if you don't know what that means, just tells me where to start the explanation :-) – Ahmed Masud Jun 22 '14 at 13:04
  • 2
    Unless you are running on a real-time kernel (and linux isn't) you don't get any guarantees of how often your software is scheduled to run, nor you can know if the threads will run on the same core taking turns, or on different cores. Normally it's completely up to the OS. – LtWorf Jun 22 '14 at 13:11
  • @LtWorf actually Linux DOES have a real-time scheduler in it if you choose to use it, and in his particular case on a multi-core CPU he can lock his thread to a CORE and get the results he's looking for. – Ahmed Masud Jun 22 '14 at 13:17
  • I lock the thread which to a single core with `sched_setaffinity`, and yes, I'm aware of that I don't get a guarantees for the scheduling (I don't use real-time kernel), my question is, what is the best thing I can do to fix this? – e271p314 Jun 22 '14 at 13:19
  • 2
    What do you want to achieve with the test? Is it a test for the `fast_time` implementation that you compare with the `system_time` that you trust? – harper Jun 22 '14 at 13:39
  • When you want to verify that `fast_time` doesn't diverge you should do somehting like: `t1=fast_time(); t2=system_time(); t3=fast_time(); assert((t2-t1)>=0 && (t3-t2)>=0);` If you need it you can make the assert condition a little bit harder. – harper Jun 22 '14 at 13:41
  • @harper, yes, I do this to make sure `fast_time` is close to `system_time`. The test you suggested is too easy and it is possible that `fast_time` returns 10 micro less than `system_time` and I won't know this. I need the test to include a maximal threshold so I will know what is the resolution of the time function I wrote – e271p314 Jun 22 '14 at 13:54
  • Chane the test condition. But calling system-time twiceallows detecting thread switching. – harper Jun 22 '14 at 13:57

1 Answers1

2

rdtsc is inherently unreliable way to measure real-time for couple of reasons:

1) each HW thread will return different values thus if your thread isn't locked to one HW thread you get different values. So the time may unexpectedly jump back and forth depending on how OS schedules the thread

And more importantly:

2) CPU throttling can cause the frequency of the CPU to change unexpectedly. Because rdtsc measures executed cycles and not time you can't reliably get the elapsed time by dividing the number of cycles by CPU frequency (between two rdtsc calls the frequency could have changed randomly)

Also in your particular test case the OS may schedule the thread to yield between fast_time() and system_time() calls thus causing variance between measured times, even if fast_time() would return correct values. So to answer your question I don't think there's any way to prevent this.

JarkkoL
  • 1,898
  • 11
  • 17
  • You are right! If the problem is not scheduling then my next guess is that the cpu frequency is changing (overclock or underclock). In any case I don't think I'm willing to give up or rdtsc so easily as it proved to be 4 times faster than the system call. So as you mentioned I suspect the OS yields my thread exactly when I don't want it to schedule my thread. So I'm still looking for some way to prevent this – e271p314 Jun 22 '14 at 14:48
  • Maybe you could sandwich the system_time() between two fast_time() calls and reject the case if the time between the fast_time() calls exceeds some threshold? I'm also curious, what's the particular application that 4x difference in the timing call makes a difference? – JarkkoL Jun 22 '14 at 14:56
  • To answer your second question, the application is in the field of algorithmic trading - where every micro second counts. – e271p314 Jun 23 '14 at 08:57
  • I don't know what platform you use, but I profiled QueryPerformanceCounter() vs __rdtsc() on win32, and for 1 billion calls I got times 10.63s vs 8.11s respectively. So at least in that case not worth the extra hassle to use rdtsc. – JarkkoL Jun 23 '14 at 15:30