Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

tick_count thread safe?

smasherprog
Beginner
437 Views
Hi, I am using the tbb libraries for a project that I am working on and anther programm brought up an excellent question that I could not answer, "how is tick_count thread safe?"

I looked at the code for tick_count::now() and there is nothing special or thread safe about it. How is it thread safe?


For reference, the code is

[bash]inline tick_count tick_count::now() {
    tick_count result;
    LARGE_INTEGER qpcnt;
    QueryPerformanceCounter(&qpcnt);
    result.my_count = qpcnt.QuadPart;
    return result;
}
[/bash]


I took out the ifdefs for each operating system. That doesnt seem thread safe to me, what am I missing?
0 Kudos
7 Replies
Dmitry_Vyukov
Valued Contributor I
437 Views
I guess it's just not thread-safe. What for?
0 Kudos
smasherprog
Beginner
437 Views
Well, this is listed in the documentation for the tbb library under the first paragraph for the class tick_count

Quote from the tbb threading documentation

Parallel programming is about speeding up wall clock time, which is the real time that
it takes a program to run. Unfortunately, some of the obvious wall clock timing
routines provided by operating systems do not always work reliably across threads,
because the hardware thread clocks are not synchronized. The library provides
support for timing across threads. The routines are wrappers around operating
services that we have verified as safe to use across threads.



Quote from Intel threading building blocks by James reinders

Unlike some timing interfaces, tick_count is guaranteed to be safe to cuse across all threads. It is based on a common or global clock. It is valid to subtract tick_count valuss that were created by different threads to compute elapsed time.


maybe someone can tell me exaclty what that means in relation to the code? Is the code thread safe across mutliple threads ?
0 Kudos
Dmitry_Vyukov
Valued Contributor I
437 Views
Quoting smasherprog
Quote from the tbb threading documentation

Parallel programming is about speeding up wall clock time, which is the real time that
it takes a program to run. Unfortunately, some of the obvious wall clock timing
routines provided by operating systems do not always work reliably across threads,
because the hardware thread clocks are not synchronized. The library provides
support for timing across threads. The routines are wrappers around operating
services that we have verified as safe to use across threads.

Think of the std::string class. It's safe to use std::string objects in different threads (each thread uses it's own set of string objects), but they are not thread-safe in itself in any way, shape or form.

The same with tick_count objects. They provide a "thread-safe timing service" that can be used from a plurality of threads, but each individual object is not thread-safe.

0 Kudos
RafSchietekat
Valued Contributor III
437 Views
Now I'm confused... :-)

There seems to be no problem with now(), because it uses a thread-safe library function and is otherwise reentrant.

Maybe the original question can be answered by emphasising that there may be other distributed time references (but what would those be, I wonder?) that are quite accurate when used within their attached set of hardware threads (and therefore within a software thread only if affinity is specified), but that may drift and perhaps even diverge considerably across such sets, like wristwatches that were not recently synchronised. tick_count takes care to pick each environment's way to use a single common reference for now(), so that computing a difference makes sense at all after bringing the values together with proper synchronisation (such as a lock), as you would have to do before being able to subtract ordinary integers computed in different threads. I suppose it would be a more expensive call than getting a hardware thread-specific value, otherwise there would be no use having those as well?

Does that clear up anything?
0 Kudos
smasherprog
Beginner
437 Views
First, I have to apologize, my topic and question were not exactly what I meant. I know that the function call tick_count::now() is thread safe, meaning that differeing threads can call the function and there are no possible races that occur, etc.

However, in the documention with tbb, and the book intel threading building blocks, it emphasises how to use tick_count because it is synchronized accross threads as quoted in

Intel Threading Building Blocks
Reference Manual
Document Number 315415-002US

Page 133 first paragraph, second sentence states, "

Unfortunately, some of the obvious wall clock timing routines provided by operating systems do not always work reliably across threads, because the hardware thread clocks are not synchronized. The library provides support for timing across threads. "

Check out the bolded part. If I make the claim to use my product and then say use it because Product A does not have a feature. Is that not implying that the product I have includes that feature? I believe it does.

So, from that sentence, the claim is made that tick_count somehow synchromizes the calls to tick_count::now() so that the result of that call can be used on different threads. Now, I know the results CAN be used on different threads, but I thought that some kind of setafinity is used.

Also In Intel Threading Building Blocks by James Reinders, Page 130,

Unlike some timing interfaces, tick_count is guaranteed to be safe to use across threads. It is based on a common or global clock. It is valid to subtract tick_count values created by different threads to compute elapsed time."

Now, if there is no kind of synchronization, then how is it valid to subtrack tick_count values created by different threads? Is this because the amount of drift is very small and doesnt matter? Or, is it valid because the operation CAN occur, which is like saying, "use Microsoft visual studio as a compiler because you can do addition. of Course you can do addition on their compiler!!. Of course I can subtract two tick_count values, they are just numbers.

I was just a little confused when I found out that tick_count did nothing special :P


Anyway, My question has been answered to my satisifaction thanks.


0 Kudos
RafSchietekat
Valued Contributor III
437 Views
I'm still confused. Maybe there's a mix-up between synchronisation of clocks (assuming distributed clocks, each serving a specific set of cores) and synchronisation of data (as in safe access from a different thread)? tick_count claims only the former, so you stilll have to use a lock or similar to reliably access an existing tick_count instance from a different thread.

The name "tick_count" is rather weird in this regard because I would rather expect a tick count to get out of synch than any real-time reference. What would such a possibly diverging real-time reference be, API-wise?
0 Kudos
Dmitry_Vyukov
Valued Contributor I
437 Views
I guess they meant known oddities of RDTSC instruction on older processors:
http://en.wikipedia.org/wiki/Time_Stamp_Counter

However, documentation on QueryPerformanceCounter():
http://msdn.microsoft.com/en-us/library/ms644904%28VS.85%29.aspx
also notes that "However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL)."
0 Kudos
Reply