【问题标题】:Performance of DWORD vs QWORD alignment in 32 bit code32 位代码中 DWORD 与 QWORD 对齐的性能
【发布时间】:2014-11-06 22:38:09
【问题描述】:

我有很多相互继承的对象等等。

默认 Embarcadero C++ Builder 2009 已将属性中的数据对齐设置为 QWORD。 如果我将其更改为 DWORD,我的许多对象的大小都会缩小,因为它们通常有 4 个字节可以备用,并且在继承对象中再次保留等。所以累积起来会有很好的效果。

缩小它们很有吸引力,因为有时我需要在内存中分配数百万个它们。

我想知道为什么 QWORD 是 32 位应用程序的默认值?我希望它实际上是 DWORD。将其更改为 DWORD 会产生性能问题吗?

另外,由于我在内存中分配了很多它们,它们是否被很好地打包在一起,一个接一个地分配,或者它们之间是否也有填充,并且这种填充是否也基于项目设置(数据对齐:QWORD /双字)?如果对象都分配在 QWORD 边界上,则更改实际对象的大小不会产生净效果。

【问题讨论】:

  • 如果您的对象实际上发生了变化,那么您不应该更改该设置。因为这意味着您未对齐 64 位变量。像double,很贵。如果未对齐 4,则慢约 x2,如果跨缓存线未对齐,则慢 x3。
  • 由于成员之间的填充,您的数据结构可能正在改变大小。我建议您检查您的数据结构布局并尝试减少成员之间的填充。一种方法是将所有相同类型的变量组合在一起,而不是混合在一起。另一个建议是首先放置最大的类型(例如 64 位指针或整数)。
  • 您是使用单个 malloc() 分配对象(即在数组中),还是每个对象都有自己的 malloc?在后一种情况下,内存分配器使用的元数据对象之间至少有 8 个字节。
  • 你如何测量对齐?如果您正在查看 sizeof(),除了一些奇异的缓存优势之外,我想不出任何优势。如果您正在查看内存利用率,malloc 以 8 字节为单位进行分配,因为它在分配时不区分类型,因此您会看到很多浪费。
  • @Sjlver 每个对象都是用 new 创建的,它的指针被添加到一个数组中。

标签: c++ memory c++builder memory-alignment borland-c++


【解决方案1】:

总体而言,对齐需要考虑许多事项:

首先,根据the Wikipedia page on Data Structure Alignment,如果Embarcadero 将所有对象对齐到8 字节边界,它可能有点例外。文章声称 GCC、VC++ 和 Borland 的计算机不会对齐 8 个字节的数据,除非它是 doublelong long

有很多事情会强制对齐:

  • mallocoperator new 将为您提供 8 字节对齐的内存区域。此外,如果您对mallocnew 执行单独的调用,对象将不会很好地打包在一起。它们之间将至少有 8 个字节左右用于分配器元数据。也不能保证对象在内存中彼此靠近。
  • 堆栈帧对齐为 8 或 16 字节,具体取决于架构
  • SSE 指令需要 16 字节对齐的数据

关于性能:我认为您不会看到 4 字节对齐和 8 字节对齐之间有很大差异。 Daniel Lemire measured,发现 1 字节和 4 字节对齐数据之间的差异很小(如果有);我希望它们在 4 到 8 个字节之间更小。

您的方案中最大的性能和内存使用差异可能来自同时为多个对象分配空间(例如,通过将它们存储在 std::vector 中)而不是为每个单独的对象调用 new

【讨论】:

    猜你喜欢
    • 2010-09-07
    • 2012-02-27
    • 2010-11-27
    • 1970-01-01
    • 2016-12-18
    • 2012-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多