内存对齐与页面对齐

Posted

技术标签:

【中文标题】内存对齐与页面对齐【英文标题】:Memory Alignment vs Page Alignment 【发布时间】:2015-01-14 19:39:33 【问题描述】:

我们经常听说将变量与内存中的 N 字节边界对齐可以提高性能(通过防止 CPU 必须将两个单独的“字”加载到缓存中来读取我们的变量)。

另一方面,我们也听说(不太常见)将一大块内存(数组/缓冲区)对齐到一个不错的、圆形的二次幂地址可能是不好的,因为分配内存地址的散列函数缓存地址不再统一(这称为页面对齐)。

因此,我的问题是,是否有某种规则或阈值点关于我们何时应该故意不对齐数据以避免页面对齐问题?什么时候不这样做,才能获得标准内存对齐的好处?

【问题讨论】:

“缓存关联性”是一个很好的搜索词。希望你能用一个更好的模型来代替你大脑中的第二段。 这肯定与 C#、C++ 或 C 无关。尤其与 C# 无关。 我选择这些语言是因为它们是您最常需要考虑这些问题的语言。是的,我认为你在 C# 中也是如此。 C# 像 C++ 一样对齐其对象字段,以提高性能。编译器会为你做这些,你不必担心。 即使使用AllocHGlobal,您也无法控制分配空间的位置。而且您的程序只能看到 虚拟 内存,这使事情变得更加复杂。此外,.NET 的 GC 进行了高度优化。除非您真的确实存在性能问题,可以通过分析您的代码并回溯到该问题来验证(这确实不太可能),否则您根本不应该打扰。 【参考方案1】:

如果性能对您的应用程序至关重要,并且您的应用程序通常会迭代已知数据集(在类型和大小方面),那么了解和理解 MMU、L-cache 和缓存行的影响就很重要。不是因为您可以真正提前避免这些问题,而是因为您可能需要事后识别它们,同时盯着分析结果并试图弄清楚为什么某些事情比过去或“通常应该”花费更长的时间。”并且——如果你很幸运并且数据集在你的控制范围内是足够的——那么你可以调整一些东西来解决某种 cpu 缓存性能问题。

不幸的是,大多数应用程序都没有机会迭代已知数据集,也无法了解其目标硬件类型。这是游戏和多媒体应用程序开发以及操作系统工程所独有的东西。对于世界上其他大多数应用程序而言,改进某个特定大小的特定数据集的缓存配置文件意味着减少另一个数据集的缓存配置文件。

最后,即使是关于“将我们的变量与 N 字节边界对齐”的“经验法则”也取决于底层硬件。大多数较新的桌面级 x86 架构(大多数是在大约 2011 年之后制造的)更喜欢打包数据而不是对齐数据,因为加载跨缓存线边界打包的单词的成本比必须加载更多总缓存线来表示相同数据集的成本要便宜。但是在运行 ARM 的移动设备上呢?对齐仍然非常关键。

更多关键字供您搜索,进一步学习:cache coloringcache eviction。但同样,这一切都非常依赖于目标 CPU,不幸的是,几乎没有(或没有)泛化。

【讨论】:

【参考方案2】:

我认为您无法为此获得一般规则。这取决于您使用的处理器,即底层系统的 MMU 和缓存实现。这将因系统而异。因此,如果您想要获得最佳性能,您需要了解当前系统的所有底层细节。一般来说,我认为将大内存块对齐到二次幂边界的好处是有限的。

【讨论】:

以上是关于内存对齐与页面对齐的主要内容,如果未能解决你的问题,请参考以下文章

内存对齐与自定义类型

C语言精要总结-内存地址对齐与struct大小判断篇

C语言精要总结-内存地址对齐与struct大小判断篇

结构体内存对齐

chatgpt教我内存对齐,对齐了但没完全对齐?

chatgpt教我内存对齐,对齐了但没完全对齐?