我想测量从L1到主内存的每个内存层次级别的延迟。所以,我试图理解1-single.c程序https://gist.github.com/jiewmeng/3787223.为什么数组的索引是由[(i*16)&lengthMod]计算的?
[(i*16)&lengthMod]和i*16的值将始终相同。例如,
i=0, [(i * 16) & lengthMod]=0, [i*16]=0
i=1, [(i * 16) & lengthMod]=16, [i*16]=16
i=2, [(i * 16) & lengthMod]=32, [i*16]=32
i=3, [(i * 16) & lengthMod]=48, [i*16]=48
i=4, [(i * 16) & lengthMod]=64, [i*16]=64
i=5, [(i * 16) & lengthMod]=80, [i*16]=80
.........................................
所以,我试着运行程序,用[I*16]替换[(I*16)&lengthMod],但每次程序都崩溃了。这就是为什么我意识到这一点明智的操作背后一定有一个坚实的原因。有人能解释一下为什么数组是由[(i*16)&lengthMod]计算的吗?
在for
循环中:
for (i = 0; i < steps; i++) {
arr[(i * 16) & lengthMod] *= 10;
CCD_ 2是256MB并且CCD_ 3具有4MB的元素。因此,如果您将数组访问更改为arr[i * 16]
,您将快速溢出数组并进入未定义的行为区域。
在原始代码中:
lengthMod = sizes[s] - 1;
其中CCD_ 5被定义为保持2到4MB的各种功率。因此,当执行(i * 16) & lengthMod
时,可以确保数组访问永远不会等于或超过sizes[s]
,从而防止发生数组溢出。
在最近的大多数处理器中,缓存线大小为64B
数组元素索引为0,1,2。。。一个元件4B缓存线大小/一个元素大小=64/4=16
每个缓存行有16个元素(=>64B)因此,它将类似于缓存行0中的数组0到15个元素缓存行1中有16到31个元素缓存行2中有32到47个元素。。。
如果访问任何元素,则该元素的缓存线将被带到内存中。
因此,访问第0个元素会将cacheline0带入缓存访问第16个元素将使下一个缓存行1进入缓存。。
您不需要访问所有元素;你只需要访问一个缓存行的一个元素,就可以把其他15个元素都带来!!
这就是为什么您在那里看到*16