web-dev-qa-db-ja.com

アウトオブオーダー実行と投機的実行

順不同実行投機的実行 に関するウィキペディアのページを読みました。

私が理解できないのは、類似点と相違点です。たとえば、条件の値を決定していない場合、投機的実行はアウトオブオーダー実行を使用しているようです。

メルトダウンとスペクターの論文を読み、さらに研究を行ったとき、混乱が生じました。 メルトダウンペーパー に記述されているように、Meltdownは順不同の実行に基づいていますが、 sepeculative execution に関するWikiページを含む他のいくつかのリソースは、Meltdownが基づいていると述べています投機的実行。

これについていくつかの説明をお願いします。

12
Name

投機的実行と順不同実行は直交します。プロセッサをこのOoOで設計することはできますが、投機的または投機的ではありませんが、順序どおりに設計できます。 OoOの実行は、プログラムの順序とは異なる順序で命令を実行できる実行モデルです。ただし、命令は引き続きプログラムの順序で破棄されるため、プログラムの観察された動作は、プログラマーが直感的に期待する動作と同じになります。 (ただし、特定の制約により、不自然な順序で命令をリタイアするOoOプロセッサを設計することは可能です。この考えに関するシミュレーションベースの研究を参照してください: 限られたリソースの最大化:制限ベースの研究と分類法順不同のコミット )。

投機的実行とは、大まかに言って、命令がフェッチされてパイプラインに入り、実際に実行する必要があるかどうかさえ(プログラムの制御フローに従って)知らなくても実行を開始できる実行モデルです。また、この用語は、パイプラインの実行段階での投機的実行を具体的に指す場合にもよく使用されます。メルトダウンペーパーは、3ページでこれらの用語を定義しています。

このホワイトペーパーでは、分岐に続く命令シーケンスを指す、より限定的な意味での投機的実行を参照し、プロセッサが実行される前に操作を実行する方法を指すために、順不同実行という用語を使用します。以前のすべての指示の結果をコミットしました。

命令は投機的に実行できるが、順序どおりに実行できることに注意してください。パイプラインのデコードステージが条件付き分岐命令を識別すると、分岐とそのターゲットを推測し、予測されたターゲット位置から命令をフェッチできます。しかし、それでも、命令を順番に実行することもできます。ただし、推測された条件付き分岐命令と予測されたパス(または両方のパス)からフェッチされた命令が発行ステージに到達すると、以前のすべての命令が終了するまで、それらは発行されません。それが発生すると、プロセッサは予測が正しいかどうかを認識し、それ以外の場合はパイプラインをフラッシュします。

単純なタスクを実行するように設計され、組み込みシステムやIoTデバイスで使用されるプロセッサーは、通常、投機的でもOoOでもありません。デスクトップとサーバーのプロセッサは、どちらも投機的であり、OoOです。コンピューティングスペクトラム(携帯電話とマイクロコントローラー)の真ん中にOoOであるが、投機的ではないプロセッサー( ARM Cortex-など)があります。 A9 )。 Intel Bonnellマイクロアーキテクチャーは投機的ですが、順序どおりです。投機的実行は、OoOと併用すると特に有益です。

メルトダウンとスペクターの論文を読み、さらに研究を行ったとき、混乱が生じました。 Meltdownは順不同の実行に基づいているとMeltdownペーパーで述べられていますが、Meltdownは投機的実行に基づいている具体的な実行状態に関するwikiページを含む他のリソースもあります。

このホワイトペーパーで説明されているメルトダウンの脆弱性には、投機的実行と順不同実行の両方が必要です。ただし、これには、さまざまな投機的実行と順序外の実行の実装があるため、これはやや曖昧なステートメントです。 Meltdownは、あらゆるタイプのOoOまたは投機的実行では機能しません。たとえば、 ARM11 (Raspberry Pisで使用)は、一部の限定されたOoOと投機的実行をサポートしますが、脆弱ではありません。

