どのようにキャッシュを高速化できますか?


37

キャッシュベンチマークのスクリーンショットは次のとおりです。

AIDA64 Cache&Memoryベンチマークの結果

ベンチマークでは、L1キャッシュの読み取り速度は約186 GB /秒で、レイテンシは約3〜4クロックサイクルです。そのような速度はどのように達成されますか?

ここでメモリを考えてみましょう:理論上の最大速度は665 MHz(メモリ周波数)x 2(ダブルデータレート)x 64ビット(バス幅)で、約10.6 GB / sであり、ベンチマーク値9.6 GB / sに近いです。

しかし、L1キャッシュを使用すると、最大周波数(3 GHz)のプロセッサーですべてのサイクルで読み取ることができたとしても、非現実的と思われるスループットを実現するには約496本のデータラインが必要になります。これは他のキャッシュにも適用されます。

私は何が欠けていますか?パラメータからキャッシュのスループットを計算するにはどうすればよいですか?


14
L1、2、3キャッシュがどれだけ小さいか、また物理的に存在する場所と同等に考えていますか。あなたはチップ全体を所有している場合ヒントは、あなたがバス規格との懸念に自分を必要としない
JonRB

2
また、ベンチマークは、テスト対象の一部のデータがレジスター内に直接保持されないようにするために何を行っているかについて十分に知っていますか?
rackandboneman

7
@rackandboneman:AIDA64は尊敬されるベンチマークであり、誰かがCでハックしてコンパイラーに負荷を最適化させただけのものではありません!マイクロベンチマークパーツは、SSEまたはAVXバージョンのアセンブリで記述されていると思います。
ピーターコーデス

1
@Peter Cordesの満足のいく答え-必要な質問へ。
rackandboneman

1
思考を物理的な視点に移すために、1.4ナノ秒で光は1フィート半ほど進みます。つまり、キャッシュがマザーボードの反対側にある場合、そのようなレイテンシは相対性を破壊する可能性があります。または、測定エラーになります
アーサー

回答:


35

このCPUには...

2コア各コアの32 KB命令と32 KBデータの一次キャッシュ(L1)

コアは2つあるため、ベンチマークでは2つのスレッドを並行して実行できます。しかし、彼らのウェブサイトはほとんど情報を提供しませんが、ここを見ると、より多くのコアを持つCPUが対応してより高いL1スループットを提供しているようです。表示されるのは、すべてのコアが並行して動作している場合の合計スループットです。したがって、CPUについては、1つのコアと1つのキャッシュに対して2で割る必要があります。

Read   93 GB/s
Write  47 GB/s
Copy   90 GB/s

現在、「コピー」は「書き込み」よりも2倍速いという事実は非常に疑わしいです。書き込み可能な速度よりも速くコピーする方法を教えてください。ベンチマークで「コピー」と表示されるのは読み取りと書き込みのスループットの合計であり、この場合は45 GB / sで読み取りと書き込みの両方が行われますが、ベンチマークであるため90が表示されます。誰がベンチマークを信頼しているのですか?それでは、「コピー」を無視しましょう。

Read   93 GB/s => 30 bytes/clock
Write  47 GB/s => 15 bytes/clock

現在、1つの128ビットレジスタは16バイトで十分に近いため、このキャッシュは1クロックあたり2つの128ビット読み取りと1つの書き込みを実行できるようです。

これはまさに、SSEの数値計算命令(サイクルごとに2回の読み取りと1回の書き込み)を本当に合理化することです。

これは多くの並列データラインで実装される可能性が最も高く、これはチップ内で非常に高速に大量のデータを持ち歩く通常の方法です。


4
ドキュメントの55ページに@ next-hackリンクがあります。「内部的には、アクセスは最大16バイトです。[...]サイクルごとに2つのロード操作と1つのストア操作を処理できます」。これが、読み取りが2倍高速である理由を説明しています。同じ操作で2回の読み取りを行うことができ、同時に1回の書き込みを行うことができます。
トムカーペンター

