17

私が知る限り、ハードウェア プリフェッチャーは、少なくともメモリを介して一定のストライドを検出してフェッチします。さらに、それが実際に意味するものは何でも、データ アクセス パターンを監視できます。ハードウェア プリフェッチャーは、メモリに格納された実際のデータに基づいて決定を下すのでしょうか、それともプログラムが示している動作に純粋に基づいて決定を下すのでしょうか?

私が尋ねる理由は、「非ネイティブ」ポインターをポインターとして使用することがあるためです。これの簡単な例は、事前に割り当てられたものの配列と、ポインターの代わりにこの配列にインデックスを付ける小さな整数です。このような「ポインタ」を大量に保存する必要がある場合、メモリの節約はすぐに加算され、使用するメモリが少なくなるため、間接的にキャッシュのパフォーマンスが向上します。

しかし、私が知る限り、これはハードウェア プリフェッチャーの動作に干渉する可能性があります。か否か!

現実的であろうとなかろうと、ネイティブ ポインター アドレスの L1 キャッシュに入るキャッシュ ラインを調べ、それらを L2 などにフェッチし始めるプリフェッチ ユニットを想像できます。その場合、メモリを節約するという私の巧妙なトリックは、突然あまり賢く見えなくなります。

では、最新のハードウェア プリフェッチャーは実際に何をするのでしょうか? それらは「非ネイティブ」ポインターによってつまずくことができますか?

4

2 に答える 2

21

ハードウェア プリフェッチャーはポインターを認識せず、メモリ アドレスを認識します。アドレスがどこから来たのか、またはあなたが書いた C++ プログラムでどのような型を持っていたのかは気にしません。CPUが読み取りまたは書き込みを行うように指示されているアドレスを確認するだけです。

いいえ、配列へのインデックス付けは、CPU がこれまで遭遇したことのない恐ろしい新しいことではありません。

于 2013-11-13T13:06:07.277 に答える
10

リンクされたデータ構造 (LDS) のプリフェッチは、コンピューター アーキテクチャにおける既知の問題です。実際にそれを行う最新の CPU には詳しくありませんが、理論的には可能です。何年にもわたって、いくつかのバリエーションを提案するアカデミー論文がいくつかありました。

  1. フェッチされたキャッシュ ライン内のアドレスのような値を検出し、これらのアドレスにプリフェッチを発行できる専用ハードウェア。
  2. コンパイラーがデータ構造の依存関係を認識し、SW プリフェッチまたはその他のヒントを挿入する、コンパイラー支援手法。

これらの方法は両方とも、あなたのテクニックの影響を受ける可能性があります (最初の方法は役に立たなくなりますが、コンパイラが十分に賢い場合は 2 番目の方法が機能する可能性があります)。

もちろん、そのようなマシンで実際に実行する必要があるため、これは理論的なものであり、うまく機能する場合はプラクティスを変更する必要はありませんが、プロファイリングはマイクロアーキテクチャごとに固有である必要があることを示しています。システム、およびある場合に役立つものは、別の場合には効率が悪い場合があります。
一般的に言えば、CPU が何らかの最適化を行うか行わないかを単に信頼するのではなく (文書化されていない限り)、期待される動作が得られることを常に確認してください。

ところで、HW がメモリの内容を認識したとしても、それはまだ仮想アドレス空間にあることに注意してください。HW は、それを使用するために何らかの物理アドレスへの変換を行う必要があるため、ある意味ではそうではありません。 t は追加のオーバーヘッドである必要があります。

参考文献:

于 2013-11-13T13:45:22.847 に答える