web-dev-qa-db-ja.com

x86の一時停止命令は、スピンロックでどのように機能し、他のシナリオでも使用できますか?

一時停止命令は、テストのループで一般的に使用されます spinlock 、他のスレッドがスピンロックを所有している場合、タイトなループを緩和します。一部のNOP命令と同等と言われています。誰かがそれがスピンロック最適化にどのように機能するか正確に教えてもらえますか? NOP命令でさえCPU時間の浪費であるように私には思えます。彼らはCPU使用率を減らしますか?

別の質問は、他の同様の目的で一時停止命令を使用できるかどうかです。たとえば、新しいノードを取得するためにいくつかの場所(キューなど)をスキャンし続けるビジースレッドがあります。ただし、キューが空で、スレッドがCPU時間を浪費していることがあります。スレッドをスリープ状態にし、他のスレッドによってウェイクアップすることもできますが、スレッドは重要であるため、スリープ状態にしたくありません。 CPU使用率を軽減する目的で、命令の作業を一時停止できますか?現在、物理コアの100%cpuを使用していますか?

ありがとう。

39
Infinite

[〜#〜] pause [〜#〜] は、これがスピンロック待機ループであることをCPUに通知し、メモリとキャッシュアクセスが最適化されるようにします。スピンループを離れるときのメモリ順序の推測の回避に関する詳細については、 x86の一時停止命令 も参照してください。

PAUSEは、電力を節約するために実際にはしばらくCPUを停止する場合があります。古いCPUではREP NOPとしてデコードされるため、サポートされているかどうかを確認する必要はありません。古いCPUは、できるだけ速く何もしない(NOP)。

参照 https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops


更新:キューをスピンロックのようにするつもりでなければ(そしてそれを行う明確な方法がない)、キューのチェックでPAUSEを使用することは良い考えではないと思います。

PAUSEを使用しても、非常に長い時間回転することは依然として非常に悪いです。

28
blaze

プロセッサは、メモリの順序違反の可能性を検出するため、ループを終了するとパフォーマンスが大幅に低下します。 PAUSE命令は、コードシーケンスがスピンウェイトループであるというヒントをプロセッサに提供します。プロセッサはこのヒントを使用して、ほとんどの状況でメモリ順序違反を回避します。これにより、プロセッサのパフォーマンスが大幅に向上します。このため、すべてのスピン待機ループにPAUSE命令を配置することをお勧めします。 PAUSE命令の追加機能は、Intelプロセッサが消費する電力を削減することです。

[ソース:Intelマニュアル]

14
Nitin Kunal

Intelは、スピンループが非常に短い場合にのみPAUSE命令を使用することを推奨します。

あなたの質問から理解したように、あなたの場合の待機は非常に長いです。この場合、スピンループは推奨されません。

あなたは「新しいノードを取得するためにいくつかの場所(例えばキュー)をスキャンし続けるスレッド」を持っていると書いた。

そのような場合、インテルはオペレーティングシステムの同期API関数を使用することをお勧めします。たとえば、新しいノードがキューに表示されたときにイベントを作成し、WaitForSingleObject(Handle, INFINITE)を使用してこのイベントを待つだけです。キューは、新しいノードが表示されるたびにこのイベントをトリガーします。

インテル最適化マニュアルによると、PAUSE命令は通常、同じプロセッサーコアにある2つの論理プロセッサーで実行されるソフトウェアスレッドで使用され、ロックが解放されるのを待ちます。このような短い待機ループは、数十から数百サイクル(つまり、20〜500 CPUサイクル)の間続く傾向があるため、OSに譲るよりもCPUを占有している間待機する方がパフォーマンス面で有利です。

4500 MHzのCore i7 7700Kプロセッサでの500 CPUサイクルは0.0000001秒、つまり1秒の1/10000000秒です。CPUは、この500 CPUサイクルで1秒間に1000万回をループさせることができます。

ご覧のとおり、このPAUSE命令は本当にshort期間用です。

一方、Sleep()などのAPI関数を呼び出すたびに、コンテキストスイッチのコストがかかります。また、リング3からリング0への遷移(1000以上のサイクル)のコストもかかります。

さらに多くのスレッドがある場合、プロセッサコア(存在する場合はハイパースレッディング機能に乗算されます)が利用可能であり、スレッドはクリティカルセクションの途中で別のスレッドに切り替えられ、別のスレッドからのクリティカルセクションを待機するのは実際にかかる可能性がありますlooong、少なくとも10000+サイクルなので、PAUSE命令は無駄になります。

詳細については、次の記事を参照してください。

待機ループが数千サイクル以上続くことが予想される場合、Windows OSのWaitForSingleObjectなどのOS同期API関数の1つを呼び出して、オペレーティングシステムに譲ることが望ましいです。

結論として:シナリオでは、PAUSEは非常に短いループを対象としていますが、待ち時間が長いため、PAUSE命令は最良の選択ではありません。一時停止は、131サイクルのSkyWell以降のプロセッサです。たとえば、Intel Core i7-7700K CPU @ 4.20GHz Kaby Lakeでは、わずか31.19nsです。

Haswellのような以前のプロセッサでは、約9サイクルあります。 Intel Core i5-4430 @ 3GHzでは2.81nsです。したがって、長いループでは、PAUSEループでCPUを占有するよりも、OS同期API関数を使用して他のスレッドに制御を放棄する方が良いです。

2
Maxim Masiutin

また、PAUSE命令はハイパースレッディングプロセッサでも使用されているようで、他のハイパースレッドへのパフォーマンスへの影響を軽減します。

次のIntelの記事はこれを概説しており、当然のことながら、そのようなプロセッサーでビジーな待機ループを回避することを推奨しています: https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on -hyper-threading-technology-enabled-intel-processors

1
egbit