13

C++ でスレッドプールを開発しようとしていますが、ワーカー スレッドのメイン ループでスレッドを yield() するか、条件変数を待機する方がよいか疑問に思います。

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

何か案は?両方のバージョンでパフォーマンスに違いはありますか?

4

2 に答える 2

10

スレッドプール内のスレッドに常にタスクが供給され、高速な応答時間が必要な場合は、yield が必要ですが、yield は待機中のスレッドが何をしていても CPU サイクルを消費します。そうでない場合は、条件付きアプローチを使用できます。タスクの準備が整うまでスレッドはスリープします(ただし、準備完了シグナルが送信されていなくても、条件付きでスレッドをウェイクアップできます)、応答時間は遅くなる可能性がありますが、燃えることはありませんCPUサイクル。

条件付きアプローチをお勧めします。反応時間が遅すぎる場合は、利回りに切り替えます。

于 2013-07-12T11:29:52.087 に答える
7

スレッド スイッチのコストはどちらの方法でも同じです。ポーリング変数と条件変数のどちらを使用する必要があるかについては、後者は、実際に何かする必要があるまでスレッドを開始してプロセッサを休ませることができます。その結果、CPU 使用率が低下します。ポーリング メソッドを使用すると、スレッドが戻って「再試行」し、実質的に CPU を無期限に実行できます。

ポーリングを好むアプリケーションがいくつかあることは指摘しておく価値があります。たとえば、task_availableis が非常に短い時間だけ false である場合 (つまり、通常はやるべき作業がある場合) です。その場合、task_availableカウンターを使用してループでポーリングする必要があります。カウンターがしきい値を超えた場合にのみスレッドを生成します。

于 2013-07-12T11:30:12.440 に答える