如果T对齐,std :: vector <t>也是对齐的吗?</t>

时间:2014-05-17 16:29:52

标签: c++ caching c++11 vector memory-alignment

我正在浏览一些新的C ++ 14特性,aligned_storage引起了我的注意,在谈到并发性,局部性和数据结构对齐之后,我想到了内存块的事实为std::vector分配的内容保证在内存中是连续的,但这并不一定意味着向量本身是有效打包的,或者更好地说,您关心的数据是有效对齐的,可能有额外的关于该数据结构的信息,不一定对计算有用,并且可能会干扰您的数据。

所以我问,如果我有一个class T并且我知道T已按照我喜欢的方式对齐和打包,std::vector<T>将缓存友好并在管道中对齐?

我的问题涉及C ++ 11和C ++ 14,它只涉及数据结构布局,我没有考虑与缓存行的组织相关的其他问题,例如虚假共享,或者与事情如何获得有关的其他问题获取,加载和执行。

我知道这听起来很傻,但我只是怀疑。

1 个答案:

答案 0 :(得分:1)

C ++默认分配器需要对齐任何所谓的标准类型正确对齐的结构,并且在结构的末尾自动添加的填充(通过sizeof()可见)通常在连续分配中促进这一点。

struct C {
  uint8_t  a; // followed by 7B of invisible padding to naturally align b
  uint64_t b;
  uint32_t c;
  uint8_t  d; // followed by 3B padding for C (natural alignment of 8B due to b)
};
// sizeof(C) = 24B, alignof(C) = 8B

struct D {
  uint8_t  a; // followed by 3B padding for b
  uint32_t b;
  uint8_t  c; // followed by 3B padding for D (natural alignment of 4B due to b)
};
// sizeof(D) = 12B, alignof(D) = 4B

struct E {
  __m256 v; // SSE/AVX intrinsics handle natural alignment properly too
  char v2;
};
// sizeof(E) = 64B, alignof(E) = 32B

对于大多数情况,这是足够的,但如果您正在进行花哨的强制转换技巧或需要64B缓存行对齐等,您可以使用alignas(),前提是您使用的是C ++ 11或较新的即可。这也可以通过填充结构的末端来实现:

struct alignas(64) F {
  double stuff[3];
};
// sizeof(F) = 64B, alignof(F) = 64B

void foo() {
  F f[4];
  // these addresses separated by (and even multiples of) 0x40 bytes:
  cout << &f[0] << " " << &f[1] << " " << &f[2] << endl;
}

如果您需要与例如4 kiB页边界对齐的大块,请使用std::aligned_storage<T>。但是,一般情况下,您只能使用展示位置new自行处理,并失去std::vector<>为您完成所有工作的便利。