2
はい、明らかにコピーBW =読み取りと書き込みをカウントしています。読み取りと書き込みを並行して実行できることが重要なので、これは代替案と同じように有効だと思われます。L2 / L3のOPのコピーには、書き込みよりも大きくなく、メモリのコピーが少ないことに注意してください。DDR3メモリバスは全二重ではありません。読み取りと書き込みには同じデータラインが必要です。(NTストアと通常のストアのx86 memcpy / memset帯域幅の詳細については、stackoverflow.com / questions / 43343231 /…を参照してください)。
ピーターコーデス

6
IvyBridge は同じクロックサイクルで2回の読み取り 1回の書き込みを実行できると推測しています。あなたはたまたま正しいですが、非常に限られた状況下でのみです。IvBにはAGUポートが2つしかないため、通常は1クロックあたり2つのメモリ操作に制限され、そのうち1つがストアになります。ただし、256b AVXロード/ストアは、ロード/ストアポートで実行するのに2サイクルかかりますが、最初のサイクルではAGUのみが必要です。したがって、ストア帯域幅uopは、ロード帯域幅を犠牲にすることなく、256bロードの2回目のサイクル中にポート2/3で実行できます。(ストアデータuopsはポート4で実行されます。)ソース:agner.org/optimize microarch pdf
Peter Cordes

2
AMD BulldozerファミリーまたはRyzen CPUは、同じ読み取り= 2xの書き込み数を提供しますが、実際には、1クロックあたり2メモリ操作に制限されます(書き込みは1つまで可能)抜け穴はありません。読み取り/書き込み/コピーは違いを検出しませんが、Triadは検出できます(a[i] = b[i] + c[i])。ところで、Intel Haswell以降では、ポート7にストアAGUがあり、単純な(インデックスなし)アドレス指定モードを処理できるため、クロックごとに2ロード+ 1ストアuopを実行できます。(それはL1Dの帯域幅を倍増させそしてL1Dへのデータパスは、256Bである。)を参照してくださいデイビット・カンターの書き込みアップ:realworldtech.com/haswell-cpu/5
ピーター・コルド

1
@AliChen:OPは、帯域幅の直後にIvyBridgeの4サイクルの負荷使用レイテンシを明示的に言及してから、どのように高速化できるかを尋ねました。
ピーターコーデス

27

@peufeuの回答は、これらがシステム全体の集約帯域幅であることを指摘しています。L1とL2はIntel Sandybridgeファミリーのコアごとのプライベートキャッシュであるため、その数はシングルコアの2倍です。しかし、それでもなお、非常に高い帯域幅と低いレイテンシーが残っています。

L1DキャッシュはCPUコアに直接組み込まれており、ロード実行ユニット(およびストアバッファー)と非常に緊密に結合されています。同様に、L1Iキャッシュはコアの命令フェッチ/デコード部分のすぐ隣にあります。(私は実際にSandybridgeシリコンフロアプランを見ていないので、これは文字通り真実ではないかもしれません。フロントエンドの問題/名前変更部分は、おそらく「L0」デコードされたuopキャッシュに近いでしょう。デコーダーより。)

しかし、L1キャッシュでは、たとえすべてのサイクルで読み取ることができたとしても...

停止する理由 Sandybridge以降のIntelおよびK8以降のAMDは、サイクルごとに2つのロードを実行できます。マルチポートキャッシュとTLBは重要です。

David KanterのSandybridgeマイクロアーキテクチャの記事には、素晴らしい図があります(これはIvyBridge CPUにも当てはまります)。

