-
虚拟地址:软件层程序使用的地址。 -
物理地址:CPU中使用的地址。 -
内存地址:真正的内存条中数据的地址。
在内存系列完结后,我计划开启Cache系列。因此VIPT、PIPT啥的,到Cache系列再细聊吧。本篇先简单提一下,CPU使用物理地址检索Cache。因此,CPU内会使用物理地址(也会使用虚拟地址,因为L1 Cache是VIPT)。
最后一个内存地址,这是一个数据在内存中真正的地址。
如果指令是访存访存指令,常见的如load/store,Core会把物理地址发送给MC(内存控制器)。MC会把物理地址按编址规则解析为内存地址,然后再和内存交互,读写数据。
内存地址大概长这个样子:
通道号:RANK号:BG号:Bank号:行号:列号
更准确的说法,应该是“内存地址中包含以上信息”。这里的内存通道、RANK、BG、Bank和Memory Array中的行、列,这些概念我们在前17篇中,反复提到了,这里不再赘述。
我当时看到这样的内存地址时,第一时间就觉得,这好像我们的住址一样啊,某城市、某区/县、某街道、某小区、几号楼、几单元、几号。
我之所以详细讲这一块,主要是地址和性能关系是很密切的。比如,一名快递小哥要送快递,最快的方式,就是把1号楼所有快递全送到,再去送2号楼的。
较慢的方式就是跑1号楼送一件快递,再跑2号楼送一件,再去1号楼送一件,……。
这是常识。
我们在访问内存时也一样。只不过,我们要根据编址规则,合理的排列我们的数据,才能让快递员(CPU或MC)以最快方式访问内存,以提升吞吐、缩短延迟。
具体要怎么做呢?
先得破译出来“编址规则”,即,“物理地址是按照什么样的规律转换为内存地址”。
但编址规则是CPU/GPU各类芯片厂商的商业秘密,通常不轻易示人。
好在破译它也并非不可能,接下来几篇我们就要聚焦这个问题,破译下CPU中内存控制器的编址规则。然后根据编址规则,看看如何排列我们的数据,才能进一步压榨出CPU与内存的潜力。
在破译编址规则之前,还要回到前面“流量”观测的话题,因为通过“观测流量”破译编址规则,是最简单的方式。
从第11到第15篇,我用5篇文章详细描述了如何在RANK层观察内存流量:
后续,我们要更进一步,在BG层、Bank层计算流量。
在内存系列11~15中,我提供了两种方式统计流量:
-
使用perf_event_open()系统调用,自行开发监控程序 -
使用 perf 工具
perf_event_open()是 perf 工具的基础,使用它可以得到更精确的流量,但如果对 perf工具 原理并不是特别感兴趣,直接使用perf能更快上手。
后续,我将尽量使用 perf 工具,力求让大伙都可以用最简单的方式,上手研究内存原理,复现和我类似的测试结果。
最后附上内存系列前17篇,包括NUMA系列(NUMA的基础知识马上就要用到了);
内存基础知识(十六)-- Rank/Chip/BG/Bank,软硬结合彻底搞懂内存底层结构
另外,我之前还写过一个 NUMA 系列,NUMA相关的基础知识,马上也要用到了:
还有这个系列,讲CPU执行阶段流水线的,虽然和内存没有直接关系,但个人感觉相当不错,值得阅读:

