【问题标题】:std::array alignmentstd::array 对齐
【发布时间】:2012-01-05 23:18:39
【问题描述】:

在 Mac 上试用 std::tr1::array 我得到 16 字节对齐。

sizeof(int) = 4;  
sizeof( std::tr1::array< int,3 > ) = 16;  
sizeof( std::tr1::array< int,4 > ) = 16;    
sizeof( std::tr1::array< int,5 > ) = 32;

STL 中是否有任何行为类似于 array 但保证不会自行填充,即

sizeof( ARRAY< T, N> ) = sizeof(  T )*N  

【问题讨论】:

  • 是的,它内置在语言中:T a[N]; static_assert(sizeof(a) == sizeof(T)*N);
  • 你使用什么标准库导致这种奇怪的填充?
  • 哈哈当然可以。我的意思是带有附加方法的包装集合,例如适合插入基于范围的范围或采用每个元素的赋值/转换运算符。这来自 mac osx 10.7,target = 64bit intel,LLVM 3.0。他们对 std::tr1::array 的实现声明了 atttribute(__aligned ) 这可能就是为什么 :( 当然,人们希望 aligned 完成它的工作,而不是成为默认
  • @centaurian_slug:不,一切都是并且应该默认对齐。问题是为什么/这个特定类的对齐比它需要的更严格
  • -对不起,如果我的最后一行听起来不精确。是的,我知道大多数 CPU 更喜欢类型有自己的 自己的对齐,因此这是默认值,我确实希望如此。但是属性(aligned)对我来说意味着选择一些“额外”对齐超出默认值(动机通常是用于宽 SIMD 加载/存储或缓存行).. 绝对出乎意料行为。

标签: c++ arrays vector alignment padding


【解决方案1】:

该标准要求元素“连续存储,这意味着如果 a 是一个数组,那么对于所有 0

据我所知,不能保证 sizeof(std::array) == sizeof(T)*N,但是 contiguity 语句断言这些值的存储方式就像在常规 C 数组中一样。 如果您只有一个需要连续的值数组,则可以使用 sizeof(T)*std::array::size() 作为大小,使用 std::array::data() 作为起始地址数组。

【讨论】:

  • 我想我可以用一个 static_assert 来警告自己,以提高可移植性。
【解决方案2】:

std::array 实际上不是一个数组,而是一个包含数组的结构体。填充的是结构,而不是数组。编译器可以随时在结构的末尾添加填充。

【讨论】:

    【解决方案3】:

    从您提供的少量数据来看,它会将内存分配到最接近的 2 次方。对 CPU 架构细节知之甚少,我可能猜想分配 2 的幂大小比非填充要快,至少在少量情况下是这样。也许您应该看看当您尝试分配更大的东西时会发生什么?

    你有什么理由绝对需要从顶部略去那些额外的字节吗?

    【讨论】:

    • >>“你有什么理由绝对需要从顶部略去那些额外的字节吗?”我通常制作自己的“template struct FixedArray ..”,但一直在寻找“标准”的做事方式。零填充是绝对必要的。 (例如,顶点数据)。
    • 我刚刚尝试在另一个类中使用它,并确保各个组件也得到单独的对齐和填充。当然,这是库头中 attribute(__aligned) 的预期行为。
    【解决方案4】:

    自从发布以来,我得到了我想要的将 IDE 设置从默认设置交换为..

    LLVM compiler 3.0 Language:
      LLVM C++ standard library:
        =libc++ (LLVM standard library with c++0x support.)
    

    (CLANG_CXX_LIBRARY = libc++)l

    以前的设置是“libstdc++(gcc c++ 标准库)”,它似乎有填充,这让我可以包含&lt;array&gt; 而不是&lt;tr1/array&gt;; 现在

    sizeof(array<T,N>)==sizeof(T)*N
    

    这一切都在 Mac osx lion 上的 Xcode 4.2 中。 我希望一个简单地被弃用并且这种行为是我将在其他平台上得到的?

    【讨论】:

    • “我希望一个被简单地弃用并且这种行为是我将在其他平台上得到的?”不,这不对。编译器可以灵活地对齐大多数对象。他们甚至可以在调试和发布之间有不同的对齐方式。我不知道你为什么需要这样特定的对齐要求。
    • 它用于 3D 渲染顶点数据 - 绝对是 size 关键情况。问题是在 tr1 标头中故意请求的 extra 对齐,超出了编译器默认值。我会假设编译器默认最常见的是最紧凑的数据结构,每种类型都与它自己的大小对齐。如果需要,我可以将数据逐字节插入原始内存,我有自己的模板,但如果 STL 中有一些东西可以完成相同的工作,那么我可以简化我的源代码,使其易于被其他人理解并且更有可能与其他库互操作,这是一个胜利。
    • 对于顶点数据的缓冲区,将它们作为原始内存处理几乎总是更好。不仅因为您将处于控制之中,还因为您想要那种控制。使用该控件,您可以玩一些技巧,例如使用 3 浮点位置和 4 字节颜色,​​所有这些都打包到每个顶点 16 字节。或者将其与 10/10/10 位格式的法线和 16 位短格式的纹理坐标结合使用,每个顶点总共 24 个字节。
    • 我已经完成了所有的原始内存技巧,然后创建了模板以使其更具可读性.. 自动转换为打包格式和中间设置计算扩展为全浮点数。我已经创建了一个定点类,可以实例化 8 位颜色或 16 位顶点;和一个“半”浮动课程。随着排列数量的增加,模板的多功能性非常受欢迎;原始的#defines 和辅助函数变得难以命名。在速度无关紧要的地方,我喜欢最紧凑的来源:)
    • 我可以做一些完全由数据驱动的事情,完全避开类问题,但是任何时候我想在语言中操作顶点数据(翻译格式、解压缩、程序网格生成..)
    猜你喜欢
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 2020-02-07
    相关资源
    最近更新 更多