我们平时看到内存条,有的上面单面有8个内存颗粒:

1R X 8 DIMM

有的则有16个内存颗粒:

2R X 4 DIMM;多出来几个颗粒是ECC校验用

甚至还有单面32个颗粒的超高怪物:

4R X 4 DIMM

前文中我们讨论了服务器能够支持的内存最大容量:

老狼:服务器最大内存是多少?制约因素有些什么呢?​zhuanlan.zhihu.com

我们得出了结论:最大内存是由能够插多少条内存决定的,因为每根内存条现在最大128GB,整体内存容量就被限制了下来,这不是钱多钱少的问题。有读者对每根内存条的极限容量感兴趣。是不是我们有钱,可以通过不停增加颗粒数目来堆出超高内存容量的内存条呢?答案当然是否定的了。今天我们就一起来探讨一下问什么。

首先我们假定不考虑内存颗粒能不能做出这么大的容量,仅仅理论探讨。限于篇幅,为了简化讨论范围,我们给问题设置了一些限制:

1.仅讨论大家DDR4,包括UDIMM DDR4和RDIMM DDR4。DDR3因为本身支持的容量就小而且基本已被淘汰,我们就不必哀悼它了。DDR5目前还没有上市,我们等它成熟后再来重新回顾它的理论极限。LRDIMM会有些许顾及,担不是重点。

2.讨论基于DDR内存的标准:JEDEC标准。

内存条的容量和它的基本单位:内存颗粒的组织方式息息相关。如果我们仔细看上面那三种内存条和我的注解,你能不能发现一些规律呢?细心的同学也许发现了:越大的内存容量,nR中的n就越大;与此相反,越大的内存容量,X n中的n反而越小。这是为什么呢?我们需要从DRAM的原理讲起。

DRAM原理

内存DRAM的每个单元可以看作一个晶体管和一个电容的组合:

电容负责存储,充过电时是1,没充过电是0,这就是内存是如何存储数据的。晶体管是个开关,用于选中该电容。Word line被选中,晶体管导通,电容的就和bit line导通,可以读出0和1。正是因为内存每个单元如此简单,才能如此大规模组织起来,形成低价而密度很高的内存颗粒。

这种方式设计简单,但是在充放电时电压和电荷管理有很多麻烦。所以引入了Sense Amplifier。单元就变成了这样:

单元还是只有一个电容和一个晶体管。但Sense Amp就复杂了不少:

示意图

Sense Amp一般由6个以上的晶体管组成。比较昂贵,但是因为整个bank只有一组Sense Amplifier,所以问题不大,而且好处不少。

好了,有了单个单元,我们来组成一个内存组试试:

绿色箭头是Sense Amp

看起来简单而优美,一个word line,选中后所有16单元都被Sense Amp缓存,漂亮!慢着,似乎那里不对?是的,这样效率太低,原来1个单元有1个晶体管和一个电容组成,现在平均变成了7个晶体管和1个电容,这和DRAM的低成本设计目标是违背的,必须减少Sense Amp的个数。有没有更好的解决办法呢?

这样好多了,还是16个存贮单元,但是仅仅用了4个sense amp,代价是word line从一个变成了4个。这是减低成本必须付出的代价。现在我们推广成更大的形式:

bank里的每个row共享一个word line,行激活ACT后,该row上的word line高电平,row上的存储内容会被该bank的Sense Amplifier缓存。这个内存单元有32个行地址(row address),32个列,5个列地址(column address)。地址线太多,有没有办法减低呢?如果一次列选中能够送出多个内容就好了:

X 4 内存array,32 Bit位宽

这样同样寻址这些单元,但列地址从5个,减小成3个。太棒了!

我们知道,X86的cache line是64 Bytes(感谢 @照猫画虎 @RLuo 发现原文中这个问题),它会一次向内存控制器请求整个cache line。内存控制器发现他们是连续的地址后,会用一次用burst方式读取8个字长,每字长是64个bits。64个bits是内存控制器读取的最小单位。这非常重要,为了完成必要条件,我们必须继续扩展内存单元:

X 4 内存array,64Bit位宽

我们数一下,共有16个column,4个column address。继续扩张成DDR4标准的4个bank就变成了:

X 4 内存array,64Bit位宽,4个bank

至于什么是bank,可以见我的这几篇入门文章:

老狼:内存系列一:快速读懂内存条标签​zhuanlan.zhihu.com

老狼:内存系列二:深入理解硬件原理​zhuanlan.zhihu.com

这就是现代内存组成的原理。

好了,我们可以回过头来看看: nR X m是啥意思了。

