2

Linuxシェルでスレッドを使用してCでプログラミングする場合、スレッドのオーバーヘッドを削減し、基本的にCPU時間を短縮します(そして効率を高めます)。

現在、プログラムでは多くのスレッドが作成されており、終了する前にジョブを実行する必要があります。相互排除のため、同時に1つのスレッドのみがジョブを実行できます。

スレッドが開始する前にジョブを完了するのにかかる時間を知っています

他のスレッドは、そのジョブを実行しているスレッドがある間、待機する必要があります。彼らが仕事をすることができるかどうかをチェックする方法は、条件変数が満たされているかどうかです。

待機中のスレッドの場合、その条件変数を使用して待機し、この特定のコードを使用して待機する場合(a、b、c、およびdは単なる任意のものであり、これは単なる例です):

while (a == b || c != d){
    pthread_cond_wait(&open, &mylock);
}

これはどれくらい効率的ですか?コードで何が起こっているのpthread_cond_waitですか?条件変数を常にチェックするのは、(舞台裏での)whileループですか?

また、スレッドにかかるジョブの時間がわかっているので、最短のジョブについて最初にスケジューリングポリシーを適用する方が効率的ですか?または、ジョブを実行するスレッドの任意の組み合わせで、プログラムが終了するのに同じ時間がかかるため、それは問題ではありません。言い換えると、最短ジョブを使用すると、待機している他のスレッドのCPUオーバーヘッドが最初に低くなりますか?最短ジョブが最初に待ち時間を短縮するように見えるので。

4

2 に答える 2

4

単一のスレッドで問題を解決してから、最小のロックが必要な方法がまだ見つからない場合は、並列化を公開するための最適な場所を特定するための支援を依頼してください。使用するスレッドの最適な数は、使用するコンピューターによって異なります。n+1 を超えるスレッドを使用することはあまり意味がありません。ここで、n はプログラムで使用できるプロセッサ/コアの数です。スレッド作成のオーバーヘッドを減らすには、各スレッドに複数のジョブを与えることをお勧めします。

以下は、明確化の編集に対する回答です。

現在、プログラムでは多くのスレッドが作成されており、終了する前にジョブを実行する必要があります。相互排除のため、同時に 1 つのスレッドしかジョブを実行できません。

いいえ。上記のように、最大​​で n+1 個のスレッドを作成する必要があります。相互排除とはどういう意味ですか?相互排除は「1つのスレッドのみがその作業キューにタスクxを含む」と考えています。これは、他のスレッドがタスク x をロックする必要がないことを意味します。

そのジョブを実行しているスレッドがある間、他のスレッドは待機する必要があります。仕事ができるかどうかをチェックする方法は、条件変数が満たされているかどうかです。

各スレッドに、完了するタスクの独立したリストを提供します。ジョブ x がジョブ y の前提条件である場合、ジョブ x とジョブ y は理想的には同じリストにあるため、スレッドはどちらのジョブでもスレッド ミューテックス オブジェクトを処理する必要がありません。この道を探索しましたか?

while (a == b || c != d){ pthread_cond_wait(&open, &mylock); これはどのくらい効率的ですか? pthread_cond_wait コードで何が起こっていますか? 条件変数を常にチェックする while ループ (舞台裏) ですか?

未定義の動作を回避するために、pthread_cond_wait を呼び出す前に mylock を現在のスレッドでロックする必要があるため、このループに入る前に、コードで pthread_mutex_lock を呼び出して mylock ロックを取得すると仮定します。

  1. pthread_mutex_lock は、ロックを取得するまでスレッドをブロックします。これは、一度に 1 つのスレッドが pthread_mutex_lock と pthread_cond_wait の間のコード (pthread_cond_wait コード) を実行できることを意味します。
  2. pthread_cond_wait はロックを解放し、他のスレッドが pthread_mutex_lock と pthread_cond_wait の間でコードを実行できるようにします。pthread_cond_wait が戻る前に、ロックを再度取得できるまで待機します。このステップはアドホックに繰り返されwhile (a == b || c != d)ます。
  3. pthread_mutex_unlock は、タスクが完了すると後で呼び出されます。それまでは、一度に 1 つのスレッドだけが pthread_cond_wait と pthread_mutex_unlock の間のコード (pthread_cond_wait 後のコード) を実行できます。さらに、1 つのスレッドが pre-pthread_cond_wait コードを実行している場合、他のスレッドが post-pthread_cond_wait コードを実行することはできません。

したがって、ジョブを優先キューに格納するシングルスレッド コードを実行することもできます。少なくとも、不要で過剰なコンテキスト スイッチはありません。先ほど言ったように、「問題は 1 つのスレッドで解決してください」。最適化によってどれだけの時間が節約されるかについて、それを測定するものがない限り、意味のある声明を出すことはできません。

また、スレッドがジョブにかかる時間を知っているので、最初に最短のジョブに関するスケジューリング ポリシーを適用する方が効率的ですか? または、ジョブを実行するスレッドのどの組み合わせでも、プログラムが完了するまでに同じ時間がかかるため、それは問題ではありません。つまり、最初に最短ジョブを使用すると、待機している他のスレッドの CPU オーバーヘッドが減少しますか? 最短のジョブが最初に表示されるため、待ち時間が短縮されるようです。

スケジューリング ポリシーを適用する場合は、シングル スレッド プロジェクトで実行してください。並行性が問題の迅速な解決に役立つと確信している場合は、完成したシングルスレッド プロジェクトを並行性に公開し、その信念を検証するためのテストを導き出します。スレッドが作業を共有する必要がない方法で並行性を公開することをお勧めします。

于 2013-02-24T02:06:48.687 に答える
2

Pthread プリミティブは一般にかなり効率的です。ブロックするものは、通常、ブロック中に CPU 時間をまったく消費しないか、ごくわずかしか消費しません。パフォーマンスに問題がある場合は、まず他の場所を探してください。

スケジューリング ポリシーについて心配する必要はありません。一度に 1 つのスレッドしか実行できないようにアプリケーションが設計されている場合、すべてのコストを課しながら、そもそもスレッド化のメリットのほとんどを失うことになります。(そして、一度に 1 つのスレッドしか実行されないために共有変数をロックするなど、すべてのコストを課していない場合は、後で問題が発生する可能性があります。)

于 2013-02-24T06:31:52.917 に答える