本文共 982 字,大约阅读时间需要 3 分钟。
结构体对齐目的:
1:访问速度:为了不让同一个变量(同时包括整个结构变量和结构体内部成员变量)分布在多个cache line上,然后两次访问内存。
2:平台限制:有些平台不能随意读取某个偏移的地址变量
如结构体:
struct AT
{
char a;
char b;
int c;
char d;
};
因为cpu是以cacheline为单位读写内存的。如x86_64的cacheline的大小为8个字节共64位,利用这一特性我们能做什么优化呢?
1:结构体起始地址尽量是cacheline的整数倍。
2:结构体变量尽量是cacheline的整数倍。
3:结构体成员变量尽量是在同一个cacheline中。(特别是要访问连续的几个成员变量情况,可以一次性读入)
当然下面这种情况需要认为代码中避免的:如果两个成员变量被不同的core频繁修改的话(cache一致性维护代价非常高),那最好不要将这两个变量落到同一个cache line中。
从上面得出一个宗旨:同一个成员变量不要跨cache line:
具体做法:找到一个最小单位n,它取决于下面的最小值:
1:人为指定:#pragma pack指定的数值
2:cache line大小
3:结构体内部最大的基本数据类型成员
当确定好n时,之后的对齐规则是:
1:结构体变量起始地址为n的整数倍
2:结构体成员变量的地址规则:取min(自身大小,n大小)
a:当自身大小大于等于n时,那么地址为n的整数倍:如
#pragma pack(4)struct s7{ char a; double d;};#pragma pack()double为8,cacheline为8,指定为4;那么n为4;sizeof(s7)为12
b:当自身大小小于n时:那么为自身大小的的整数倍:如:
struct s5{ char a; char b; int c; double d;};doube为8,cacheline为8,没有指定,那么n为8,sizeof(s5)为16
3:总长度为n的总数倍,如:
struct s6{ char a; char b; double d; int c;};double为8,cacheline为8,那么n为8,sizeof(s6)为24
写代码的时候有一个宗旨:按所占字节大小从小到大排序。
转载地址:http://lquvi.baihongyu.com/