1.R是Rank的缩写,n是多少有个Rank。每个Rank有自己的片选信号:CS。各个rank单独工作,JEDEC标准DDR4可以取1,2,4个rank。

2.X m中的m就是前面讲的每个列的位宽,X4就是每列输出4个bit,X8就是每列输出8个bit。JEDEC标准只有4,8,16,三个选项。

明显的rank越多,用同种内存颗粒,可以做出的内存条容量就大。那么是不是内存颗粒X m,m越大,内存就大呢?恰恰相反,同样容量的内存颗粒,m越小,就可以用更多的内存颗粒拼起来,组成大内存。我们看个例子:

同样4Gb(注意这里是小b)的内存颗粒,为了组成64 Bit的位宽,我们可以用16个X 4颗粒,那么总容量是:

4 Gb X (64/4)= 64 Gb = 8GB

而用X 16的颗粒呢?只能用4个:

4 Gb X (64/16)= 16Gb = 2GB

那么单内存颗粒是不是容量就可以无穷大呢?并不是。

内存颗粒容量限制

内存颗粒并不能无限变大,因为没有那么多地址线。尽管从DDR开始,JEDEC标准就不停的增加地址线,但到了DDR4,地址还是有限的,这也是DDR5必须尽早出来的原因之一。地址线的多少决定了可以寻址多大空间,也决定了单颗内存容量的上限。

我们来看看DDR4对地址线的定义:

1.行地址:A0~A17共18根

2.列地址:A0~A9

3. Bank Addr:BA0,BA1两个

4. Bank Group: BG0,BG1两个

好了,我们可以来算算颗粒的容量了,如果我们用X4的颗粒

(2^18) X (2 ^10) X(2^2) X (2^2) X 4 = 16Gb

我们来算一下DIMM的容量:

16 Gb X 16个 X 4个rank = 128GB

这就是单根内存条的理论最大容量。

结论

单根UDIMM/RDIMM的容量最大128GB,这是JEDEC的标准所允许的最大容量。LRDIMM可以达到更大容量。它的原理我们今后再讲。

另外我们看到,如果选用X16的颗粒,单颗颗粒可以容量更大,但是总容量受只能用4个颗粒的限制,还是不能超过64GB。而同样容量的内存颗粒,因为单元数目相同,成本差别不大,为了组成更大内存,内存条厂商往往选择x 4的来组成大容量内存。这也就为什么超大容量内存条总是X 4的原因。

其他内存相关文章:

老狼:服务器最大内存是多少?制约因素有些什么呢?​zhuanlan.zhihu.com

老狼:神秘消失的内存去哪了?​zhuanlan.zhihu.com

老狼:内存系列一:快速读懂内存条标签​zhuanlan.zhihu.com

老狼:内存系列二:深入理解硬件原理​zhuanlan.zhihu.com

老狼:内存系列三:内存初始化浅析​zhuanlan.zhihu.com

老狼:Win10任务管理器中的"专用GPU内存"是怎么回事?“共享GPU内存”又是什么?​zhuanlan.zhihu.com

老狼:为什么现在的电脑都这么吃内存?​zhuanlan.zhihu.com

老狼:内存条应该怎么插?为什么要从远端插起?不遵循为啥还可以work?有啥副作用?​zhuanlan.zhihu.com

老狼:16个内存小问题,一次全部回答!​zhuanlan.zhihu.com

老狼:内存的容错设计是怎样的?内存容量比你看到的更大!​zhuanlan.zhihu.com

欢迎大家关注本专栏和用微信扫描下方二维码加入微信公众号"UEFIBlog",在那里有最新的文章。同时欢迎大家给本专栏和公众号投稿!

用微信扫描二维码加入UEFIBlog公众号

