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

6

enter image description here

我尝试了各种可能的推理,但我真的不太理解这个图表。它基本上显示了从不同大小的数组中读取和写入不同步长时的性能。我知道对于像4字节这样的小步长,我可以读取缓存中的所有单元格,因此我具有良好的性能。但是当我使用2MB数组和4k步长时会发生什么?或者4M和4k步长呢?为什么性能如此糟糕?最后,为什么当我有1MB数组并且步长是大小的1/8时性能还可以,而当步长是大小的1/4时性能变差,然后在一半大小时,性能非常好?请帮帮我,这件事让我发疯。

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


1
你能附上基准测试代码吗?乍一看,似乎你正在使用4k页面大小,可能会导致TLB失效,但是如果不知道你具体在做什么,很难确定。 - Leeor
我已经添加了一个链接到代码 https://dl.dropboxusercontent.com/u/18373264/membench/membench.c,非常感谢。 - Davide Nava
1个回答

1
你的代码循环一个给定的时间间隔而不是恒定数量的访问,你没有比较相同数量的工作量,并且并非所有缓存大小/步长都享有相同的重复次数(因此它们获得不同的缓存机会)。
另外请注意,第二个循环可能会被优化掉(内部的for),因为你没有在任何地方使用temp。
编辑:
这里还有另一个效果,即TLB利用率:
在4k页面系统上,当您在步幅仍然小于4k的情况下增加步幅时,每个页面的利用率会越来越低(最终在4k步幅上达到每页一次访问),这意味着访问时间的增长,因为您必须在每次访问时访问第二级TLB(可能甚至部分串行化您的访问)。 由于您通过步幅大小对迭代计数进行了归一化,在内部循环中,您通常会有(size / stride)次访问,但是在外部则有* stride次访问。然而,您访问的唯一页面数量不同-对于2M数组,2k步幅,您将在内部循环中进行1024次访问,但仅有512个唯一页面,因此需要进行512 * 2k次访问到TLB L2。在4k步幅上,仍将有512个唯一页面,但需要进行512 * 4k次TLB L2访问。 对于1M数组情况,总共有256个唯一页面,因此2k步幅将有256 * 2k次TLB L2访问,而4k步幅将再次增加一倍。
这就解释了为什么在接近4k时每行都有逐渐下降的性能损失,以及为什么数组大小加倍会使相同步幅的时间加倍。较小的数组大小可能仍然部分享受L1 TLB,因此您不会看到相同的效果(虽然我不确定为什么有512k)。
现在,一旦您开始增加步幅超过4k,您突然又开始受益了,因为您实际上正在跳过整个页面。8K步幅仅访问每隔一个页面,对于相同的数组大小,总体TLB访问量只有4k的一半,依此类推。

这不是我自己写的代码,但基于那段代码,你能否回答我的疑问? - Davide Nava
@DavideNava,我添加了另一个效果,我相信它可以解释你在这里看到的行为。 - Leeor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接