正文
字节的数据都有相同的延迟,因为CPU每次从内存中读取
字节的数据,这些数据通常会被缓存在CPU中。也就是说,如果数据存储在
字节对齐的地址上,其存储大小
不是
的倍数,那么一些内存访问带宽会被浪费。
当被访问的数据长度为
字节且数据地址是
字节对齐时,我们说这种内存访问是对齐的。当内存访问不对齐时,我们说它是未对齐的。请注意,根据定义,单字节内存访问总是对齐的。理论上,可以在不是
的倍数的内存地址上访问
字节的数据,但这会浪费更多的内存访问带宽。但是,由于C和C++标准假设内存访问是对齐的,访问未对齐的地址可能导致未定义的行为。
数据对齐要求
alignof
可以用来检查特定数据类型的对齐要求。
#include
struct float4_4_t
{
float data[4];
};
// float4_32_t类型的每个对象都将对齐到32字节边界。
// 可能对SIMD指令有用。
struct alignas(32) float4_32_t
{
float data[4];
};
// 比同一声明上的另一个alignas更弱的有效非零对齐会被忽略。
struct alignas(1) float4_1_t
{
float data[4];
};
// 访问对象会导致未定义行为。
// 1字节结构成员对齐。
// size = 32, alignment = 1字节,这些结构成员没有填充。
// 这是不规范的,因为float需要4字节对齐。
#pragma pack(push, 1)
struct alignas(1) float4_1_ub_t
{
float data[4];
};
#pragma pack(pop)
int main()
{
assert(alignof(float4_4_t) == 4);
assert(alignof(float4_32_t) == 32);
assert(alignof(float4_1_t) == 4);
assert(alignof(float4_1_ub_t) == 1);
assert(sizeof(float4_4_t) == 16);
assert(sizeof(float4_32_t) == 32);
assert(sizeof(float4_1_t) == 16);
assert(sizeof(float4_1_ub_t) == 16);
}
内存分配
根据GNU文档(https://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html),在GNU系统中,
malloc
或
realloc
返回的块地址总是8的倍数(在64位系统上是16的倍数)。数组的默认内存地址对齐由元素的对齐要求决定。
可以为分配的静态内存和动态内存使用自定义数据对齐。
alignas(T)
可以用来指定静态数组的字节对齐,
aligned_alloc
可以用来指定动态内存上缓冲区的字节对齐。
#include