【问题标题】:memory alignment for structs tbb vs atomic_ops结构 tbb 与 atomic_ops 的内存对齐
【发布时间】:2015-10-16 18:29:02
【问题描述】:

我正在使用两个不同的库来执行原子操作。我创建了一个二叉树节点结构,其中包含一个键(8 个字节)和指向左右子节点(每个 8 个)的指针。

预期的节点大小为 24 字节。 如果我使用英特尔 TBB 库,我会得到预期的行为。但如果我使用 HP 的 atomic_ops 库,我会看到节点大小为 32。

使用的编译器:

gcc4.6、gcc4.8、icc 2013

机器架构:x86_64

代码:

#include<stdio.h>
#include<stdlib.h>
#include<tbb/atomic.h>
#include<atomic_ops.h>

struct node24
{
    unsigned long key; //size 8
    tbb::atomic<struct node*> child[2]; //size 2*8=16
};

struct node32
{
    unsigned long key; // size 8
    AO_double_t child; // size 16
};

int main()
{
    printf("TBB          node size: %d\n",sizeof(node24));
    printf("HP atomicOps node size: %d\n",sizeof(node32));
}

输出

$ ./foo.o
TBB          node size: 24
HP atomicOps node size: 32

编辑

我的假设是node24 的大小四舍五入到最接近的 8,而node32 的大小四舍五入到最接近的 16(AO_double_t 的大小)。所以我添加了一个额外的value 变量(8 字节)以使节点大小为 32。现在我预计node32 的大小为 32 但它变成了 48。我不明白为什么额外的 16 字节填充当它已经在 32 处对齐时。

【问题讨论】:

  • 我怀疑有些对齐问题,试着把钥匙放在最后。
  • 试过了。没有变化。
  • 尝试添加一个 static_assert(sizeof(AO_double_t)==16, "is not 16");
  • 是的。它通过了静态断言。
  • 所以我会假设问题出在代码 #if ((defined(__x86_64__) &amp;&amp; __GNUC__ &gt;= 4) || defined(_WIN64)) \ &amp;&amp; !defined(__ILP32__) # include &lt;xmmintrin.h&gt; typedef __m128 double_ptr_storage; 中,__m128 应该对齐 16。

标签: c++ c gcc atomic tbb


【解决方案1】:

没有太多理由说明原子的非标准实现应该在它们使用的数据类型上保持一致,大小和对齐方式可以不同。根据编译器标志,在另一个使用本机指令的某些情况下,甚至可以使用锁定版本。只是不要混合它们。

现代 C 和 C++ 具有内置于语言中的原子,如果可以,请使用它们。它们甚至被设计为在两者之间兼容。

【讨论】:

    【解决方案2】:

    正如comment 中所指出的,node32::child 是使用定义的

    typedef __m128 double_ptr_storage;
    

    它的对齐为 16。因此编译器必须在第一个 key 字段之后添加额外的填充,因为它的大小只有 8 个字节,需要另外 8 个填充空间来修复对齐。当您添加第三个字段时(我假设到最后?)编译器必须添加更多填充以保持数组对齐。

    【讨论】:

      猜你喜欢
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      • 2011-02-02
      • 1970-01-01
      • 2012-06-26
      • 2013-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多