TA的每日心情 | 开心 2016-9-26 15:28 |
|---|
签到天数: 56 天 [LV.5]常住居民I
|
消息来自- 浙江杭州
CPU 的访问粒度不仅仅是大小限制,地址上也有限制。也就是说,CPU 只能访问对齐地址上的固定长度的数据。
以四字节对齐为例,就是只能访问 0x0 - 0x3,0x4 - 0x7, 0x8 - 0xc 这样的(闭)区间,不能跨区间访问。
如果真正需要访问的数据并没有占据那个区间的全部字节范围,还有另外的信号线来指出具体操作哪几个字节,类似于掩码的作用。好像也有些架构干脆就不允许这种部分访问,强制要求按粒度访问。
如果一个数据跨越了两个这样的区间,那么就只能将这个数据的操作拆分成两部分,分别执行,效率当然就低了。
解决这个问题的一个办法就是强制数据对齐,现在假设一个 16 字节对齐的系统(稍微新一点的 x86 架构应该都是 16 字节对齐):
显然,一个字节无论如何不会跨越两个对齐区间;
当一个 2 字节的数据放在奇数地址上,就有可能跨越两个区间,但放在偶数地址上(即 2 字节对齐)就肯定不会;
同样,只要 4 字节数据放在 4 字节地址上,8 字节数据放在 8 字节地址上,一定不会跨越两个区间
假定你工作在32位机上,
假定你分配的变量的起始地址为0x00000001H,是一个占四字节空间的整形量。
这个地址就不是按照四字节地址对齐的,处理器在访问这个变量是,由于处理器的数据总线位宽是32位,所以处理器必须进行两次内存访问操作,第一次从地址0x00000000h-0x00000003读入一次,第二次从0x00000004-0x00000007读入一次,然后再将0x00000001H-0x00000003和0x00000004H的内容进行组合,才得到了你想要获得的数据,这样会造成性能的下降。
当你使用编译器开关进行4字节对齐时,只需要一次访内操作,就可以读入一个整型数
为啥要对齐,这个要从总线的硬件实现上来讲了
而你在编代码的时候写的#pragma pack(1),并不会改变CPU访问总线的方式
#pragma pack(1)只是让编译器不再对齐,而没有让CPU访问内存不对齐
这硬件对齐而软件不对齐的差异要靠CPU花时间来解决。 |
|