(「統一スケジューラは」ALUとメモリのuopは、それらの入力を準備するのを待っている、および/またはその実行ポートを待って保持している。(例えばvmovdqa ymm0, [rdi]デコードのために待機しなければならない負荷UOPにrdi以前の場合add rdi,32のために、まだ実行されていません例) 。Intelは発行/名前変更時にuopをポートにスケジュールします。この図はメモリuopの実行ポートのみを示していますが、未実行のALU uopも競合します。発行/名前変更ステージはuopをROBとスケジューラに追加します。彼らは、引退するまでROBに留まりますが、スケジューラーには実行ポートへのディスパッチまでしかありません(これはIntelの用語です。他の人は問題とディスパッチを異なる方法で使用します)。 AMDは整数/ FPに個別のスケジューラを使用しますが、アドレス指定モードでは常に整数レジスタを使用します

David KanterのSnBメモリダイアグラム

それが示すように、2つのAGUポートのみがあります(アドレス生成ユニットは、 [rdi + rdx*4 + 1024]を採用し、線形アドレスを生成します)。クロックごとに2つのメモリ操作(128b / 16バイト)を実行でき、そのうちの1つがストアになります。

ただし、SnB / IvBは256b AVXロード/ストアを単一のuopとして実行し、ロード/ストアポートで2サイクルかかりますが、最初のサイクルではAGUのみが必要です。これにより、ロードスループットを失うことなく、2番目のサイクル中にポート2/3のAGUでストアアドレスuopを実行できます。したがって、AVX(Intel Pentium / Celeron CPUは:/をサポートしていません)を使用すると、SnB / IvBは(理論上)2つの負荷維持できサイクルごとに 1つのストアをます。

IvyBridge CPUは、Sandybridgeのダイシュリンクです(mov-eliminationなどのマイクロアーキテクチャの改善がいくつかあります)、ERMSB(memcpy / memset)、および次ページのハードウェアプリフェッチます)。その後の世代(Haswell)は、AVX 256bの負荷がクロックあたり2を維持できるように、実行ユニットからL1へのデータパスを128bから256bに広げることにより、クロックあたりのL1D帯域幅を2倍にしました。また、単純なアドレッシングモード用に追加のstore-AGUポートを追加しました。

Haswell / Skylakeのピークスループットは96バイトのロード+クロックあたりの格納ですが、Intelの最適化マニュアルでは、Skylakeの持続的な平均スループット(L1DまたはTLBミスがないと仮定)はサイクルあたり〜81Bであると示唆しています。(スカラー整数ループは、SKLでのテストよると、 4つの融合ドメインuopからクロックごとに7(非融合ドメイン)uopを実行すると、クロックあたり2ロード+ 1ストアを維持できます。しかし、64ビットオペランドではなく、 32ビットなので、明らかにマイクロアーキテクチャのリソース制限があり、ストアアドレスuopをポート2/3にスケジュールし、負荷からサイクルを盗むだけの問題ではありません)

パラメータからキャッシュのスループットを計算するにはどうすればよいですか?

パラメータに実際的なスループットの数値が含まれていない限り、できません。上記のように、SkylakeのL1Dでさえ、256bベクターのロード/ストア実行ユニットに十分に対応できません。それは近いですが、32ビット整数でも可能です。(キャッシュの読み込みポートよりも多くの負荷ユニットを使用することは意味がありません。逆も同様です。完全に利用できないハードウェアはそのままにしておきます。 /他のコアから、およびコア内からの読み取り/書き込み用。

データバスの幅とクロックを見るだけでは、全体像がわかりません。 L2およびL3(およびメモリ)帯域幅は、L1またはL2が追跡できる未解決のミスの数によって制限される場合があります。帯域幅はレイテンシ* max_concurrencyを超えることはできません。また、レイテンシが高いL3(メニーコアXeonなど)のチップは、同じマイクロアーキテクチャのデュアル/クアッドコアCPUよりもシングルコアL3帯域幅がはるかに少なくなります。このSO回答の「レイテンシー制限プラットフォーム」セクションを参照してください。SandybridgeファミリのCPUには、L1Dミスを追跡するための10個のラインフィルバッファがあります(NTストアでも使用されます)。

(多くのコアがアクティブなL3 /メモリの総帯域幅は、大きなXeonでは巨大ですが、シングルスレッドコードは、同じクロック速度でクアッドコアよりも帯域幅が悪くなります。レイテンシーL3。)


キャッシュ遅延

そのような速度はどのように達成されますか?

L1Dキャッシュの4サイクルのロード使用レイテンシは非常に驚くべきもので、特にのようなアドレス指定モードで開始する必要があることを考えると[rsi + 32]仮想アドレスを持つ前に追加を行う必要があります。次に、それを物理に変換して、キャッシュタグの一致を確認する必要があります。

[base + 0-2047]Intel Sandybridgeファミリーで余分なサイクルを取る以外のモードに対処するため、AGUには単純なアドレス指定モードのショートカットがあります(通常、低負荷使用レイテンシが最も重要であるが一般的に一般的なポインター追跡の場合) (Intelの最適化マニュアル、Sandybridgeセクション2.3.5.2 L1 DCacheを参照してください。)これは、セグメントオーバーライドがなく、セグメントベースアドレスが0であると想定しています。これは通常です。

また、ストアバッファーをプローブして、以前のストアと重複していないかどうかを確認する必要があります。また、以前の(プログラム順で)store-address uopがまだ実行されていない場合でも、これを把握する必要があるため、store-addressは不明です。ただし、これはL1Dヒットのチェックと並行して発生する可能性があります。ストアフォワーディングがストアバッファーからデータを提供できるため、L1Dデータが不要であることが判明した場合、それは損失ではありません。

Intelは、他のほとんどすべての人と同じようにVIPT(Virtually Indexed Physically Tagged)キャッシュを使用し、キャッシュを十分小さく、十分に高い連想性を持たせて、PIPTの速度でPIPTキャッシュ(エイリアスなし)のように動作するという標準的なトリックを使用します(インデックスを作成できます) TLB virtual-> physical lookupと並行して)。

