2

複数のプロデューサー、単一のコンシューマーモデルを持つアプリケーションを作成しています(複数のスレッドが単一のファイルライタースレッドにメッセージを送信します)。

各プロデューサースレッドには2つのキューが含まれ、1つは書き込み用、もう1つはコンシューマー用のキューです。コンシューマースレッドのすべてのループは、各プロデューサーを反復処理し、そのプロデューサーのミューテックスをロックし、キューを交換し、ロックを解除して、プロデューサーが使用しなくなったキューから書き込みます。

コンシューマースレッドのループでは、すべてのプロデューサースレッドを処理した後、指定された時間スリープします。私がすぐに気付いたのは、プロデューサーがキューに何かを書き込んで戻るまでの平均時間が、1つのプロデューサースレッドから2に移動したときに劇的に(5倍)増加したことです。スレッドが追加されると、この平均時間は底に達するまで減少します。アウト-10人のプロデューサーと15人のプロデューサーの所要時間に大きな違いはありません。これはおそらく、処理するプロデューサーが多いほど、プロデューサースレッドのミューテックスの競合が少なくなるためです。

残念ながら、プロデューサーが5人未満の場合は、アプリケーションでかなり一般的なシナリオです。プロデューサーの数に関係なく、妥当なパフォーマンスが得られるように、スリープ時間を最適化したいと思います。スリープ時間を長くすると、プロデューサー数が少ない場合はパフォーマンスが向上しますが、プロデューサー数が多い場合はパフォーマンスが低下することに気付きました。

他の誰かがこれに遭遇しましたか?もしそうなら、あなたの解決策は何でしたか?スレッドの数でスリープ時間をスケーリングしようとしましたが、マシン固有であり、かなり試行錯誤のようです。

4

4 に答える 4

2

プロデューサーの数に基づいてスリープ時間を選択することも、いくつかの動的スキームに基づいてスリープ時間を適応させることもできます。消費者が目を覚まして仕事がない場合は、睡眠時間を2倍にし、そうでない場合は半分にします。ただし、スリープ時間を最小値と最大値に制限します。

いずれにせよ、あなたはより根本的な問題について論文を書いています。睡眠とポーリングは簡単に正しく行うことができ、利用できる唯一のアプローチである場合もありますが、多くの欠点があり、「正しい」方法ではありません。

セマフォを追加することで、正しい方向に進むことができます。セマフォは、プロデューサーがアイテムをキューに追加するたびにインクリメントされ、コンシューマーがキュー内のアイテムを処理するときにデクリメントされます。消費者は、処理するアイテムがある場合にのみウェイクアップし、すぐにウェイクアップします。

ただし、キューのポーリングは依然として問題になる可能性があります。アイテムがあるキューを参照する新しいキューを追加できます。しかし、それはむしろ、プロデューサーごとのキューではなく、コンシューマーが処理する単一のキューがない理由についての疑問を提起します。他のすべてが等しいということは、最善のアプローチのように聞こえます。

于 2009-09-09T17:02:54.243 に答える
1

寝る代わりに、生産者によって合図された状態で消費者がブロックすることをお勧めします。posix準拠のシステムでは、pthread_condで動作させることができます。pthread_cond_tプロデューサーごとに1つずつ配列を作成してから、プロデューサー間で共有される追加の配列を作成します。プロデューサーは最初に個々の条件変数を通知し、次に共有条件変数を通知します。コンシューマーは共有条件を待機してから、配列の要素を反復処理し、配列の各要素に対してを実行します( 「今」の絶対時間を取得するためにpthread_cond_timed_wait()使用します)。pthread_get_expiration_np()待機が0を返す場合、そのプロデューサーはデータを書き込んでいます。コンシューマーは、再度待機する前に条件変数を再初期化する必要があります。

ブロッキング待機を使用することで、コンシューマーがプロデューサーを不必要にロックアウトする時間を最小限に抑えることができます。前の回答で述べたように、これをセマフォで機能させることもできます。私の意見では、セマフォのセマンティクスは条件に比べて単純化されていますが、コンシューマーループを通過するたびに処理されたプロデューサーごとに共有セマフォを1回デクリメントするように注意する必要があります。条件変数には、シグナルが送信された後で再初期化すると、基本的にブールセマフォのように使用できるという利点があります。

于 2009-12-02T19:25:32.647 に答える
0

プログラミングに使用する言語でブロッキングキューの実装を見つけてください。任意の数のプロデューサーと1つのコンシューマーに対して、1つのキューだけで十分です。

于 2009-09-09T16:34:53.633 に答える
0

私には、スリープ中または実際の作業を行っているときに、コンシューマースレッドを別の場所でビジー状態にすることにより、誤ってバッファリングを導入しているように思われます。(キューがバッファとして機能します)プロデューサー側で単純なバッファリングを行うと、競合が減る可能性があります。

あなたのシステムはプロデューサーとコンシューマーの間のロック競合に非常に敏感であるようですが、なぜそのような単純なスワップ操作が実行統計に表示されるのに十分なCPU時間を占めるのかについて私は困惑しています。

コードを見せてもらえますか?

編集:多分あなたはあなたがする仕事がないときでさえあなたのロックを取りそしてキューを交換していますか?

于 2009-09-09T16:55:55.920 に答える