【发布时间】:2016-05-23 18:44:50
【问题描述】:
我想在缓存边界上过度对齐我的类型,所以我使用了alignas:
struct alignas(64) W { };
这编译得很好。但是,令我惊讶的是,当我尝试分配一堆 Ws 时,它们不是 64 字节对齐的,而是实际上是 16 字节对齐的:
#include <iostream>
#include <iomanip>
#include <unordered_map>
struct alignas(64) W { };
int main() {
std::unordered_map<int, int> offset;
for (int i = 0; i < 1000; ++i) {
auto w = new W;
offset[(uintptr_t)w % 64]++;
}
for (const auto& p : offset) {
std::cout << p.first << ' ' << p.second << '\n';
}
}
产量:
0 250
16 250
32 250
48 250
在多个编译中(gcc 4.8.2、gcc 5.2.0、clang 3.7.1)。这是怎么回事?我告诉它对齐,为什么它不对齐?
【问题讨论】:
-
@T.C.这看起来应该是一个答案。
-
operator new 是 borken,编译器知道对齐要求,但无法告诉 operator。所以这几乎肯定会出错。解决它是你的负担,比如aligned_alloc() 或posix_memalign() 或_aligned_malloc()。
-
是的,编译器可以控制它,它会选择堆栈偏移量。
-
@HansPassant 要添加到该建议,您可能可以在
struct W内部创建一个operator new和operator delete,在内部调用aligned_alloc和aligned_free而不会使外部客户的工作复杂化