Meltdownと彼の他の answer の詳細については、ピーターの回答を参照してください。

関連: スーパースカラーとOoO実行の違いは何ですか?

10
Hadi Brais

Meltdownが投機的実行をどのように使用するかを理解するのにまだ苦労しています。論文の例(前述の例と同じ)ではIMOのみを使用していますOoO- @ Name in a comment

Meltdownは楽観的にIntel CPUに基づいています推測負荷に障害は発生せず、障害のある負荷がロードポートに到達した場合、それは以前の誤って予測された分岐の結果でした。したがって、ロードuopにマークが付けられるため、リタイアに達するとエラーになりますが、実行は投機的に続行されますデータを使用して、ページテーブルエントリは、ユーザースペースからの読み取りが許可されていません

負荷の実行時にコストのかかる例外回復をトリガーする代わりに、確実にリタイアするまで待機します。これは、機械が分岐ミス->悪い負荷のケースを処理するための安価な方法だからです。ハードウェアでは、needでない限り、パイプがパイプを維持する方が簡単です。例えばページテーブルエントリがまったくないロード、つまりTLBミスがあるロードは待機する必要があります。ただし、TLB hit(それを使用することをブロックするアクセス許可を持つエントリの場合)でも待機すると、さらに複雑になります。通常、ページフォールトは、ページウォークの失敗(仮想アドレスのエントリが見つからない)の後、またはロードまたはストアのリタイア時に、ヒットしたTLBエントリのアクセス許可に失敗した後にのみ発生します。

最新のOoOパイプライン化されたCPUでは、all命令はリタイアまで投機的に扱われます。退職時にのみ、指示は非投機的になります。 Out-of-Order機構は、予測されたがまだ実行されていないブランチの片側を推測しているのか、過去に障害が発生している可能性のある負荷を推測しているのか、実際には知りません。ロードが失敗しない、またはALU命令が例外を発生させない「推測」 実際には推測とは見なされないCPUでも発生します が、完全に順不同の実行はそれを別の種類に変えます憶測の。

「投機的実行」の正確な定義、何が重要で何が重要でないのかについてはあまり心配していません。現代のアウトオブオーダーデザインが実際にどのように機能するか、そしてパイプラインの終わりまで投機的と非投機的を区別しようとさえしない方が実際には簡単であることに私はより興味があります。この答えは、(分岐予測に基づく)投機的な命令フェッチでより単純な順序のパイプラインに対処しようとはしていませんが、実行、またはそれとの間のどこにもありません ROB +スケジューラーを備えた本格的なTomasuloのアルゴリズム OoO exec +正確な例外のための適切なリタイア。

たとえば、afterリタイアメントのみが、ストアバッファーからL1dキャッシュにコミットすることができます。また、ショートバーストやキャッシュミスを吸収するために、リタイアの一環として発生する必要もありません。したがって、唯一の非投機的な順不同の1つは、ストアをL1dにコミットすることです。アーキテクチャの状態に関する限り、これらは確実に発生しているため、割り込み/例外が発生した場合でも、それらを完了する必要があります。

障害が発生した場合にリタイアするメカニズムは、ブランチの予測ミスの陰でコストのかかる作業を回避するための良い方法です。また、例外が発生した場合に、CPUに適切なアーキテクチャ状態(レジスタ値など)を提供します。 OoO機構に、例外を検出したポイントを超えて命令を継続させるかどうかにかかわらず、それは必要です。


ブランチミスは特別です:ブランチでmicro-architectural state(register-allocationのような)を記録するバッファーがあるため、ブランチリカバリは、パイプラインをフラッシュして最後の既知の正常なリタイア状態から再開するのではなく、その状態にロールバックできます。ブランチは実際のコードではかなりの量を誤って予測します。他の例外は非常にまれです。

