精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
服务方向
联系方式
锐英源精品原创,禁止转载和任何形式的非法内容使用,违者必究。点名“简易百科”和“闲暇巴”盗用锐英源原创内容。
C++17 过度对齐分配的英文是over-aligned allocation,其实这个翻译是有问题的,over是过的大的意思,翻译成大对齐分配或大值对齐分配就可以了,过度这个词明显是机器翻译的结果,不是意思翻译的结果。过度对齐分配理解成大值对齐分配,大家就明白了,相当于对齐值变大了。
对齐值变大有什么好处?现代CPU的数据总线结构和地址总线结构复杂且强大,寻址功能和提取写入数据功能也比以前优秀,硬件改动了,也要让软件改动,对齐值变大了,让寻址功能和提取写入数据功能更容易体现到软件运行上,特别是内存池和共享文件内存处理上,对齐的内存读写更快,效率更高。
在电脑和互联网刚传入到国内时,很多自己开发的软件在性能上总是差那么一丝丝,这就是底层硬件的处理没吃透,不过随着华为带领一批公司崛起,硬件吃透了,软件性能也跟上了。这中间华为方舟编译器是里程碑事件,华为方舟编译器把Java解释代码编译成静态代码,提升了性能。华为方舟编译器支持多种芯片平台,和上段话的CPU结构对应上了。
说了这么多,就是说内存对齐能优化软件性能,C++17以前对齐值太小,不支持硬件了。
开启过度对齐分配,在编译选项里加上/Zc:alignedNew,加上后,如果对齐值小于宏__STDCPP_DEFAULT_NEW_ALIGNMENT__,则没有改变;如果大于宏__STDCPP_DEFAULT_NEW_ALIGNMENT__则使用新的::operator new(size_t, align_val_t) 获取内存,新的::operator delete(void*, align_val_t) 或特定大小的删除函数 ::operator delete(void*, size_t, align_val_t)。
要关闭此选项并在使用 /std::c++17 或更高版本时恢复到 new 和 delete 的 C++14 行为,请指定 /Zc:alignedNew-。
参考的新new和新delete示例如下:
// alignedNew.cpp // Compile by using: cl /EHsc /std:c++17 /W4 alignedNew.cpp #include <iostream> #include <malloc.h> #include <new> // "old" unaligned overloads void* operator new(std::size_t size) { auto ptr = malloc(size); std::cout << "unaligned new(" << size << ") = " << ptr << '\n'; return ptr ? ptr : throw std::bad_alloc{}; } void operator delete(void* ptr, std::size_t size) { std::cout << "unaligned sized delete(" << ptr << ", " << size << ")\n"; free(ptr); } void operator delete(void* ptr) { std::cout << "unaligned unsized delete(" << ptr << ")\n"; free(ptr); } // "new" over-aligned overloads void* operator new(std::size_t size, std::align_val_t align) { auto ptr = _aligned_malloc(size, static_cast<std::size_t>(align)); std::cout << "aligned new(" << size << ", " << static_cast<std::size_t>(align) << ") = " << ptr << '\n'; return ptr ? ptr : throw std::bad_alloc{}; } void operator delete(void* ptr, std::size_t size, std::align_val_t align) { std::cout << "aligned sized delete(" << ptr << ", " << size << ", " << static_cast<std::size_t>(align) << ")\n"; _aligned_free(ptr); } void operator delete(void* ptr, std::align_val_t align) { std::cout << "aligned unsized delete(" << ptr << ", " << static_cast<std::size_t>(align) << ")\n"; _aligned_free(ptr); } struct alignas(256) OverAligned {}; // warning C4324, structure is padded int main() { delete new int; delete new OverAligned; }
注意,里面的delete new连接使用非常新,以前没想到过能这样用。
如果自己没有写新new和delete,编译器在有编译宏/Zc:alignedNew时会自动生成新new和delete。
硬件我也是略懂,我猜测,过度对齐大值对齐内存可能更好支持CPU的某些并发访问存取,在大游戏和高算力场景有需求。