Recently at work, I ran into an interesting threading problem.
I have two threads – A and B, running concurrently. Thread A needs a piece of data from Thread B. Normally, Thread B would just pass a message to Thread A. But in this scenario, every millisecond counts. Thread A needs the data A.S.A.P!
In theory, Thread B should have the result within couple milliseconds. Since the wait is so short, the synchronous approach is feasible. I would block Thread A until Thread B gets the data. But should I use a condition varialbe, or should I just spin-wait (assuming that I have a multi-core processor)?
This is very much a real life threading problem that even expert programmer encounters. (And I am no expert. :???:)
Speed Comparison
I expect spin-wait to have lower latency than condition variable. But by how much?
It has been awhile since I ran any performance test. So I cooked up some test code to get a sense of the latency.
Here’s the spin-wait code.
long global_spin_var = 0;
void spin_thread()
{
while(1)
{
// memory barrier for visibility semantics
_ReadWriteBarrier();
// spin wait
if(global_spin_var == 1){ break; }
}
}
void time_spin_thread()
{
// ... set up timing code here
// update the global variable with cmpxchg
InterlockedExchange(&global_spin_var,0);
thread t1(bind(&spin_thread));
// wait for a second for thread start, sloppy but good enough
Sleep(1000);
t1.join();
}
Here’s the condition variable code.
long global_condition_wait_var = 0;
condition_variable global_condition;
mutex global_mutex;
void condition_wait_thread()
{
mutex::scoped_lock lock(m_mutex);
while(global_condition_wait_var == 0)
global_condition.wait(lock);
}
void time_condition_wait_thread()
{
// ... set up timing code here
// update the global variable with cmpxchg
InterlockedExchange(&global_condition_wait_var,0);
thread t2(bind(&condition_wait_thread));
// wait for a second for thread start, sloppy but good enough
Sleep(1000);
global_condition.notify_all();
t2.join();
}
It turns out that latency of condition variable is higher, but not absurdly high.
Spin-wait’s latency is about half of condition variable. This is a reasonable trade-off for spending a bunch of CPU cycles spinning.
Final Thoughts
So which approach did I end up using? Neither.
Apparently Thread A doesn’t really need the “right” answer from Thread B. It just needs “some” answer to make things look good.
Another lesson from the real world – it doesn’t matter if it works, as long as it looks good. 🙄
Source
The source and the data sheet can be downloaded here.
Tools: Visual Studio 2008, Boost 1.41, Window 7, Intel I5-750 (quad core)