最新の高性能CPUは、分岐ミス前のuopsの実行を(順不同)維持し、その時点以降のuopsと実行結果を破棄できます。高速リカバリは、予測ミスが発見された時点から大幅に遅れている可能性がある退職状態からすべてを破棄して再起動するよりもはるかに安価です。

例えば。ループでは、ループカウンターを処理する命令がループ本体の残りの部分よりもはるかに先に行き、フロントエンドをリダイレクトするのに十分なだけ早く最後に​​誤予測を検出し、特にボトルネックの場合、実際のスループットをそれほど失うことはない依存関係チェーンのレイテンシまたはuopスループット以外の何かでした。

この最適化された回復メカニズムはブランチにのみ使用されます(状態スナップショットバッファーが制限されているため)。これにより、完全なパイプラインフラッシュと比較してブランチミスが比較的安価になります。 (例:Intelでは、メモリ注文マシンがクリアされ、パフォーマンスカウンターmachine_clears.memory_orderingハイパー兄弟と非ハイパー兄弟間でのメモリロケーションのプロデューサー/コンシューマー共有のレイテンシおよびスループットコストは?


ただし、例外は前例のないものではありません。ページフォールトは、通常の操作中に発生します。例えば読み取り専用ページに保存すると、コピーオンライトがトリガーされます。マップされていないページをロードまたは保存すると、ページインまたは遅延マッピングの処理がトリガーされます。しかし、新しいメモリを頻繁に割り当てているプロセスであっても、通常、ページ違反のたびに数千から数百万の命令が実行されます。 (1GHz CPUではマイクロ秒またはミリ秒ごとに1つ)。新しいメモリをマップしないコードでは、例外なくはるかに長く進むことができます。ほとんどの場合、I/Oなしの純粋な数値処理では、タイマー割り込みだけが時々発生します。

しかし、とにかく、例外が実際に発生するsureになるまで、パイプラインのフラッシュや高価なものをトリガーする必要はありません。そして、あなたはright例外があることを確信しています。例えばおそらく、以前の障害のあるロードのロードアドレスはすぐに準備ができていなかったため、実行する最初の障害のあるロードは、プログラムの順序では最初ではありませんでした。退職するまで待つことは、正確な例外を取得するための安価な方法です。このケースを処理するための追加のトランジスタという点で安価であり、通常の順序付けられたリタイアメント機構に、どの例外が発動するかを正確に判断させます。

退職時にフォールトとマークされた命令の後に命令を実行する無駄な作業は、ほんの少しの電力を要し、例外は非常にまれであるため、ブロックする価値はありません。

これは、そもそもMeltdownに対して脆弱なハードウェアを設計することが理にかなっている理由を説明しています。明らかにnot保持しても安全ですメルトダウンが考えられている今、これを行う。


メルトダウンを安く修正する

障害のあるロードの後に​​投機的実行をブロックする必要はありません。実際に機密データを使用しないようにする必要があるだけです。問題は、ロードが投機的に成功することではありません。メルトダウンは、次の命令に基づいて、そのデータを使用してデータ依存のマイクロアーキテクチャ効果を生成します。 (例えば、データに基づいてキャッシュラインに触れる)。

そのため、ロードポートがロードされたデータをゼロまたは何かにマスクし、リタイアメントフラグを設定すると、実行は続行されますが、シークレットデータに関する情報を取得できません。これには、クリティカルパスのゲート遅延が約1増えるはずです。これは、クロックポートを制限したり、レイテンシのサイクルを追加したりせずに、ロードポートでおそらく可能です。 (1クロックサイクルは、ロジックがパイプラインステージ内の多くのAND/ORゲート(たとえば、完全な64ビット加算器)を伝搬するのに十分な長さです)。

関連:私は なぜAMDプロセッサはMeltdownとSpectreに対して脆弱ではない/それほど脆弱ではないのですか? のMeltdownのHW修正に対して同じメカニズムを提案しました。

4
Peter Cordes