比如有一个内存条,总容量为: 64 Bit
有一个 16 bit
的 CPU
这个时候,cpu
读取内存只能是 [0,16)
、[16,32)
、[32,48)
这样吗?
不能是 [3,19)
、[6,22)
这样吗?
[0,16) 表示读取内存条第 0 个 bit(包含)到第 16 个 bit(不包含)
[3,19) 表示读取内存条第 3 个 bit(包含)到第 19 个 bit(不包含)
如果要读取 [3,19)
这样的地址范围的话,是不是要分成 [0,16)
、[16,32)
分成两次读取,是这样吗?
假设这个问题讨论的是现代 CPU,比如 intel 的i9-12900k
, AMD 的5990x
, Apple 的m1 max
,高通的8 gen1
这些现代化的 64 bit 的 cpu,是不是必须是[0,64)
、[64,128)
、[128,192)
按照 64 的倍数来读取内存?还是说他们是支持非整数倍操作内存的?(包括读和写)
理论上可以这么读,但不经济,原因在于CPU并不直接和内存打交道,因为内存实在太慢...了。
CPU 通常是和1级2级3级缓存打交道,不得已才读写内存。读写内存通常是一整块一整块的读,这样效率高。这就像汽车的油箱和加油站的关系,加油费时间,但一次加一箱和加一升的时间差别不太大。发动机会首先从油箱里取,没有了才会去加油站,没人一次加一升。
那为什么一定要内存对齐呢?
简单地说,还是因为这么做效率高。磁盘存储是分块的,内存也是按页管理,CPU 也是按32/64/128位来寻址和处理数据。如果可以任意偏移读写,会有的大量的计算都要浪费在偏移处理上,硬件设计上也不容易。所以没人这么做。
这就好比做工业化的鸡蛋篓,一篓装32个,可以设计好机器可以很愉快地自动装载,但你这一篓非要装31个,为实现单拿出一个的需求,需要设计复杂得多的机器/算法/操作才能实现。提这样需求的人会被打的,所以没有人这么干。