質問

これは、cachegrind出力の一部です。コードのこの部分は1224回実行されています。 ELMG1は、サイズ16 x 20の署名されていないロングの配列です。私のマシンL1キャッシュサイズは、32kb、64bキャッシュラインサイズ、8ウェイセットの連想です。

  1. for(i = 0; i <20; i ++)78,336 2,448 2 50,184 0 0 1,224 0 0
  2. {
  3. telm01 = elmg1 [i]; 146,880 0 0 73,440 0 0 24,480 0 0
  4. telm31 =(telm01 << 3) ^ val1; 97,920 0 0 48,960 0 0 24,480 0 0
  5. telm21 =(telm01 << 2) ^(val1 >> 1); 146,880 1,224 1 48,960 0 0 24,480 0 0
  6. telm11 =(telm01 << 1) ^(val1 >> 2); 146,880 0 0 48,960 0 0 24,480 0 0
  7. }

A.私がここに置いた理由は、forループ内の3行目で、多くのi1ミス(1つのL2ミスも同様に)を見るからです。それはやや混乱しており、理由を推測できませんでしたか?

B.コードの一部を最適化しようとしています(時間)。上記は小さなスニペットです。私のプログラムのメモリには、私に大いに費用がかかると思います。上記の例のように、Elmg1は16 x 20サイズの無署名ロングの配列です。コードで使用しようとすると、常にいくつかのミスがあり、私のプログラムではこれらの変数がよく発生します。助言がありますか?

C.これらの署名されていないロングを割り当てて(時には初期化する)必要があります。 Callocまたは配列の宣言、そして明示的な初期化を好むべきものを提案できますか。ちなみに、キャッシュがそれらを処理する方法に違いはありますか?

ありがとう。

役に立ちましたか?

解決

ループを展開しようとしましたか?

  1. 私は今L1ミスについて心配しません。また、1224回の1つのL2ミスは問題ありません。CPUは、ある時点で値をキャッシュにロードする必要があります。
  2. このコードは、プログラムの残りの部分と比較して、L2の何パーセントでコストがかかりますか?
  3. calloc()を使用します。配列のサイズが常に同じで、サイズに定数を使用する場合、コンパイラは配列のゼロを最適化できます。また、キャッシュラインの使用に影響を与える唯一のものは、それがどのように開始されたかではなく、アラインメントです。

編集:そのように読みにくい番号を初めて間違えます。

5行目の数字を正しく読んでいることを確認しましょう:

Ir    146,880
I1mr  1,224
ILmr  1
Dr    48,960
D1mr  0
DLmr  0
Dw    24,480
D1mw  0
DLmw  0

L1キャッシュは、コードI1とデータD1の2つの32kbyteキャッシュ1に分割されます。 IL&DLは、データと命令の両方で共有されるL2またはL3キャッシュです。

多数のI1MRは、データミスではなく命令ミスです。これは、ループコードがI1命令キャッシュから排出されていることを意味します。

I1は、3倍の1224である3672行1と5の合計3672でミスしているため、ループが実行されるたびに64バイトキャッシュラインで3 I1キャッシュミスを取得します。したがって、これらのI1は5行目のミスは、ループコードが最後のキャッシュラインを通過する場所だからです。

cachegrindの結果を表示するためにKcachegrindを使用することをお勧めします

編集:キャッシュラインの詳細。

そのループコードは、それ自体で1224回呼び出されているようには見えないので、このコードをi1キャッシュから押し出しているコードが増えます。

32kbyte I1キャッシュは512キャッシュライン(それぞれ64バイト)に分割されます。 「8ウェイセット連合」パートは、各メモリアドレスがこれらの512キャッシュラインのうち8回のみにマッピングされることを意味します。あなたがプロファイルであるプログラム全体が32kbytesのメモリの連続ブロックの1つである場合、それはすべてi1キャッシュに収まり、排出されるものはありません。それはほとんどそうではなく、同じ8つのキャッシュラインにコンテンツを含む8 64バイトのコードブロックを超えています。プログラム全体に1mbyteのコード(これにはライブラリが含まれています)があり、8キャッシュラインの各グループには、同じ8キャッシュラインに約32(1mbyte/32kbyte)コンテンツが含まれます。

CPUキャッシュに関するすべてのgoryの詳細については、このlwn.net記事を読む

コンパイラは、プログラムのどの機能がホットスポット(何度も呼ばれます)であり、コードスポット(つまり、ほとんど実行されないエラーハンドラーコード)になるかを常に検出することはできません。 GCCには関数属性があります ホット/コールド これにより、機能をホット/コールドとしてマークすることができます。これにより、コンパイラがメモリの1つのブロックにホット関数をグループ化して、キャッシュの使用を改善することができます(つまり、コールドコードはキャッシュからホットコードを押し出さないでしょう)。

とにかく、これらのi1のミスは本当に心配する時間はありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top