24

リトルの法則により、特定のレイテンシーと特定のレベルの同時実行でデータを転送できる速度が制限されることに気付きました。何かをより速く転送したい場合は、より大きな転送、「実行中」の転送の増加、または待ち時間の短縮のいずれかが必要です。RAM から読み取る場合、同時実行性は Line Fill Buffer の数によって制限されます。

ロードが L1 キャッシュをミスすると、Line Fill Buffer が割り当てられます。最新の Intel チップ (Nehalem、Sandy Bridge、Ivy Bridge、Haswell) は、コアあたり 10 個の LFB を備えているため、コアあたりの未解決のキャッシュ ミスは 10 個に制限されています。RAM レイテンシが 70 ns (妥当) で、各転送が 128 バイト (64B キャッシュ ラインとそのハードウェア プリフェッチ ツイン) の場合、コアあたりの帯域幅は 10 * 128B / 75 ns = ~16 GB/s に制限されます。シングルスレッドStreamなどのベンチマークは、これがかなり正確であることを確認しています。

レイテンシを短縮する明白な方法は、RAM から読み取る必要がないように、PREFETCHT0、PREFETCHT1、PREFETCHT2、または PREFETCHNTA などの x64 命令を使用して目的のデータをプリフェッチすることです。しかし、それらを使用しても何も高速化できませんでした。問題は、__mm_prefetch() 命令自体が LFB を消費するため、それらにも同じ制限が適用されることです。ハードウェア プリフェッチは LFB に触れませんが、ページの境界を越えることもありません。

しかし、私はこれがどこにも文書化されているのを見つけることができません。私が見つけた最も近いものは、15 年前の記事で、Pentium III でのプリフェッチは Line Fill Buffers を使用すると述べています。それ以来、状況が変わったのではないかと心配しています。また、LFB は L1 キャッシュに関連付けられていると思われるため、L2 または L3 へのプリフェッチでそれらが消費される理由がわかりません。それでも、私が測定した速度は、これが事実であることと一致しています.

では、これらの 10 個の Line Fill Buffer のいずれかを使い果たすことなく、メモリ内の新しい場所からフェッチを開始し、リトルの法則を回避してより高い帯域幅を実現する方法はありますか?

4

2 に答える 2

10

まず、マイナーな修正 -最適化ガイドを読むと、一部の HW プリフェッチャーが L2 キャッシュに属することに注意してください。したがって、フィル バッファーの数によって制限されるのではなく、対応する L2 によって制限されます。

「空間プリフェッチャー」(128B チャンクまで完了するコロケート 64B ライン) はその 1 つであるため、理論的には、1 行おきにフェッチすると、より高い帯域幅を取得できるようになります (一部の DCU プリフェッチャーは、 「あなたのためにギャップを埋めます」が、理論的には優先度を低くする必要があるため、機能する可能性があります)。

ただし、「キング」プリフェッチャーはもう 1 人の「L2 ストリーマー」です。セクション 2.1.5.4 には次のように書かれています。

Streamer : このプリフェッチャーは、L1 キャッシュからの読み取り要求を監視して、アドレスの昇順および降順シーケンスを監視します。監視対象の読み取り要求には、ロード操作とストア操作、およびハードウェア プリフェッチャーによって開始される L1 DCache 要求と、コード フェッチ用の L1 ICache 要求が含まれます。要求の順方向または逆方向のストリームが検出されると、予想されるキャッシュ ラインがプリフェッチされます。プリフェッチされたキャッシュ ラインは同じ 4K ページにある必要があります

重要な部分は -

ストリーマーは、L2 ルックアップごとに 2 つのプリフェッチ要求を発行する場合があります。ストリーマーは、ロード要求よりも最大 20 行先まで実行できます。

この 2:1 の比率は、このプリフェッチャーによって認識されるアクセスのストリームが常にアクセスよりも先に実行されることを意味します。これらの行が L1 に自動的に表示されないのは事実ですが、すべてがうまく機能している場合は、常に L2 ヒット レイテンシを取得する必要があることを意味します (プリフェッチ ストリームが先行して実行され、L3/メモリを軽減するのに十分な時間があれば)。レイテンシ)。LFB は 10 個しかないかもしれませんが、計算で指摘したように、アクセス遅延が短くなればなるほど、より高速に交換でき、より高い帯域幅に到達できます。これは本質的に、レイテンシをとL1 <-- memの並列ストリームに切り離すことです。L1 <-- L2L2 <-- mem

見出しの質問については、L1 を埋めようとするプリフェッチで、そのレベルで取得したデータを保持するためにライン フィル バッファが必要になるのは当然のことです。これには、おそらくすべての L1 プリフェッチが含まれるはずです。SW プリフェッチに関しては、セクション 7.4.3 に次のように記載されています。

PREFETCH がデータのプリフェッチを実行しない場合があります。これらには以下が含まれます:

  • PREFETCH は DTLB (Data Translation Lookaside Buffer) ミスを引き起こします。これは、ファミリ 15、モデル 0、1、または 2 に対応する CPUID シグネチャを持つ Pentium 4 プロセッサに適用されます。 PREFETCH は、DTLB ミスを解決し、ファミリ 15、モデル 3 に対応する CPUID シグネチャを持つ Pentium 4 プロセッサでデータをフェッチします。
  • フォールト/例外を引き起こす指定されたアドレスへのアクセス。
  • メモリ サブシステムが、第 1 レベルのキャッシュと第 2 レベルのキャッシュの間の要求バッファーを使い果たした場合。

...

だから私はあなたが正しいと思います.SWプリフェッチは、未処理のリクエストの数を人為的に増やす方法ではありません. ただし、同じ説明がここにも当てはまります。SW プリフェッチを使用して回線にアクセスする方法を事前に十分に知っていれば、アクセス遅延の一部を軽減し、実効 BW を増やすことができる場合があります。ただし、これは 2 つの理由で長いストリームでは機能しません。1) キャッシュ容量が限られている (たとえプリフェッチが t0 フレーバーのように一時的なものであっても)、2) それでも L1-->mem レイテンシをすべて支払う必要があります。データ操作がメモリ アクセスよりも速い場合は、最終的に SW プリフェッチに追いつくことになります。したがって、これは、必要なものを事前に十分にプリフェッチして、そこに保持できる場合にのみ機能します。

于 2013-10-20T18:05:59.597 に答える