ポーリングするのが良いでしょうか、それとも待つのが良いでしょうか?

StackOverflow https://stackoverflow.com/questions/937713

質問

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

コンテキストとして、シングルコア、ハイパースレッド、マルチコアなど、あらゆるタイプのプロセッサ上でコードを実行する必要があると想定します。また、ポーリングまたは待機するスレッドは、待機せずにポーリングした場合、ポーリング結果が満足できるまで続行できないと仮定します。最後に、スレッドが待機 (またはポーリング) を開始してから条件が満たされるまでの時間は、非常に短い時間から長時間まで変動する可能性があります。

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

役に立ちましたか?

解決

提供OSを並行処理プリミティブのこれらのタイプの合理的な実装を持っている、それはカーネルオブジェクト上で待機するように間違いなく良いです。

他の理由の中で、これはOSが待っ-用されているオブジェクトが適切な状態になるまで、追加のタイムスライスのために、当該スレッドをスケジュールしないように知ることができます。そうしないと、あなたは常に、再スケジュールコンテキストスイッチ-に、その後の時間のために実行してきているスレッドを持っています。

あなたは、具体的スレッドのプロセッサ時間を最小限に抑えることについて尋ねた:この例では、カーネルオブジェクト上でブロックするスレッドがZEROの時間を使用します。ポーリングスレッドは、時間のすべての種類を使用することになります。

さらに、「他の誰かがポーリング」引数が真である必要はありません。カーネルオブジェクトが適切な状態になると、カーネルは、スレッドは、そのオブジェクトを待っているその瞬間に見るために見て...そして実行のためにそれらの一つ以上のスケジュールを設定することができます。この場合には何もポーリングするカーネル(または他の誰)の必要はありません。

他のヒント

待機中動作するように、「よりよい」方法です。あなたがカーネルに待っているとき、あなたのスレッドは、それが無い仕事の準備ができていることをスケジューラによって知られているように任意のCPU時間を付与されることはありませんオブジェクト。あなたのスレッドは、条件が満たされた待つのCPU時間を与えられることになるだろう。あなたはどちら不CPUリソースを占有されないことを意味します。

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

待っているより多くのリソースを必要とすると、追加のコンテキストスイッチを意味しません。確かに、CLRモニタおよびWin32のクリティカル・セクションのようないくつかの同期プリミティブは、2フェーズロック・プロトコルを使用する - いくつかのスピン待ちがフォアが実際に真の待機をやって行われます。

私は非常に困難であろう二相のことをやって想像し、試験研究の多くを伴うだろう。だから、あなたは、時間とリソースを持って、窓のプリミティブに固執しない限り...彼らはすでにあなたのための研究をしました。

スピン待ちが理にかなっている/必要とされ、通常はOSの低レベルのものの中だけでいくつかの場所は、(ハンドラ/デバイスドライバを中断)があります。汎用アプリケーションは、ミューテックス/条件変数/セマフォのようないくつかの同期プリミティブで待機している、常にオフに優れています。

私はあなたのOSがまともな並行処理プリミティブを持っているならば、あなたがポーリングする必要はありません、Darksquidに同意します。ポーリングは通常、リアルタイムシステムやOSを持っていない制限付きハードウェア上でそれ自身に入ってくるあなたは(待つためのオプションを持っていない可能性がありますので、あなたは、ポーリングする必要がある)が、また、それはあなたが正確にどのくらいの期間にわたりfinegrainに制御することができますので、あなたは、スケジューラの慈悲であることと対照的に、特定の状態で待機します。

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

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

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

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

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

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

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

アプローチ #2 は多くの場合 #3 よりも複雑ですが、専用のスレッドを使用せずに単一のタイマーで多くのリソースを処理できるという利点があります。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top