1

特定のCPUのキャッシュサイズを決定する際に、次のようにメモリ/キャッシュへのメモリアクセスの時間を計ろうとしました。

lengthMod = sizes[i]/sizeof(int)  - 1; // where sizes[i] is something like 1024, 2048 ... 
for (unsigned int k = 0; k < REPS; k++) {
    data[(k * 16) & lengthMod]++;
}

1, 0.52 
4, 0.52 
8, 0.52 
16, 0.52 
32, 0.52 
64, 1.11 // << note the jump in timing. L1 cache size is 32K
128, 1.12 
256, 1.19 

したがって、lengthModが2の累乗でない場合、これを行うことはできないと思います。だからやってみた

lengthMod = sizes[i]/sizeof(int);
for (unsigned int k = 0; k < REPS; k++) {
    data[(k * 16) % lengthMod]++;
}

1, 2.67 
4, 2.57 
8, 2.55 
16, 2.51 
32, 2.42 
64, 2.42 // << no jump anymore ...
128, 2.42 
256, 2.42

それから、私が期待したタイミングの増加はもう存在しないことがわかります...私は増加する時間を期待しましたが、それはすべての値に適用されるべきですか?したがって、xを使用するときの秒の場合、秒(ほぼ一定)を&期待しますが、そうではありません。実際、タイミングの差が存在しないようになります。なぜですか。~x+cc

4

2 に答える 2

3

あなたが見ているのは、ボトルネックのトレードオフです。

  • 最初の例では、キャッシュ帯域幅によってボトルネックになっています。
  • 2番目の例では、整数除算によってボトルネックになっています。

続行する前に、2つの例の違いを見てみましょう。

  • 最初のケースでは、これを使用します&。これは高速のビット演算です。
  • 2番目のケースで%は、非常に遅い分割を使用します。

分裂は非常に遅いです。最新のコンパイラは、除数/モジュラスがコンパイル時定数である場合にそれらを最適化しようとします。

しかし、ここではそうではありません。したがって、ハードウェア部門の全費用を支払うことになります。これが、2番目の例の時間が最初の例よりもはるかに遅い理由です。


を使用する&と、コードはキャッシュ帯域幅を最大化するのに十分な速度になります。ただし、を使用する%と、コードははるかに遅くなり、キャッシュに追いつくのに十分な速度ではありません。だからあなたはずっと同じ時間を見る。

于 2012-10-05T03:28:04.417 に答える
0

2番目のケースでは、コンパイラは最適化されていないコードを生成するように見えます(「余りのある除算」のため)。

于 2012-10-05T03:27:51.570 に答える