程序堆栈和数据段之间的距离是否会影响CPU缓存?

时间:2013-05-16 23:57:29

标签: optimization memory-management stack global-variables cpu-cache

我在linux上看过,程序内存布局可以大致可视化如下(我假设它在大多数其他操作系统上类似):

memory layout

现在,我不确定我是否记得正确,但我认为CPU会在相同的时间内将相当大的相邻RAM地址块读入其最大的缓存级别。如果是这样,从性能的角度来看,将所有程序的数据保持在尽可能短的内存范围内是有意义的,以防止缓存未命中。

然而,如果是这种情况,那么翻转事物并将向上增长的部分(文本,全局数据和堆)置于向下增长的部分(cl args,env vars和stack)之上似乎会更好。但我猜真相比那复杂一点?如果数据段与堆栈存在完全不同的内存部分,那么它是否重要?

2 个答案:

答案 0 :(得分:3)

  翻转事物并将向上增长的部分(文本,全局数据和堆)放在最上面似乎更好?

没有。高速缓存行通常只有32个字节到256个字节。程序使用少于几兆字节的数据很少见,因此共享基本上无关紧要。 (即使您不使用它,标准库也会代表您做很多事情。)

相关的是确保一起使用的数据在内存中保持紧密相关(在某些情况下,与高速缓存行对齐)。

在脚本语言中,数组的每个元素都可能位于其自己的缓存行上。但是在C语言中,你可以将事物放在一起(使用数组或结构)。在数字操作方面,用C语言重写可以轻松快100倍。 (或像NumPy这样的高效图书馆)

大多数处理器也有单独的指令和数据缓存。

  

如果数据段与堆栈存在完全不同的内存部分,那么它是否重要?

同样,如果您的堆栈可能超过几百字节(它将是!),那么它甚至不相关。实际上,您的堆栈可能会在非平凡的程序中使用许多缓存行。

如果您想了解更多信息,我建议您尝试阅读Ulrich Drepper撰写的What every programmer should know about memory。这是一本很好的书,但即使你浏览它,你也可以得到一些简洁的信息。 (就像通过改变循环索引使程序运行速度快20倍,或者RAM不再是随机访问"而不是你的硬盘驱动器。)

答案 1 :(得分:2)

程序和缓存之间的距离不一定是问题。缓存使用地址的某些部分来确定缓存中的内容和位置。

还要明白,当在操作系统,Linux,Windows等上运行时,您可能纯粹是在虚拟内存地址上运行,因此内存分离只是一种错觉。你的程序的一小部分与另一个小块相邻,在物理地址空间中可能相距甚远。

然后问题是缓存在哪里,是在mmu的虚拟侧还是物理侧。

所以简短的回答是你的缓存和程序和堆可能会或可能不会彼此冲突,并且有一些简单的事情可以完成(如果你可以控制缓存使用的地址空间)让缓存变得更好,或者更糟。例如,您可以在偶数边界“划分”数据,从而导致缓存的一小部分发生冲突,从而导致过多的读取(假设您没有使用所有缓存行)和驱逐。对于程序来说也是如此,大量使用的功能恰好可能恰好分开以引起更多的高速缓存冲突,或间隔使得它们导致彼此更少的冲突。降低或提高整体表现。

如果您可以控制系统(并知道缓存使用了哪些地址位),编写程序来演示这些问题并不难,只需移动基础就可以提高或降低相同代码的性能。数据和/或程序功能所在的地址,但不改变程序或数据。缓存ram与其后面的内存之间的差值越大,就越容易看到。