17

valgrind の cachegrind/callgrind ツール用の小さなパッチをまとめています。これは、完全に汎用的なコード、CPU 命令、およびキャッシュ構成を使用して自動検出します (現在は x86/x64 自動構成のみで、他のアーキテクチャでは提供されません)。非特権コードへの CPUID タイプの構成)。このコードは、非特権コンテキスト、つまり純粋なユーザー モード コードで完全に実行する必要があります。また、非常に異なる POSIX 実装間で移植可能である必要があるため、目的のシステムの 1 つにそのような機能がないため、/proc/cpuinfo を調べてもうまくいきません。

CPU の周波数、キャッシュの数、それらのサイズ、さらにはキャッシュ ラインのサイズの検出はすべて、CPU 固有のオペコードをまったく持たない 100% 汎用の POSIX コードを使用して実行できますメモリまたはレジスタ依存ストールがなければ、おそらく 1 サイクルで実行されます)。この部分はかなり簡単です。

それほど簡単ではないのはなぜですか? StackOverflow に尋ねる理由は、特定のキャッシュのキャッシュ ラインの連想性を検出する方法です。連想性とは、メイン メモリからの特定のキャッシュ ラインをキャッシュ内に含めることができる場所の数です。L1 キャッシュの連想性は検出できていることがわかりますが、L2 キャッシュは? 確かにL1連想性は邪魔になりますか?

これはおそらく解決できない問題だと思います。しかし、私はそれを StackOverflow に投げて、誰かが私が知らないことを知っていることを願っています。ここで失敗した場合は、結果に大きな違いをもたらさないと仮定して、結合性の既定値である 4 つの方法で単純にハード コードすることに注意してください。

ありがとう、
ナイル

4

3 に答える 3

7

スキームは次のとおりです。

ストライドSのメモリ アクセス パターンと、アクセスされる一意の要素の数 = Nを持ちます。このテストでは、最初に各固有の要素に触れてから、同じパターンに非常に多くの回数アクセスすることによって、各要素にアクセスする平均時間を測定します。

例: S = 2 および N = 4 の場合、アドレス パターンは 0,2,4,6,0,2,4,6,0,2,4,6,... になります。

マルチレベルのキャッシュ階層を考えてみましょう。次の合理的な仮定を行うことができます。

  • n+1 番目のレベル キャッシュのサイズは、n 番目のキャッシュのサイズの 2 乗です。
  • n+1 番目のキャッシュの結合性も、n 番目のキャッシュの結合性の 2 乗です。

これら 2 つの仮定により、2 つのアドレスが n+1 番目のキャッシュ (L2 など) の同じセットにマップされる場合、それらは n 番目のキャッシュ (L1 など) の同じセットにマップされる必要があると言えます。

L1、L2 キャッシュのサイズを知っているとします。L2 キャッシュの連想性を見つける必要があります。

  • set stride S = L2 キャッシュのサイズ (すべてのアクセスが L2 と L1 の同じセットにマップされるように)
  • Nを変化させる(2 の累乗)

次の体制が得られます。

  • レジーム 1: N <= L1 の結合性。(L1 のすべてのアクセス HIT)
  • レジーム 2: L1 の結合性 < N <= L2 の結合性 (L1 ではすべてのアクセスが失敗しますが、L2 ではヒットします)
  • レジーム 3: N > L2 の連想性 (L2 ですべてのアクセスが失敗する)

したがって、平均アクセス時間を N (S = L2 のサイズの場合) に対してプロットすると、階段状のプロットが表示されます。最下段の終点で、L1 の結合性が得られます。次のステップでは、L2 の結合性が得られます。

L2-L3 などの間で同じ手順を繰り返すことができます。それが役立つかどうか教えてください。メモリ アクセス パターンのストライドを変化させてキャッシュ パラメーターを取得する方法は、LMBENCH ベンチマークで使用される方法と似ています。lmbench も結合性を推測するかどうかはわかりません。

于 2013-04-14T05:28:35.703 に答える