使用未初始化的内存是什么意思_单根内存条的极限容量是多少?内存条上的2R X 8代表了什么意思?...相关推荐

  1. 使用未初始化的内存是什么意思_他们都说JVM能实际使用的内存比-Xmx指定的少?这是为什么呢...

    这确实是个挺奇怪的问题,特别是当最常出现的几种解释理由都被排除后,看来JVM并没有耍一些明显的小花招: -Xmx和-Xms是相等的,因此检测结果并不会因为堆内存增加而在运行时有所变化. 通过关闭自适应 ...

  2. 使用未初始化的内存是什么意思_活动板房是什么意思?怎么装修?使用年限+价格知识点合集...

    活动板房是现在很多工地上都可以见到的一种房子,目的是给施工工人提供方便,那么活动板房可以住多长时间呢?怎么装修呢?什么?你还不知道活动板房是什么意思?那就赶紧来听听青岛装修网的讲解吧. 活动板房是什么 ...

  3. vs使用未初始化的内存怎么解决_遇到C语言内存错误怎么办?一定要找准这六个原因...

    一.没有为指针分配内存 定义了指针变量,但是没有为指针分配内存,即指针没有指向一块合法的内存.浅显的例子就不举了,这里举几个比较隐蔽的例子. 1.结构体成员指针未初始化 struct student ...

  4. c++ 使用未初始化的内存_C语言内存分布(内核区、堆栈区等)

    C语言内存分布(内核.变量,堆栈等) 内核区是提供给操作系统使用的.栈区是给局部变量使用的,局部变量是函数内定义的变量,包括函数系数:程序调用时把局部变量存的数据压入栈,程序退出时把局部变量存的数据弹 ...

  5. c语言使用未初始化的内存怎么解决_C语言快速入门——数组与调试进阶

    由ASCII码表的输出程序,我们可以认识到使用循环语句处理一组连续的数据有着巨大的优势.在更普遍的情况下,数据由一组离散的数值组成,如一组学生的考试成绩.对于这些数据的处理,有效的方式是使用循环.但前 ...

  6. vs使用未初始化的内存怎么解决_C语言内存操作陷阱总结

    微信公众号:二进制人生 专注于嵌入式linux开发. 更新:2020/07/21,内容整理自网络. 1.返回局部变量的地址,或者返回指向局部变量的指针 int *stackref(){ int val ...

  7. vs使用未初始化的内存怎么解决_C语言内存管理(转载)

    问题不能拖,我这就来学习一下吧,争取一次搞定. 在任何程序设计环境及语言中,内存管理都十分重要. 内存管理的基本概念 分析C语言内存的分布先从Linux下可执行的C程序入手.现在有一个简单的C源程序h ...

  8. visual studio C语言指针提示:使用未初始化的内存xx

    因为定义指针后直接使用: *p = *x; 这样的语句,虽然只是告警并未显示错误,但这样做确实是超出规则了,如果只看左边,p相当于是个野指针,*p当然是不行的 直接用 p = x 就没有问题 别乱用就 ...

  9. 使用未初始化内存的指针

    当我们使用未初始化的内存指针时,会导致程序无法进行,因为指针并没有指向一个合法的地址,这时候其内部存的只是一些乱码.所以在调用函数时,会使用乱码所指的内存,指针根本就无权访问,导致出错. 看一段代码 ...

最新文章

  1. WinRAR4.11-64Bit最简易的注册方法
  2. Python 任意中文文本生成词云 最终版本
  3. C语言算小数加减,C语言带小数加减乘除.doc
  4. Gnome即将满18岁,适用于Docker,Kali Linux 2.0的新工具以及更多新闻
  5. 读高性能网站建设指南
  6. Eclipse — 更改包名后导致服务器启动报异常
  7. GitHub上IOS开源项目
  8. ECMall插件——余额支付
  9. python怎么建立索引_python建立索引
  10. 阴阳师服务器维护3月14,3月14日阴阳师体验服更新:三个限定新式神
  11. 号外号外 !新媒之家APP2.1.0版本震撼上线!!!
  12. iOS 画板 涂鸦 答题
  13. CF Canada Cup 2016 D 优先队列
  14. php红包退回通知,php红包
  15. “宅一族”大数据报告:喜欢学习,喜欢健身,生活同样很精彩
  16. 升级 glibc 到2.18版本
  17. 【Arduino】基于阿里云的体感手柄
  18. 百度识图API教程二:EasyDL物体检测的使用
  19. 百度BML上传压缩包导入失败,“数据集本次导入完成,因压缩包解压未成功,导致部分样本未上传成功”
  20. 面试唯品会实习测试岗、抖音实习测试岗【真实投稿】

热门文章

  1. 搭建基于asp.net的wcf服务,ios客户端调用的实现记录
  2. windows2008下配置iis时出现错误“由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。”...
  3. SQL Server--用户自定义函数
  4. python3 安装模块_python3 Crypto模块的安装与使用
  5. java实现导出Excel的功能
  6. 养成这6个编程好习惯,助你减少90%BUG
  7. CSS3的background-size:可以设置高宽 百分比 最大大小 最小大小
  8. Go的sync.Mutex(七):互斥锁锁定一个资源 只有一个协程操作其他等待
  9. Yii设置响应数据的样式与内容
  10. c 窗体程序 mysql_C\C++开发MySQL程序简介(下)