0

これは私の最初の投稿です。事前に寛容に感謝します。

ジョブ キュー >> スレッド数のスレッド プールがあります。

プロセスフロー:

  1. スレッドプールの初期化 (M 個のスレッド)
  2. N 個のタスクをキューに入れます ( N >> M にすることができます)
  3. スレッドはタスクの実行を開始します。現在のタスクスレッドが終了すると、次の利用可能なタスクが自動的に実行されます。
  4. 同期点 - すべてのタスクを完了する必要があります。
  5. データ処理 (シングルスレッド)
  6. 処理されたデータに基づいてタスクを生成するか、終了します
  7. 後藤2

問題は同期点です。カウンターとミューテックスを使用して単純なセマフォを実装しました。ステップ2の前に、ロードするタスクの数でカウンターが初期化され、各タスクが完了するとカウンターが減ります。カウンター == ゼロの場合、ワーカー スレッドから pthread_cond_signal を送信し、ステップ 4 の pthread_cond_wait がそれをキャッチします。

これを行うには最も効率的な方法ではないように感じます (カウンターのデクリメントのために各スレッドでロック/ロック解除するのは好きではありません。特にタスクのペイロードが小さい場合は大きなオーバーヘッドになります) が、改善方法がわかりません。バリアについては認識していますが、同期イベントが発生する前にスレッドを複数回再利用する必要があるため、スレッドで pthread_barrier_wait を実行できません。

キュー内のタスク数に対する pthread_spin_lock ? キューが空であっても、スレッドが実行されていないという意味ではありません。スレッドは最後の M タスクにある可能性があります。スレッドは次のサイクルで再利用されるため、スレッドを結合できません。

入力/アイデアをいただければ幸いです。ありがとうございました。

4

1 に答える 1

0

おそらく、カウンターのカーネルロックの代わりにアトミックデクリメント命令を使用することで、少し最適化できます-カウンターをゼロにデクリメントするスレッドは、「OnComplete(何か)」メソッド/関数を呼び出すことができます。おそらく、元のスレッドにシグナルを送信します(現在行っているのと同じように)。

キューとバリア/ランデブーをどのように設計しても、些細なタスクをスレッド化する価値はありません。プールがビジーではなく、プール スレッドがキューでブロックされている場合は、通常、元のスレッドが待機に入り、タスクの完了後に再度実行されるときに 2 つのコンテキスト変更が発生します。完了カウントでスピンすると、CPU のプールから 1 つのコアが吸い出されます - あまり役に立たないでしょう (特に、複数のタスク セットを並行して実行するようにプールを設計する場合、複数の元のスレッドがスピンすることになります)。 .

CPU の自明なタスクのみをスレッド化しないでください。実行する CPU 作業が多い場合、またはタスクがブロック操作を実行し、コアよりも多くのスレッドがある場合は問題ありません。

于 2013-01-23T08:53:55.127 に答える