IntelのL1キャッシュは32kiB、8ウェイアソシアティブです。ページサイズは4kiBです。これは、「インデックス」ビット(特定の行をキャッシュできる8つの方法のセットを選択する)がすべてページオフセットより下にあることを意味します。つまり、これらのアドレスビットはページへのオフセットであり、仮想アドレスと物理アドレスで常に同じです。

それについての詳細と、小型/高速キャッシュが有用/可能な理由(および、より大きな低速キャッシュと組み合わせた場合にうまく機能する理由)の詳細については、L1DがL2よりも小さい/速い理由についての私の答えを参照してください。

タグを取得すると同時にセットからデータ配列を取得するなど、小さなキャッシュは大きなキャッシュでは電力が高すぎることを実行できます。そのため、コンパレーターが一致するタグを見つけると、SRAMから既にフェッチされた8つの64バイトキャッシュラインの1つを多重化するだけで済みます。

(実際にはそれほど単純ではありません。Sandybridge/ Ivybridgeは、16バイトチャンクの8つのバンクを備えたバンクL1Dキャッシュを使用します。 (8つのバンクがあるため、これは128の倍数のアドレス、つまり2つのキャッシュラインで発生する可能性があります。)

IvyBridgeは、64Bキャッシュライン境界を超えない限り、非境界整列アクセスのペナルティもありません。下位アドレスビットに基づいてどのバンクをフェッチするかを把握し、正しい1〜16バイトのデータを取得するために必要なシフトを設定します。

キャッシュラインの分割では、1つのuopのみですが、複数のキャッシュアクセスを行います。4kスプリットを除き、ペナルティはまだ小さいです。Skylakeは、複雑なアドレッシングモードでの通常のキャッシュライン分割と同じように、4k分割でさえも、約11サイクルのレイテンシーでかなり安くします。ただし、4k分割のスループットは、cl分割の非分割よりも著しく悪化します。


ソース


1
それは非常に明確で、網羅的で、よく書かれています!+1!
ネクストハック

8

最新のCPUでは、キャッシュメモリは同じダイ(チップ)のCPUのすぐ隣にあり、PCのRAMモジュールに使用されるDRAMよりもはるかに高速なSRAMを使用して作られています。

メモリの単位(ビットまたはバイト)あたり、SRAMはDRAMよりもはるかに高価です。だからこそ、DRAMはPCでも使用されています。

ただし、SRAMはCPU自体と同じ技術で作られているため、CPUと同じくらい高速です。また、内部バス(CPU上)のみを処理するため、496行幅のバスが必要な場合はおそらくそうです。


ご関心をお寄せいただきありがとうございます。レジスタアクセス速度が300 GB / sを超えると書かれた本をいくつか見たことがあります。この場合、3 GHzプロセッサの場合、レジスタスループットは100 B /サイクルですが、レジスタは通常64/128ビット幅であるため、それらはそれほど出力できませんでした。これが私に関することです。GB / saはスループットを表現する正しい方法です。
ナイト

3
@Knightは、IvB(任意の高性能プロセッサーとして)がサイクルごとに3つのALU操作、2つのロード、1つのストアなどのいくつかの命令を実行することに留意してください。これらのほとんどは、2つの入力(インデックス付きアドレッシングの場合でもロード)を取り、ロードは3を取ります。つまり、それぞれ8バイト、104バイトの13レジスタです(このような叙事詩の組み合わせが許可されていない場合もありますが、 IvBに当てはまることを示すものではありませんが、持続することはできません。ベクトルレジスタも考慮すると、その数はさらに大きくなります。
ハロルド

@harold:関連:HaswellとSkylakeには、クロックあたりのレジスタ読み取りに制限があるようですが、これはフロントエンドにある可能性があり、一部の入力が準備できた後の実行のバーストには影響しません。他のマイクロアーキテクチャの制限かもしれませんが、コードあたりのボトルネックを発見し、クロックあたりの操作数を増やすことができるはずです。 agner.org/optimize/blog/read.php?i=415#852。Haswellでは、私の最高のシナリオでは、クロックサイクルごとに〜6.5個の整数レジスタを読み取ります(持続)。また、Skylakeでのディスパッチ/実行クロックごとに持続的な7 uopを取得することができました(ストアはstore-address + store-dataです)。
ピーターコーデス

@PeterCordesはフロントエンドである必要がありますか?歴史的にも問題であったIIRC(PProからCore2)およびそれ以外の場合に小数がどのように意味をなすかはわかりません。とにかく私の数字は少しずれていましたが
ハロルド

@harold:ええ、それは何らかの名前のフロントエンドのボトルネックであると確信しています。P6のレジスタ読み取りのボトルネックは、永続レジスタファイルから問題のROBに読み込む必要がある「コールド」レジスタにありました。最近変更されたレジスタはまだROBにあり、ボトルネックはありませんでした。何らかの理由でループを反復あたり4 uops /理想的には1cより大きくすることを考えていなかったため、HSW / SKLのコールドとホットのレジスタについてはあまり調査しませんでした。おっとっと。IDK転送とPRF読み取りの差(実行/発行ではなく、発行/名前の変更が必要)。
ピーター・コーデス

4

L1キャッシュはかなり広いメモリ構造です。IntelプロセッサのL1キャッシュのアーキテクチャは、このマニュアル(next-hackで提供)に記載されています。ただし、一部のパラメーターの解釈は正しくありません。「キャッシュラインサイズ」は「データ幅」ではなく、アトミックデータアクセスのシリアルブロックのサイズです。

表2-17(セクション2.3.5.1)は、負荷(読み取り)のキャッシュ帯域幅が2x16 = CYCLEあたりコアあたり32バイトである。これだけでも、3GHzコアで96 Gb / sの理論帯域幅が得られます。引用されたベンチマークが何を報告しているかは明らかではありません。2つのコアが並行して動作しているように見えるため、2つのコアで192 Gbpsになります。


2

ゲート遅延は何ですか?10ピコ秒?パイプライン化された操作全体のサイクル時間は333ピコ秒で、次のクロックサイクルが始まる前にさまざまなデコードおよびバスアクティビティとフリップフロップでデータを取得します。

キャッシュの読み取りで最も遅いアクティビティは、データラインが十分に離れるのを待っていることを期待しています(おそらく、これらは差分です:1つのリファレンスと1つの実際の充電ビットからの電荷)、コンパレータ/ラッチをクロックして正の小さな電圧を大きなレールツーレールロジックレベルの電圧スイング(約1ボルト)に変換するフィードバックアクション。


1
4サイクルのL1Dレイテンシには、アドレス生成(の単純なアドレッシングモードの場合[reg + 0-2047])、TLBルックアップ、およびタグ比較(8ウェイアソシエイティブ)が含まれ、結果の16バイトまでの非アライメントバイトがロードユニットの出力ポート、他の実行ユニットへの転送用。のようなポインター追跡ループでは4cのレイテンシーですmov rax, [rax]
ピーターコーデス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.