Threadpool implementation: condition_variables vs. yield()
Asked Answered
H

2

16

I try to develop a threadpool in C++ and I wonder if it is better to yield() the thread in the main loop of the worker thread or to wait on a condition variable:

void worker_thread( void )
{
    // this is more or less pseudocode
    while( !done )
    {

        if( task_available ) 
             run_task();
        else
            std::this_thread::yield();
    }
}

versus

void worker_thread( void )
{
    // this is more or less pseudocode

    std::unique_lock< std::mutex > lk( mutex_ );
    while( !done )
    {

        if( task_available ) 
             run_task();
        else
            condition_.wait( lk );
    }
}

Any ideas? Will there be any performance differences between both versions?

Hillside answered 12/7, 2013 at 11:16 Comment(0)
D
12

if your threads in the thread pool are constantly fed with tasks and you need fast response time, then yield is what you want, but yield will burn cpu cycles no matter what the waiting thread is doing. if not, you can use the conditional approach, threads will sleep until a task is ready (note though, a conditional can wake a thread, even if no ready signal was sent), the response time might be slower, but you will not burn cpu cycles.

i would recommend the conditional approach, and if the reaction time is too slow, switch to yield.

Disjoin answered 12/7, 2013 at 11:29 Comment(6)
How is the conditional approach implemented? Do they have a similar waiting mechanism that the worker_thread above?Hillside
yield causes the calling thread to yield execution to another thread that is ready to run on the current processor (see SwitchToThread for windows).Disjoin
for conditionals, see pthread_cond_wait. so it causes the thread to enter a sleep state until the conditional is fired (like a event on windows)Disjoin
So the check for the condition variable is put into the "main scheduler"?Hillside
the wait is put into the worker thread (like in your example), the scheduler notifies the worker thread (notify_one / notify_all) if new work is ready.Disjoin
Polling solutions are generally hopeless, wasting CPU cycles and memory bandwidth.Lindblad
O
9

The cost of a thread switch is the same either way. As for whether you should use polling or condition variables, the latter can rest the processor by kicking the thread off until there is really something to do. That results in lower CPU utilization. The polling method will allow the thread to return and "try again", effectively running the CPU indefinitely.

It's worth point-out that there are a few applications that prefer polling, like when task_available is false for very short amounts of time (i.e. there is usually work to do). In that case, you will want to poll task_available in a loop with a counter; only yield the thread when the counter exceeds a threshold.

Offutt answered 12/7, 2013 at 11:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.