在尝试确定给定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+c
秒(其中c
近似不变),但事实并非如此,事实上,它减少了与不存在的时间差异为什么呢?
答案 0 :(得分:3)
你所看到的是瓶颈的权衡。
在继续之前,让我们看看两个例子之间的区别:
&
这是一种快速按位操作。%
这是非常慢的划分。分部非常慢。当除数/模数是编译时常数时,现代编译器将尝试优化它们。
但事实并非如此。 因此,您需要支付硬件部门的全部费用。 这就是为什么第二个示例中的时间比第一个示例慢得多。
使用&
,代码足够快以最大化缓存带宽。但是,对于%
,代码要慢得多 - 不够快,无法跟上缓存。所以你一直看到同样的时间。
答案 1 :(得分:0)
在第二种情况下,编译器生成的优化代码较少(因为“与余数分开”)。