13

「ポーリングが悪い」理由に関する質問を見てきました。1 つのスレッドが使用するプロセッサ時間を最小限に抑えるという点では、スピン待機 (while ループで必要な変更をポーリングする) を行うか、カーネル オブジェクト (Windows のカーネル イベント オブジェクトなど) を待機する方がよいでしょうか。 ?

文脈上、コードはシングルコア、ハイパースレッディング、マルチコアなど、あらゆるタイプのプロセッサで実行する必要があると仮定します。待つ代わりに。最後に、スレッドが待機 (またはポーリング) を開始してから条件が満たされるまでの時間は、非常に短い時間から長い時間までさまざまです。

OSは「待機」の場合により効率的に「ポーリング」する可能性が高いため、「待機は単に他の誰かがポーリングを行うことを意味する」という議論を見たくありません。これは古いニュースであり、必ずしも100%正確であるとは限りません.

4

8 に答える 8

18

OSにこれらのタイプの並行性プリミティブの合理的な実装がある場合、カーネルオブジェクトを待つ方が間違いなく優れています。

他の理由の中でも、これにより、待機中のオブジェクトが適切な状態になるまで、OSは問題のスレッドを追加のタイムスライスにスケジュールしないようになります。それ以外の場合は、絶えず再スケジュールされ、コンテキストスイッチが入れられてからしばらくの間実行されているスレッドがあります。

スレッドのプロセッサ時間を最小化することについて具体的に質問しました。この例では、カーネルオブジェクトでのスレッドブロッキングはゼロ時間を使用します。ポーリングスレッドはあらゆる種類の時間を使用します。

さらに、「他の誰かがポーリングしている」という議論は真実である必要はありません。カーネルオブジェクトが適切な状態に入ると、カーネルはその瞬間にどのスレッドがそのオブジェクトを待機しているかを確認し、1つ以上のスレッドの実行をスケジュールできます。この場合、カーネル(または他の誰か)が何かをポーリングする必要はありません。

于 2009-06-02T02:51:05.137 に答える
9

待つことは、行動するための「より良い」方法です。カーネルオブジェクトを待機しているときは、スケジューラーによって準備ができている作業がないことがわかっているため、スレッドにはCPU時間が付与されません。スレッドには、待機条件が満たされた場合にのみCPU時間が与えられます。つまり、CPUリソースを不必要に占有することはありません。

于 2009-06-02T02:53:53.087 に答える
3

まだ提起されていない点は、OSにやるべきことがたくさんある場合、ブロックするとスレッドが別のプロセスに移動するということだと思います。すべてのプロセスが必要な場所(カーネル待機、ファイル/ネットワークIOなど)でブロッキングプリミティブを使用する場合、実行するスレッドを選択するための詳細情報をカーネルに提供します。そのため、同じ時間でより多くの作業を実行します。そのファイルが開くのを待っている間、またはパケットが到着するのを待っている間にアプリケーションが何か便利なことをしている可能性がある場合、yeildingはあなたが自分のアプリであることにさえ役立ちます。

于 2009-06-02T03:52:27.003 に答える
2

待機にはより多くのリソースが必要であり、追加のコンテキストスイッチを意味します。実際、CLRモニターやWin32クリティカルセクションなどの一部の同期プリミティブは、2フェーズロックプロトコルを使用します。実際に実際に待機する前に、一部のスピン待機が実行されます。

二段階のことをするのは非常に難しく、たくさんのテストと研究が必要になると思います。したがって、時間とリソースがない限り、Windowsプリミティブに固執してください...彼らはすでにあなたのために調査を行っています。

于 2009-06-02T03:01:17.097 に答える
2

通常、OSの低レベルのもの(割り込みハンドラー/デバイスドライバー)内で、スピン待機が理にかなっている/必要な場所はごくわずかです。汎用アプリケーションは、ミューテックス/条件変数/セマフォなどの同期プリミティブを待つ方が常に優れています。

于 2009-06-02T03:03:13.473 に答える
1

OSに適切な同時実行プリミティブがある場合、ポーリングする必要はありません。ポーリングは、通常、OS を持たないリアルタイム システムまたは制限付きハードウェアで独自のものになります。その場合、wait() のオプションがない可能性があるため、ポーリングする必要がありますが、正確な期間を細かく制御できるためです。スケジューラに翻弄されるのではなく、特定の状態で待機したい場合。

于 2009-06-02T03:15:49.983 に答える
1

ほとんどの場合、待機 (ブロック) が最良の選択です (処理リソースを効率的に使用し、同じシステムで実行されている他のコードへの影響を最小限に抑えるという意味で「最良」)。主な例外は次のとおりです。

  1. 予想されるポーリング期間が短い場合 (ブロッキング syscall のコストと同様の大きさ)。
  2. 主に組み込みシステムで、CPU が特定のタスクの実行専用であり、CPU をアイドル状態にする利点がない場合 (たとえば、90 年代後半に構築された一部のソフトウェア ルーターはこのアプローチを使用しました)。

通常、OS カーネル内でポーリングを使用してブロッキング システム コールを実装することはありません。代わりに、イベント (割り込み、タイマー、ミューテックスに対するアクション) によって、ブロックされたプロセスまたはスレッドが実行可能になります。

于 2009-06-02T03:21:18.897 に答える
1

次の 4 つの基本的なアプローチがあります。

  1. OS 待機プリミティブを使用して、イベントが発生するまで待機します。
  2. OSタイマープリミティブを使用して、イベントがまだ発生しているかどうかを定義された速度で確認します
  3. イベントが発生したかどうかを繰り返し確認しますが、OS プリミティブを使用して、発生していない任意の不明な期間のタイム スライスを生成します。
  4. イベントが発生したかどうかを繰り返し確認し、発生していない場合は CPU を解放しません。

#1 が実用的である場合、イベントへの対応を遅らせることが有益でない限り、多くの場合、これが最善のアプローチです。たとえば、数秒間にわたって大量のシリアル ポート データを受信することが予想され、データが送信されてから 100 ミリ秒後にデータを処理することが、即座に処理するのと同じくらい良い場合は、後者の 2 つのいずれかを使用して定期的にポーリングします。アプローチは、「データ受信」イベントを設定するよりも優れている場合があります。

アプローチ 3 はかなり大雑把ですが、多くの場合は適切な方法です。多くの場合、#1 にアプローチするよりも多くの CPU 時間とリソースを浪費しますが、多くの場合、実装がより簡単になり、多くの場合、リソースの浪費は問題にならないほど小さくなります。

アプローチ 2 は 3 よりも複雑になることがよくありますが、多くのリソースを 1 つのタイマーで専用スレッドなしで処理できるという利点があります。

アプローチ #4 は、組み込みシステムで必要になる場合がありますが、ハードウェアを直接ポーリングしていない限り、通常は非常に悪い方法であり、問​​題のイベントが発生するまで何もする必要はありません。多くの場合、待機中のスレッドが CPU を解放するまで、待機中の状態が発生することはありません。アプローチ #3 のように CPU を明け渡すと、待機中のスレッドはイベントを独占するよりも早くイベントを確認できるようになります。

于 2012-05-15T15:17:18.203 に答える