内存对齐的影响
2015-07-29 11:07
267 查看
先说理论的:为何要内存对齐?
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。
图一:
这是普通程序员心目中的内存印象,由一个个的字节组成,而CPU并不是这么看待的。
图二:
CPU把内存当成是一块一块的,块的大小可以是2,4,8,16字节大小,因此CPU在读取内存时是一块一块进行读取的。块大小成为memory accessgranularity(粒度)本人把它翻译为“内存读取粒度”。
假设CPU要读取一个int型4字节大小的数据到寄存器中,分两种情况讨论:
1、数据从0字节开始
2、数据从1字节开始
再次假设内存读取粒度为4。
图三:
当该数据是从0字节开始时,很CPU只需读取内存一次即可把这4字节的数据完全读取到寄存器中。
当该数据是从1字节开始时,问题变的有些复杂,此时该int型数据不是位于内存读取边界上,这就是一类内存未对齐的数据。
图四:
此时CPU先访问一次内存,读取0—3字节的数据进寄存器,并再次读取4—5字节的数据进寄存器,接着把0字节和6,7,8字节的数据剔除,最后合并1,2,3,4字节的数据进寄存器。对一个内存未对齐的数据进行了这么多额外的操作,大大降低了CPU性能。
这还属于乐观情况了,上文提到内存对齐的作用之一为平台的移植原因,因为以上操作只有有部分CPU肯干,其他一部分CPU遇到未对齐边界就直接罢工了。
我所遇到的问题:
在项目中要按协议解析一接收到的字串,从中提取数据。
环境为MSP430,裸奔程序。
刚开始使用的方法是,取串中对应数据段的首地址,将其强制转换成目标数据的数据类型指针,再取其值,将该值赋予目标对象。
以下是示意代码:
/*******************code start**********************/
// 找到指定数据的地址,pcSrcData指向传入的数据,MY_DATA_IDX是所需提取数据的相对地址
pcSrcData += MY_DATA_IDX;
// 提取我所需要的数据
fMydata = *((float *)pcSrcData);
/*******************code end**********************/
分析此代码,实际上我是要从任意地址上访问一个四字节的FLOAT数据,可能遭遇以下3种情景:
地址对齐,访问成功,此情况纯属巧合;
地址未对齐,CPU具有在未对齐情况下,CPU依然支持通过多次访问移位操作,对程序来说也可认为是成功的;
地址未对其,CPU也不支持未对齐情况下的纠错处理。
很不幸,也很幸运,在测试时我就遇到了第三种情况。但又不完全相同,此时CPU仍在访问,不过它对地址进行了调整,将其调整为四字节对齐,这样它是能正常访问了,可我的数据却提取错了。
处理方法:
/*******************code start**********************/
// fMydata = *((float *)pcSrcData);将此语句改为下面这句
memcpy(&fMydata , pcSrcData, sizeof(float));
/*******************code end**********************/
从这件事吸取的经验是态度上要谨慎再谨慎,不能有侥幸心理。
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。
图一:
这是普通程序员心目中的内存印象,由一个个的字节组成,而CPU并不是这么看待的。
图二:
CPU把内存当成是一块一块的,块的大小可以是2,4,8,16字节大小,因此CPU在读取内存时是一块一块进行读取的。块大小成为memory accessgranularity(粒度)本人把它翻译为“内存读取粒度”。
假设CPU要读取一个int型4字节大小的数据到寄存器中,分两种情况讨论:
1、数据从0字节开始
2、数据从1字节开始
再次假设内存读取粒度为4。
图三:
当该数据是从0字节开始时,很CPU只需读取内存一次即可把这4字节的数据完全读取到寄存器中。
当该数据是从1字节开始时,问题变的有些复杂,此时该int型数据不是位于内存读取边界上,这就是一类内存未对齐的数据。
图四:
此时CPU先访问一次内存,读取0—3字节的数据进寄存器,并再次读取4—5字节的数据进寄存器,接着把0字节和6,7,8字节的数据剔除,最后合并1,2,3,4字节的数据进寄存器。对一个内存未对齐的数据进行了这么多额外的操作,大大降低了CPU性能。
这还属于乐观情况了,上文提到内存对齐的作用之一为平台的移植原因,因为以上操作只有有部分CPU肯干,其他一部分CPU遇到未对齐边界就直接罢工了。
我所遇到的问题:
在项目中要按协议解析一接收到的字串,从中提取数据。
环境为MSP430,裸奔程序。
刚开始使用的方法是,取串中对应数据段的首地址,将其强制转换成目标数据的数据类型指针,再取其值,将该值赋予目标对象。
以下是示意代码:
/*******************code start**********************/
// 找到指定数据的地址,pcSrcData指向传入的数据,MY_DATA_IDX是所需提取数据的相对地址
pcSrcData += MY_DATA_IDX;
// 提取我所需要的数据
fMydata = *((float *)pcSrcData);
/*******************code end**********************/
分析此代码,实际上我是要从任意地址上访问一个四字节的FLOAT数据,可能遭遇以下3种情景:
地址对齐,访问成功,此情况纯属巧合;
地址未对齐,CPU具有在未对齐情况下,CPU依然支持通过多次访问移位操作,对程序来说也可认为是成功的;
地址未对其,CPU也不支持未对齐情况下的纠错处理。
很不幸,也很幸运,在测试时我就遇到了第三种情况。但又不完全相同,此时CPU仍在访问,不过它对地址进行了调整,将其调整为四字节对齐,这样它是能正常访问了,可我的数据却提取错了。
处理方法:
/*******************code start**********************/
// fMydata = *((float *)pcSrcData);将此语句改为下面这句
memcpy(&fMydata , pcSrcData, sizeof(float));
/*******************code end**********************/
从这件事吸取的经验是态度上要谨慎再谨慎,不能有侥幸心理。
相关文章推荐
- 如何查看我的订单-REST的流程API设计案例
- inux查看进程的所有子进程和线程
- java访问控制的理解
- HDOJ 2120 Ice_cream's world I(并查集判断成环)
- 使用PhoneGap打包HTML成iOS应用
- hdu1203
- java Map对象排序demo
- URAL 1934 最短路变形
- 关于windows服务的操作
- Error:No such property: GROUP for class: org.gradle.api.publication.maven.internal.deployer.DefaultGroovyMavenDeployer
- 每天一个linux命令(2):cd命令
- MPMoviePlayerViewController和MPMoviePlayerController的使用
- poj3074 DLX精确覆盖
- Js 动态插入css js文件
- 202.Happy Number
- 不吐不快之EJB演练——开篇概述
- QTableView的滚动条设置样式
- 算法导论2.3.2--归并排序
- 玩转Android---UI篇---WebView(网络视图)
- Android中定时执行任务的3种实现方法