内存基准测试图:了解缓存行为

Dav*_*ava 5 memory performance benchmarking

在此输入图像描述

我尝试过各种各样的推理,但我真的不明白这个情节.它基本上以不同的步幅显示了不同大小数组的读写性能.我明白,对于4个字节的小步幅,我读取了缓存中的所有单元格,因此我有很好的性能.但是当我拥有2 MB阵列和4k步幅时会发生什么?还是4M和4k的步幅?为什么表现如此糟糕?最后为什么当我有1MB阵列并且步幅是1/8的尺寸性能是不错的时候,当1/4的尺寸性能变得最差然后只有一半尺寸时,性能是否超级好?请帮助我,这件事让我发疯.

在此链接中,代码为:https://dl.dropboxusercontent.com/u/18373264/membench/membench.c

Lee*_*eor 1

您的代码循环给定的时间间隔而不是恒定的访问次数,您没有比较相同的工作量,并且并非所有缓存大小/步长都享有相同的重复次数(因此它们获得不同的缓存机会)。

另请注意,第二个循环可能会被优化(内部for),因为您不在temp任何地方使用。

编辑:

这里的另一个影响是 TLB 利用率:

在 4k 页面系统上,当您的步幅仍小于 4k 时,您将享受到每个页面的利用率越来越低(最终在 4k 步幅上达到每页一次访问),这意味着访问时间会随着您的增加而增加每次访问都必须访问第二级 TLB(甚至可能序列化您的访问,至少部分序列化)。
由于您通过步幅大小标准化了迭代计数,因此您通常可以(size / stride)在最内部的循环中进行访问,但* stride在外部循环中。但是,您访问的唯一页面数量不同 - 对于 2M 数组、2k 步幅,您在内循环中将有 1024 次访问,但只有 512 个唯一页面,因此对 TLB L2 的访问次数为 512*2k。在 4k 步长上,仍然会有 512 个唯一页面,但有 512*4k TLB L2 访问。
对于 1M 阵列的情况,总共将有 256 个唯一页面,因此 2k 步长将有 256 * 2k TLB L2 访问,而 4k 又将有两次。

这解释了为什么当接近 4k 时每行的性能逐渐下降,以及为什么数组大小每增加一倍,相同步长的时间也会增加一倍。较小的数组大小可能仍部分享受 L1 TLB,因此您不会看到相同的效果(尽管我不确定为什么存在 512k)。

现在,一旦您开始将步幅增加到 4k 以上,您就会突然再次受益,因为您实际上是在跳过整个页面。8K 跨度将仅访问每隔一个页面,对于相同的数组大小,将 TLB 总体访问量的一半视为 4k,依此类推。