精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
服务方向
联系方式
锐英源精品原创,禁止转载和任何形式的非法内容使用,违者必究。点名“简易百科”和“闲暇巴”盗用锐英源原创内容。
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的某些并发访问存取,在大游戏和高算力场景有需求。