• 带你深入理解内存对齐最底层原理


    https://zhuanlan.zhihu.com/p/83449008

    相信绝大多数的人都了解内存对齐,对齐后性能高。但是其最最底层的原理是啥呢? 有的人可能会说,因为高速缓存的工作机制。读者你很聪明,这是原因之一。但我今天想挖的是更底层一点的原理,让我们去内存的物理构成里找找答案!

    内存物理结构

    我们来了解一下内存的物理构造,一般内存的外形图片如下图:

    一个内存是由若干个黑色的内存颗粒构成的。每一个内存颗粒叫做一个chip。每个chip内部,是由8个bank组成的。其构造如下图:

    而每一个bank是一个二维平面上的矩阵,前面文章中我们说到过。矩阵中每一个元素中都是保存了1个字节,也就是8个bit。

    内存编址方式

    那么对于我们在应用程序中内存中地址连续的8个字节,例如0x0000-0x0007,是从位于bank上的呢?直观感觉,应该是在第一个bank上吗? 其实不是的,程序员视角看起来连续的地址0x0000-0x0007,实际上位8个bank中的,每一个bank只保存了一个字节。在物理上,他们并不连续。下图很好地阐述了实际情况。

    你可能想知道这是为什么,原因是电路工作效率。内存中的8个bank是可以并行工作的。 如果你想读取址0x0000-0x0007,每个bank工作一次,拼起来就是你要的数据,IO效率会比较高。但要存在一个bank里,那这个bank只能自己干活。只能串行进行读取,需要读8次,这样速度会慢很多。

    结论

    所以,内存对齐最最底层的原因是内存的IO是以8个字节64bit为单位进行的。 对于64位数据宽度的内存,假如cpu也是64位的cpu(现在的计算机基本都是这样的),每次内存IO获取数据都是从同行同列的8个chip中各自读取一个字节拼起来的。从内存的0地址开始,0-7字节的数据可以一次IO读取出来,8-15字节的数据也可以一次读取出来。

    换个例子,假如你指定要获取的是0x0001-0x0008,也是8字节,但是不是0开头的,内存需要怎么工作呢?没有好办法,内存只好先工作一次把0x0000-0x0007取出来,然后再把0x0008-0x0015取出来,把两次的结果都返回给你。 CPU和内存IO的硬件限制导致没办法一次跨在两个数据宽度中间进行IO。这样你的应用程序就会变慢,算是计算机因为你不懂内存对齐而给你的一点点惩罚。

    扩展1:事实上,编译和链接器会自动替开发者对齐内存的,尽量帮你保证一个变量不跨列寻址。但是他不能做到十分完美。
    扩展2:其实在内存硬件层上,还有操作系统层。操作系统还管理了CPU的一级、二级、三级缓存。不知道你有没有印象,我们前面的文章说过高速缓存里的Cache Line也是64字节,它是内存IO的整数倍,不会让内存IO浪费。
  • 相关阅读:
    Word 操作类库
    Windows服务卸载之后未重启机器之前再安装问题
    Word转Html
    Centos7下配置Python3和Python2共存,以及对应版本Ipython安装配置
    Linux 和Windows之间命令行实现目录或文件互传
    centos下卸载OpenJDK 并安装sun的jdk
    bridged(桥接模式)、NAT(网络地址转换模式)和hostonly(主机模式)VMware下三种网络配置方式
    关于centos启动报错:Failed to start Crash recovery kernel arming的解决方案
    centos7下固定IP(静态IP)网络配置
    【分享】BUG从诞生到灭亡——处理BUG的流程
  • 原文地址:https://www.cnblogs.com/nafio/p/13675321.html
Copyright © 2020-2023  润新知