博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
内存对齐之深度探索
阅读量:4316 次
发布时间:2019-06-06

本文共 1647 字,大约阅读时间需要 5 分钟。

(废话:最近接触到内存对齐概念,针对内存对齐的规则,我在vc中一一进行了验证,发现编译器确实对我的数据进行了内存对齐。我便知道内存对齐必定是有它的优点所在,是什么呢?我找的资料都是说内存对齐可以提高内存访问效率、可移植到不同的平台等等,但是为什么会这样呢,没有一个清晰的解释。下面便是我多天努力的成果!)

编译器为什么要替我们内存对齐?

学了计算机组成原理,了解了内存的基本单元是一个字节,内存可以随机寻址,于是乎我天真的认为内存就是一个字节型的容器,基本单位是单个字节。
Figure 1. 我眼中的内存空间布局
How Programmers See Memory
悲剧的是,内存读写的真正访问者cpu不是这么想的。cpu是根据内存访问粒度(memory access granularity,下文简写成MAG)来读取内存,MAG就是cpu一次内存访问操作的数据量,具体数值依赖于特定的平台,一般是2byte、4byte、8byte。
Figure 2. cpu眼中的内存空间布局
How Some Processors See Memory
因此,程序员和cpu看待内存空间布局是存在差异的。唉,既不能过多的苛刻程序员,又要让cpu舒服,怎么办呢?只好让编译器来对我们的代码进行隐式的内存对齐(当然它能做的只是帮程序中的数据进行内存对齐,至于直接用指针去访问内存,它是不会管的)。
向开发编译器的大大们致敬!

内存对齐的好处

下面用一个小实例来剖析内存对齐的好处:很简单,在32位的机器下,分别访问一个内存对齐的地址空间(从地址0开始)和一个没有对齐的地址空间(从地址1开始),读取四个字节到cpu的寄存器中,比较两者的读取过程。
Case1:内存访问粒度为1个字节(cpu眼中的内存模型等价于程序员眼中的内存模型):
Figure 3. MAG=1
Single-byte memory access granularity
Result:读取4个字节,两者都需要进行4次内存访问操作。打平,在MAG=1的情况下不需要考虑内存对齐。
Case2:内存访问粒度为2个字节:
Figure 4. MAG=2
Double-byte memory access granularity
Result:读取4个字节,左边的(内存对齐地址)只需要进行2次内存访问操作,右边的需要进行3次内存访问操作+附加操作(见下文)。内存对齐地址取胜!
Case3:内存访问粒度为4个字节:
Figure 5. MAG=4
Quad-byte memory access granularity
Result:读取4个字节,左边的只需要进行1次内存访问操作,右边的需要进行2次内存访问操作+附加操作。内存对齐地址再次取胜!
Conclusion:
内存对齐地址vs没有内存对齐的地址,在三种不同的内存访问粒度下,取得了2胜一平的完胜战绩。对于32位的机器,实际的内存访问粒度是4个字节,原因如下:
  • 每一次内存访问操作需要一个常量开销;
  • 在数据量一定的情况下,减少内存访问操作,能提高程序运行性能;
  • 增大内存访问粒度(当然不超过数据总线的带宽),能减少内存访问操作(从上面的实例就能够看出来);
一句话,内存对齐确实可以提高程序性能。

cpu如何处理没有内存对齐的数据访问?

继续分析上面那个实例,在内存访问粒度为2、从地址1开始读取四个字节的cpu处理过程(硬件方式):
  1. 读取数据所在的第一块内存空间(0-1),移除多余字节(0);
  2. 读取数据所在的第二块内存空间(2-3);
  3. 读取数据所在的第三块内存空间(4-5),移除多余字节(5);
  4. 把三块数据拼接起来(1-4),放入寄存器中。
访问一块相同大小的数据,内存对齐的优势是多么的巨大!
如果cpu能这么来处理,也只不过是影响了我们程序的运行性能,至少还是能运行的!悲剧的是,以前的cpu并没有这么“勤快”,遇到没有内存对齐的数据访问,它会直接抛出一个异常:操作系统可能会响应这个异常,用软件的方式来处理,性能只会更差;或者程序直接崩溃掉。
一句话,内存对齐的代码确实具有更高的可移植性!
Over!更多内容,参照此文:
内存对齐的具体规则,参照此篇博客:

转载于:https://www.cnblogs.com/newhand-liu/archive/2012/05/29/2793272.html

你可能感兴趣的文章
BeforeFieldInit的小叙
查看>>
TeamViewer的下载地址,低调低调
查看>>
005 线程ID和线程的优先级
查看>>
POJ 3067 Japan (树状数组 && 控制变量)
查看>>
python基础条件和循环
查看>>
an exciting trip
查看>>
【转】xmind8 破解激活教程
查看>>
Mysql用命令方式启动服务
查看>>
【贪心】codeforces A. Heidi and Library (easy)
查看>>
【leetcode】lower_bound
查看>>
跨站请求伪造(CSRF)
查看>>
EF Code First数据库映射规则及配置
查看>>
.Net StackFrame
查看>>
Qt 学习之路:视图选择 (QItemSelectionModel)
查看>>
QStyleFactory类参考
查看>>
ng-深度学习-课程笔记-2: 神经网络中的逻辑回归(Week2)
查看>>
正则表达式的搜索和替换
查看>>
个人项目:WC
查看>>
地鼠的困境SSL1333 最大匹配
查看>>
flume+elasticsearch+kibana遇到的坑
查看>>