本篇文章承接上文继续介绍 DDR 内存的硬件原理, 包括如何寻址, 时序和时延以及可以为提高内存的效能可以有哪些方法.
上次虽然解决了小张的问题, 却引发了他对内存原理的兴趣. 这不他又来找我了, 说我还欠他一个解释. 这次我们约在一个咖啡馆见面, 这次内容有点深入, 我带了些图片, 小张也点了一大杯美式, 计划大干一场. 看着他认真的样子, 我也决定毁人不倦, 把他也带入 IT 工程师的不归路...
寻址(addressing)
为了了解前几天说的几个延迟参数, 不得不介绍下 DIMM 的寻址方式. 也许你发现了上次介绍 Rank 和 chip 的关系时, 有个 Bank/Column/row 我们没有讲到, 它们和如何寻址密切相关. 还记得上次的图片吗?
这次我们来看看 rank 和 Chip 里面有什么, 如下图:
这是个 DDR3 一个 Rank 的示意图. 2GB 的内存共有 16 个 chip, 每个 chip 容量为 128MB. 我们把左边 128MB Chip 拆开来看, 它是由 8 个 Bank 组成, 每个 Bank 核心是个一个存储矩阵, 就像一个大方格子阵. 这个格子阵有很多列 (Column) 和很多行(Row), 这样我们想存取某个格子, 只需要告知是哪一行哪一列就行了, 这也是为什么内存可以随机存取而硬盘等则是按块存取的原因.
XXXX,CAS# 和 RAS# 只有一根信号线. 实际上每个格子的存储宽度是内存颗粒 (Chip) 的位宽, 在这里由 8 个 Chip 组成一个 Rank, 而 CPU 寻址宽度是 64bit, 所以 64/8=8bit, 即每个格子是 1 个字节. 16384rows*1024columns*8bank=128MB. 每一个格子都是由一个晶体管和一个电容组成.
对于 DDR3, 我们通常说它是 8n-prefetch(这儿 n 是指每个 rank 的 bank 数目), 因为 DDR3, 每个 IC 有 8 个 bank, 每个 bank 读取数据的最小单位是 8bit, 一个 byte. 每次数据读取 request, 都会读取 8*8bit=64bitdata, 而不管这些数据是否都是我们所需要的, 比如我们只需要其中的某个 byte, 但读 request 会读取 8 个 byte.
选择每个格子也不是简单的两组信号, 是由一系列信号组成, 以这个 2GB DDR3 为例:
1. 片选 (Chip Select) 信号, S0# 和 S1#, 每个用于选择是哪个 Rank.
2. Bank 地址线, BA0-BA2, 2^3=8, 可以选择 8 个 Bank
3. 列选 (Column Address Select), CAS#, 用于指示现在要选通列地址.
4. 行选(Row Address Select),RAS# 用于指示现在要选通行地址.
5. 地址线, A0-A13, 用于行和列的地址选择(可并不都用于地址, 本处忽略).
6. 数据线, DQ0-DQ63, 用于提供全 64bit 的数据.
7. 命令, COMMAND, 用于传输命令, 如读或者写等等.
注意这里没有内存颗粒的选择信号线, 只有 Rank 的选择信号. 在 Rank 选择好后, 8 个内存颗粒一起被选中, 共提供 64bit 的数据.
读取和写入数据也稍微复杂点, 简单来说分为以下三步:
1. 行有效. RAS# 低电平, CAS# 高电平. 意味着现在行地址有效, 同时在 A0-A13 传送地址信号, 即 2^13 个 Row 可以选择.
2. 列有效. RAS# 高电平, CAS# 低电平. 意味着列地址有效, 这时在 A0-A13 上传送的是列地址. 没错, A0-A13 是行列共用的, 所以每个格子选择需要有 1 和 2 两步才能唯一确定.
3. 数据读出或写入. 根据 COMMAND 进行读取或者写入. 在选定好小方格后, 就已经确定了具体的存储单元, 剩下的事情就是数据通过数据 I/O 通道 (DQ) 输出到内存总线上了.
这里只介绍随机访问, Burst 模式这里略过. 下图是个简单的图示:
时序(Timing)
一气说了这么多, 我不禁口干舌燥, 停下来喝了一大口咖啡. 小张以为我说完了, 着急的问我:"我好像听懂了, 不过那好几个数字还没讲呢.". 别着急啊, 且听我慢慢道来. 正因为访问一个数据需要大致三步, 为了保证信号的完整性, 步骤直接要有区隔, 一起发出来会造成错乱, 间隔太近也会为采样带来难度, 容易引入噪音. 所以时序非常重要,
下面是个背对背 (back-to-back) 读写的时序图:
时延(Latency)
小张一看到这个图, 不禁大叫:"太复杂了, 看得我都犯密集恐惧症了, 看不懂!". 没关系, 我们拆开了一个个看.
1. CL: CAS Latency.CL 是指 CAS 发出之后, 仍要经过一定的时间才能有数据输出, 从 CAS 与读取命令发出到第一笔数据输出的这段时间, 被定义为 CL(CAS Latency,CAS 时延). 由于 CL 只在读取时出现, 所以 CL 又被称为读取时延(RL,Read Latency). 也就是我们上面第 3 步读取时需要的时间. CL 是延迟里面最重要的参数, 有时会单独在内存标签上标出如 CLx. 它告诉我们多少个时钟周期后我们才能拿到数据, CL7 的内存会延迟 7 个周期才能给我们数据, CL9 的则要等 9 个. 所以越小我们越能更快的拿到数据. 注意这里的周期是真正的周期而不是标注的 DDR3 1333MHz 的周期, 因为一个周期传输两次, 真正的周期只是 1/2, 这里是 666MHz. 如下图, 是 CL7 和 CL9 的例子:
如果相同频率的内存, CL7 可以比 CL9 有 22% 的效能提高.
2. tRCD:RAS 到 CAS 时延. 在发送列读写命令时必须要与行有效命令有一个间隔, 这是根据芯片存储阵列电子元件响应时间所制定的延迟. 即步骤 1 和 2 要间隔的时间. 这个间隔当然也是越快越好了, 下面是个 tRCD=3 的例子:
你也可以看出这个时间也是激活命令和读命令的间隔.
3. tRP: 预充电有效周期(Precharge command Period). 在上一次传输完成后到下一次行激活前有个预充电过程, 要经过一段充电时间才能允许发送 RAS. 也就是步骤 1 的准备工作要做多久. 下面是个例子:
还有两个类似的时延 tRAS 和 CMD, 我看到小张都快睡着了就不讲了. 总之, 所有这些时延共同构成了整体时延, 而时延是越小越好.
SPD
说了这么多, 小张总算搞懂内存标签条上的 4-4-4-8, 5-5-5-15, 所代表的 CL-tRCD-tRP-tRAS-CMD 都是啥意思了. 不过小张有点搞不懂, 这些数据印在纸上消费者是看懂了(实际上似乎没多少人了解), 可电脑又没长眼睛, 它是怎么知道的呢? 其实, 每个 DIMM 在板子上都有块小的存储芯片(EEPROM), 上面详细记录了包括这些的很多参数, 还有生产厂家的代码等等, 这也是 BIOS 为什么能知道我们插了哪种内存的原因. 在小张的内存条上, 我指给了他看:
实际上随着 DDR 的一步步进化, 这些延迟的时钟周期个数也在步步提高, 但由于频率的加快, 实际上是在时间是在慢慢的减少的.
效能提高的其他手段
看时间还早, 我和小张聊起了除了提高频率, 还有什么办法能够提高内存存取速度.
1. 多通道(Channel)
现代内存控制器都从北桥移入 CPU 内部, 而且内存控制器都可以同时操作多个通道. 典型的台式机和笔记本 CPU 很早就支持双通道, 现在还加入了三通道. 如果数据分布在插在不同的通道上的内存条上, 内存控制器可以不管上面这些延迟啊时序啊, 同时可以读取他们, 速度可以翻倍甚至三倍! 小张听了跳了起来:"我也要翻倍!". 别急, 要启用多通道, 首先要插对插槽. 现在主板制造商为了让小白用户插对内存条, 通常用颜色标识内存通道. 注意同一个通道颜色不同! 所以要把内存插在颜色相同的内存插槽里, 才能让内存占据不同的通道. 最好有主板手册检查一下, 插好后进入 BIOS 里面看看现在内存状态是不是多通道模式.
2.Interleave
看着小张跃跃欲试的样子, 我不禁给他泼了盆冷水. 幻想美妙, 现实残酷. 多通道在很多时候用处并不明显! 因为程序的局部性, 一个程序并不会把数据放到各个地方, 从而落入另一个 DIMM 里, 往往程序和数据都在一个 DIMM 里, 加上 CPU 的 Cache 本身就会把数据帮你预取出来, 这个提高就个不明显了. 除非你运行很多巨型任务才行.
"啊, 我都是开一个游戏打, 对我来说没啥用处啊, 简直是鸡肋!", 小张说. 也不尽然, 还有种办法, 就是让同一块内存分布到不同的通道中去, 这种技术叫做 Interleaving. 这样无论 Cache 命中与否都可以同时存取, 多通道的技术才能发挥更大的用处."太好了, 要怎么才能开启这个 interleave 呢?", 我不禁呵呵了, 这个功能一般只有服务器 CPU 才有, 你的 i5 要是有了, 谁去买几千上万的服务器 CPU 呢?
3.Overclock
"你这不是废话吗, 我要怎么样才能搭建个发烧机才配有的高速内存呢?". 其实小张可以购买发烧级的内存条. 这些内存条 DDR3 标注达到 2133 以上! 但是要注意, 如果我们把这些内存插入一般主板, 很有可能会运行在 1333 或者 1600 上面, 因为这是 DDR3 规定的最高频率. 好马配好鞍, 要有个能支持超频内存的主板, 在主板 BIOS 里面升压升频才能真正用好这些发烧内存条.
尾声
时间差不多了, 我向小张保证下次还会介绍神秘的 BIOS 如何初始化内存, 正要离去. 小张拉住了我, 说:"你上次挖的坑还没填呢!"" 什么坑?"也许是我挖坑太多, 记不住了." 就是上次你让我回去想的三个问题. 第一个我知道了, DIMM 有防呆口, 几代 DDR 防呆口位置不同, 插不进去, 我在网上 google 过了, 后面两个实在想不出来 ". 好吧, 那我们长话短说, 实际上两个问题可以一起回答, 今天我们知道 DDR 每代的各种时延参数是上升的, 所以如果两代一样的频率, 实际上性能有可能还会下降! 譬如 DDR2 800 在很多时候比 DDR3 800 的时延要小. 我们可以认为每代的起点比前一代的低, 有一段重合期, 在频率上去后会弥补时延的时钟个数差异, 比较时延是 clock 个数, 而不是时间, clock 快了, 有可能时延会更小. 而这段重合期, 也为不同的商业策略留下了空间.
小张还是抓住我, 他不知道从哪里查了些名词, 什么预取个数每代增加, 而内核频率不同于外部频率等等. 我希望他能自己找找资料看看, 也顺便挖了个新坑:
1. 为什么每代 DDR 要升级, 不直接把频率向上提高就行了, 为什么没有 DDR2 3200 的内存?
2. DDR 的内存还是并行的数据, 串行似乎可以更高速, 比格更高, 为什么不弄个串行访问的内存呢?
小张陷入了沉思, 我也暗喜又骗到一顿咖啡下午茶. 不过回去还要准备些材料才能继续混吃混喝, 下次介绍完内存的 BIOS 部分, 还有啥题目可以继续吸引小张呢?
来源: http://www.bubuko.com/infodetail-2876874.html