1

問題を解決するために (そしてマルチタスクの理解を深めるために)、小さなスレッド プールの実装を作成しました。このスレッド プールは、スレッド プールのクライアントによってタスクが追加されると、キューからタスクをポップする多数のワーカー スレッドを起動します。この質問の目的のために、タスク キューが空の場合、ワーカー スレッドはすべて終了します。

いくつかの基本的なベンチマークを行った後、アプリケーションがキュー ロックの取得を待機するために最大 60% の時間を費やしていることを発見しました。おそらく、これは主にワーカー スレッド内で行われています。

これは、ワーカー スレッドに十分な処理を与えていないことを示しているにすぎないのでしょうか。ワーカースレッドのスループットを向上させるために欠けている可能性のある簡単なものはありますか?

編集:これは、物事をある程度説明するための大まかな擬似コードです。これらは、ワーカー スレッドの実行中にロックが取得/解放される唯一の 2 つの場所です (アプリケーションの実行時間の大部分です)。

std::list<task_t> task_list;

// Called by the client to add tasks to the thread pool
void insert_task(const task_t& task)
{
    lock_type listlock(task_mutex);

    task_list.push_back(task);
}

// The base routine of each thread in the pool. Some details
// such as lifetime management have been omitted for clarity.
void worker_thread_base()
{
    while (true)
    {
        task_t task;

        {
        lock_type listlock(task_mutex);

        if (task_list.empty())
            continue;

        task = task_list.front();

        task_list.pop_front();
        }

        do_task(task);
    }
}
4

2 に答える 2

0

単一のロック、複数のロックでこれを実行しようとしていますか?ミューテックス?どの待機セマンティクスを使用していますか?

私はあなたの説明から(そしてこれは純粋に推測です)あなたが次のようなものを持っていると推測します:

lock(theLock) {
 // ... do lots of work ...
}

軽量スレッドにディスパッチするコードを含むメインスレッド。これで待機時間が長くなる理由の1つは、スピンアップされたスレッドから、キューに入れられて実行を待機しているというシグナルを返す必要があるためです(これも、コードを指定しなかったための推測です)。

これを解決する1つの方法は、上記のような明示的なロックの使用から、スレッドの1つを機能させたいときにパルス化されるシグナルミューテックスの使用に切り替えることです。

しかし、あなたの現在の実装を見ずに、私はそれをはるかに超えることができるかどうかわかりません。

于 2010-08-05T17:23:53.890 に答える
0

各スレッドがロックを取得しようとして「スピン」する場所に設計が構築されます。これは、すべてのワーカー スレッドが作業を実行していない限り、常に発生します。その場合、ロックが取得されずに作業が行われます。

すべてのスレッドがただ座ってロックをスピンしていると、かなりの量の CPU 時間を使用して待機することになります。あなたの設計を考えると、これはある程度予想されます。

ワーカー スレッドの数が少ないと、ブロックされる時間の割合が劇的に減少する可能性が高いことがわかります。また、スレッドよりも多くの作業項目がある時点で、そのロックの待機に費やす時間はほとんどなくなります。

はるかに優れた設計は、この時点での待機を防ぐことができるため、作業キューに何らかの形式のロックレス キューを使用することです。さらに、キューに作業が入るまでワーカー スレッドをブロックできる待機ハンドルがあると、不要なスピンを防ぐことができます。

于 2010-08-05T17:39:28.347 に答える