Реализация пустого потока: condition_variables vs. yield()

Я пытаюсь создать threadpool в С++, и мне интересно, лучше ли выдать() поток в основном цикле рабочего потока или ждать переменной условия:

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

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

против

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 );
    }
}

Любые идеи? Будут ли какие-либо различия в производительности между обеими версиями?

Ответ 1

если ваши потоки в пуле потоков постоянно загружаются задачами, и вам нужно быстрое время отклика, тогда выход - это то, что вы хотите, но выход будет записывать циклы процессора независимо от того, что делает поток ожидания. если нет, вы можете использовать условный подход, потоки будут спать до тех пор, пока задача не будет готова (обратите внимание, что условное может разбудить поток, даже если не был отправлен готовый сигнал), время отклика может быть медленнее, но вы не будете гореть циклы процессора.

я бы рекомендовал условный подход, и если время реакции слишком медленное, переключитесь на выход.

Ответ 2

Стоимость коммутатора потоков одинакова в любом случае. Что касается того, следует ли использовать опросы или переменные состояния, последний может оставить процессор, отбросив поток, пока не будет что-то делать. Это приводит к снижению загрузки ЦП. Метод опроса позволит потоку вернуться и "попробуй еще раз", эффективно запустив ЦП на неопределенный срок.

Стоит отметить, что есть несколько приложений, которые предпочитают опрос, например, когда task_available является ложным в течение очень короткого промежутка времени (т.е. обычно есть работа). В этом случае вам нужно будет опросить task_available в цикле с помощью счетчика; только выход потока, когда счетчик превышает пороговое значение.