Real World Technologies ’の記事「 Intel’s Sandy Bridge Microarchitecture 」によると:
「SandyBridgeのuopキャッシュは、32セットと8ウェイに編成されており、1行あたり6 uopsで、合計1.5Kuopsの容量になります。 uopキャッシュは、L1命令キャッシュに厳密に含まれています。各行には、その行の有効なuopの数や、uopキャッシュ行に対応するx86命令の長さなどのメタデータも含まれています。 uopキャッシュにマップされる各32Bウィンドウは、セット内の8つの方法のうち3つにまたがることができ、最大18 uop(約1.8B/uop)になります。 32Bウィンドウに18uopsを超える場合、uopキャッシュに収まらないため、従来のフロントエンドを使用する必要があります。マイクロコード化された命令はuopキャッシュに保持されず、代わりにマイクロコードROMおよびオプションで最初のいくつかのuopsへのポインターによって表されます。」
「(命令キャッシュからの)各32Bウィンドウはuopキャッシュにマップされ、セットの8つの方法のうち3つにまたがることができます」
したがって、L1命令キャッシュラインの半分となる32B命令ウィンドウがあると仮定します。そのラインでは、オフセットビットのみが異なりますが、タグビットとセットビットはライン上のすべてのバイトで同じです。
32バイトのウィンドウがデコードされると、uopsはL1命令キャッシュから16バイトのフェッチブロックを取得するために使用されたのと同じ仮想アドレスでuopキャッシュに入力されます(32Bマージンごとに並列にプローブできるように)
これらのuopsは、セット内の8つの方法のうち3つにまたがることができると書かれていますが、同じセットになるには、同じセットビットが異なるタグビットが必要になることを意味します(つまり、それらはオンになっていないでしょう) L1Iキャッシュの同じ行)、これは、uopキャッシュの配置がわずかに異なり、行の先頭に1つの仮想アドレスがあり、uopsがセットの次の方法と次の方法でいっぱいになることを意味しますか?セットする。同じタグと同じセットビットを持ちながらオフセットビットが異なる次の32B命令ウィンドウ(L1Iの64 Bラインの後半)がそのセットの4番目の方法にマップされることをどのように保証しますか。
Postulation:uopキャッシュウェイは仮想インデックス物理タグでタグ付けされ、次のウェイは何もタグ付けされず、3番目は何もタグ付けされず、4番目はタグ付けされますオフセットが0から32に変更されたという違いがある仮想インデックス/物理タグ。したがって、本質的に、L1Iキャッシュがタグ付けされる方法とは対照的に、異なるオフセットビットを使用して方法を選択できます。オフセットビットはキャッシュラインのオフセット。
誰かがuopキャッシュのレイアウトや、このタグ付けが実際にどのように機能するかを明確にできますか?
AMD Zenにもuopキャッシュがありますが、その内部についてはあまり知られていません。つまり、SandybridgeファミリにあるIntelのuopキャッシュについて具体的に質問しているのです。
Agner Fogのテスト( https://www.agner.org/optimize/ 、特に彼のmicroarch pdf)によると、仮想的にアドレス指定され(VIVT)、uop-のiTLBルックアップのレイテンシー/パワーを節約します。キャッシュヒット。また、VIPT L1キャッシュの通常のように、iTLBをL1iキャッシュと非常に緊密に統合することを可能にします。
(関連: Intel Core i7プロセッサで使用されているキャッシュマッピング手法はどれですか? そのキャッシュと他のキャッシュの概要については https://stackoverflow.com/tags/x86/info パフォーマンスの向上/ uarchリンク。)
32バイトのウィンドウがデコードされたら
これはあなたがあなたの思考過程で間違っていたところです。
Uopキャッシュは、(投機的)実行のパスに沿ってデコードされるuopのみをキャッシュします。 x86命令は、正しい開始点がわかっている場合にのみ正しくデコードできます。無条件のjmp
の後のバイトは、命令の開始ではない可能性があります。
さらに、関数間の多くのシングルバイトフィラー命令でuopキャッシュを汚染したくない場合(例:0x90 NOPまたは 0xcc
int3
MSVCで使用)。または、一般に、分岐後の通常の実行では到達しない「コールド」命令を使用します。 uop-cache "line"/wayは、無条件ジャンプまたはcall
で早期に終了します。
レガシーデコーダーは、CPUが実際に実行することを期待する命令をデコードする(後で再利用するためにuopキャッシュにフィードするか、IDQを直接使用してすぐに使用する) )、または電源がオフになっています。 P4とは異なり、レガシーデコーダーは弱くありません。これらはCore2/Nehalemのデコーダーに似ているため、平均命令サイズが大きい高スループットコードを除いて、L1iからの実行は一般的に問題ありません。事前に「トレースの作成」を試みる必要はありません。 (uopキャッシュはnotとにかくトレースキャッシュではありません。ジャンプには従いません。しかし、とにかく、32命令バイトすべてのuopキャッシュにデータを入力しようとはしませんすぐにキャッシュできます。)
しかし興味深いことに、Agnerは、「同じコードに複数のジャンプエントリがある場合、μopキャッシュに複数のエントリを含めることができます」と述べています。
コードをフェッチする64ビットの仮想アドレスが与えられた場合:
5ビットインデックスを使用してセットを選択します。
そのセットから8つの方法すべてを取得します(タグ+メタデータ、およびこれは高性能キャッシュであるため、データを並列に取得します)。
8つの方法すべてを並行して比較します:
セット内の最大1つの方法で、特定の命令アドレスに対して両方の条件が真になります。1つある場合、これがヒットであり、フェッチできます。一致した一方向からのuops。 (通常のバイトキャッシュと同様ですが、メタデータをチェックして、途中でジャンプした場合にフェッチを開始するuopを選択する必要があります。)
これは、uopキャッシュがどのように実行され、いつウェイをスローするかに基づく推測です。しかし、それはあなたがそれの有用なメンタルモデルを得るのを助けるかもしれません。
アドレスは16バイトに揃える必要がないことに注意してください。整列されていないブランチターゲット、および32バイト境界と整列しない命令境界を持つ直線コードを効率的にサポートする必要があります。 (私が知る限り、32バイトの境界を越える命令は、64バイトの境界を越える次のL1iキャッシュラインで終了する場合でも、命令の開始アドレスに対してuop-cache方式でキャッシュされます。)
L1iフェッチブロック/命令長のプリデコードは調整されますが、レガシーデコーダーでの完全なデコードは、プリデコードとデコードの間のキューから取得された、最大16バイトの調整で機能します。ループエントリポイントの特定の配置境界への配置は、以前ほど重要ではありません。
次に、フェッチアドレスが選択した方法で命令の開始アドレスの1つと完全に一致するチェックがあると思います。難読化されたコードのみが同じバイトを2つの異なる方法でデコードするため、これは効率的にサポートされていません。
Uopキャッシュは両方の方法を同時にキャッシュできないため、これを検出すると、CPUはレガシーデコーダーにフォールバックし、この32Bブロック(タグコンパレータですでに検出されている)のuopキャッシュ方法を破棄する必要があります。
次に、この時点からuopsをデコードするときに、uop-cacheの再入力を開始できます。
3つのウェイがすでにいっぱいの場合にも同様のことが起こりますが、x86マシンコードの同じ32Bブロックからより多くのuopsがあります。 uop-cacheは、そのブロックの3つの方法すべてを破棄します。 (次回のためにそれらをキャッシュしようとしないことを覚えているのか、それとも毎回キャッシュを構築し、制限に達したときに20個のシングルバイトnop
たとえば指示。)
このケースの詳細については、 Intel SnBファミリCPUでのマイクロコード化された命令を含むループのブランチアラインメント を参照してください。 div
のようなマイクロコード化された命令は、それ自体でuopキャッシュ全体を使い果たし、3つの方法すべてがいっぱいになり、DSBからMITEへの切り替え(uopキャッシュからレガシーへ)がトリガーされる可能性があることに注意してください。デコードスイッチは、フロントエンドに1サイクルのバブルを作成する可能性があります)。
そのQ&Aには、uopsがどのようにキャッシュされるかについての詳細な実験と結論がたくさんあります。 uopキャッシュが物理的にどのように実装されているかについてはそれほど重要ではありません。これは、ここでの私の側の純粋な当て推量です。
また、Skylakeより前のIntel CPUは、uopキャッシュからIDQに4 uopしか追加できませんが、uopキャッシュに4ではなく3または6 uopの方法がある場合、どういうわけかボトルネックにならないことに注意してください。非分岐uopフェッチのバッファリングの概要。これは少し謎です。それぞれ6uopsのフルラインからフェッチする場合、フェッチは4、2、4、2のパターンで行われると予想されますが、2のuopキャッシュから実行されるループのようなフロントエンドのボトルネックは見られません。 -xor eax,eax
のようなバイト命令。 Intelは、uopキャッシュはサイクルごとに1ウェイからのみuopをフェッチできると述べています。したがって、4 uopの制限は、実際にはuopキャッシュからマージバッファーに読み取るためではなく、IDQに追加するためだけのものである可能性があります。