0

pthreads を使用するマルチスレッド アプリケーションがあります。私はミューテックス()ロックと条件変数()を持っています。2 つのスレッドがあり、1 つのスレッドが 2 番目のスレッド (ワーカー) のデータを生成しています。2 番目のスレッドは、生成されたデータをリアルタイムで処理しようとしており、1 つのチャックが可能な限り一定時間の経過に近づくように処理されます。

これは非常にうまく機能しますが、ワーカー スレッドが待機している状態をプロデューサー スレッドが解放するとき、ワーカー スレッドが制御を取得して再度実行するまでに、最大でほぼ 1 秒の遅延が見られることがあります。

私がこれを知っているのは、プロデューサーがワーカーが待機している条件を解放する直前に、別のチャックを処理する時間になるとワーカーの処理のチャックを行い、ワーカー スレッドで条件を受け取るとすぐに、それも行うためです。別のチャックを処理する時が来たら、処理のチャック。

この後者のケースでは、チャックの処理が何度も遅れていることがわかります。この効率の低下を解消し、チャックのカチカチ音をできるだけ望ましい周波数に近づけるためにできることをしたいと思います。

プロデューサーからの解放条件と、ワーカーが処理を再開するようにその条件が解放されたことが検出されるまでの遅延を減らすためにできることはありますか? たとえば、プロデューサーが何かを呼び出して、自分自身を強制的にコンテキスト スイッチ アウトにすることは役に立ちますか?

要するに、ワーカーは、プロデューサーに作業を作成するように要求するたびに待機する必要があるため、プロデューサーはワーカーのデータ構造をいじってから、ワーカーに再び並列実行する準備ができていることを伝えることができます。このプロデューサーによる排他的アクセスの期間は短いはずですが、この期間中に、プロデューサーが排他的アクセスを持っている間に、ワーカーに代わってプロデューサーが実行するリアルタイムの作業も確認しています。どういうわけか、再び並列実行に戻ると、回避したい大幅な遅延が発生することがあります。これを最もよく達成する方法を提案してください。

4

1 に答える 1

2

次のパターンを提案できます。一般に、リアルタイムレンダラーなどでフレームを事前にバッファリングする場合などに、同じ手法を使用できます。

まず、メッセージに記載されているアプローチは、両方のスレッドが常に均等に (またはほぼ均等に) ロードされている場合にのみ効果的であることは明らかです。そうでない場合、マルチスレッドは実際に状況に役立ちます。

では、あなたの問題に最適な糸のパターンを考えてみましょう。とスレッドがあるyieldingとします。processingそれらの最初は処理するデータのチャンクを準備し、2番目は処理を行い、処理結果をどこかに保存します(実際には重要ではありません)。

これらのスレッドを連携させる効果的な方法は、適切な譲歩メカニズムです。yieldingスレッドは単純に共有バッファにデータを追加する必要があり、そのデータで何が起こるかを実際に気にする必要はありません。そして、バッファは単純な FIFO キューとして実装できます。これは、yieldingスレッドが処理するデータを準備PUSHし、キューを呼び出す必要があることを意味します。

X = PREPARE_DATA()
BUFFER.LOCK()
BUFFER.PUSH(X)
BUFFER.UNLOCK()

さて、processingスレッド。動作はこのように説明する必要があります(おそらくSLEEP(X)、呼び出しの間に人工的な遅延を追加する必要がありますEMPTY

IF !EMPTY(BUFFER) PROCESS(BUFFER.TOP)

ここで重要なのは、処理スレッドが処理済みデータをどう処理するかです。明白なアプローチはPOP、データが処理された後に呼び出しを行うことを意味しますが、おそらくもっと良いアイデアが必要になるでしょう。とにかく、私のバリアントでは、これは次のようになります

// After data is processed
BUFFER.LOCK()
BUFFER.POP()
BUFFER.UNLOCK()

ロック操作yieldingprocessingスレッドは、データのチャンクごとに 1 回しか呼び出されないため、実際にはパフォーマンスに影響しないことに注意してください。


さて、興味深い部分です。最初に書いたように、このアプローチは、スレッドが CPU / リソースの使用に関してある程度同じように動作する場合にのみ有効です。この条件が常に真ではなく、他のランタイム条件で問題になる場合でも、これらのスレッド化ソリューションを有効にする方法があります。

この方法は、スレッドと呼ばれる別のスレッドを作成することを意味しcontrollerます。このスレッドは、各スレッドがデータの 1 つのチャンクを処理するために使用する時間を比較し、それに応じてスレッドの優先順位のバランスを取るだけです。実際には、 「時間を比較する」必要はありません。controllerスレッドは単純に次のように機能します。

IF BUFFER.SIZE() > T
   DECREASE_PRIORITY(YIELDING_THREAD)
   INCREASE_PRIORITY(PROCESSING_THREAD)

もちろん、ここでより優れたヒューリスティックを実装することもできますが、controllerスレッドを使用したアプローチは明確です。

于 2010-05-24T06:16:19.113 に答える