双端口RAM和多模块存储器
存取周期
注:DRAM芯片的恢复时间比较长,有可能是存取时间的几倍(SRAM的恢复时间较短)
存取周期:可以连续读/写的最短时间间隔
如:存取时间为r,存取周期为T,T=4r;
多核CPU都要访存,怎么办?
CPU的读写速度比主存快很多主存恢复时间太长怎么办?
双端口RAM
作用:优化多核CPU访问同一根内存条的速度
需要有两组完全独立的数据线,地址线,控制线,CPU,RAM中也要有更复杂的控制电路
两个端口对同一主存操作有以下4种情况:
1.两个端口同时对不同的地址单元存取数据
2.两个端口同时对同一地址单元读出数据
3.两个端口同时对同一地址单元写入数据:写入错误
4.两个端口同时对同一地址单元,一个写入数据,另一个读出数据:读出错误
为了解决3和4这种情况,RAM向CPU发出"忙"的信号,置"忙"的信号为0,由判断逻辑决定暂时关闭一个端口(即被延时),未被关闭的端口正常访问,被关闭的端口延长一个很短的时间段后再访问。
体并行存储器
即便对于单核CPU,CPU的读取速度也比内存快得多,而内存读取后需要恢复时间后才能继续读取。这个问题的解决就可以使用多体并行存储器
高位交叉编址的多体存储器
可理解为"四根内存条":4*8=32=2^5;所以我们可以用5个bite作为主存的地址,高位的两个数表示体号,地址后面三位数表示体内地址.
低位的两个数表示体号,前三个数表示体内地址
每个存储体存取周期为T,存取时间为r,假设T=4r;
连续访问00000,00001,00010,00011,00100情况下:
低位交叉编址
下面的低位交叉编址的多体存储器耗时T+4r;而高位交叉编址的多体存储器耗时为4T;性能几乎提升了4倍
应该取几个"体"囊?
采用"流水线"的方式并行存取(宏观上并行,微观上串行)
宏观上,一个存储周期内,m体交叉存储器可以提供的数据量为单个模块的m倍。
存取周期为T,存取时间为r,为了使流水线不间断,应保证模块数m>=T/r.
m<T/r时
m>T/r时
m=T/r时
多模块存储器
多体并行存储器
每个模块都有相同的容量和存取速度。各模块都有独立的读写控制电路,地址寄存器和数据寄存器。他们既能并行工作,又能交叉工作.
单体多字存储器
每个存储单元存储m个字总线宽度也为m个字,一次并行读出m个字。
每次只能同时取m个字,不能单独取其中某个字,指令和数据在主存内必须时连续存放的
Cache的基本概念和原理
双端口RAM,多模块存储器提高存储器的工作速度,优化后速度与CPU差距依然很大
如何解决:我们可以设计更高速的存储单元,这就意味着我们存储价格就会更高;基于程序的局部性原理,我们增加一个"Cache-主存"层次
Cache的工作原理
注:实际上,Cache被集成在CPU内部Cache用SRAM实现,速度快,成本高;
空间局部性:在最近的未来要用到的信息(指令和数据),很可能与现在正在使用的信息在存储空间上是邻近的
时间局部性:在最近的未来要用到的信息,很可能是现在正在使用的信息
基于局部性原理,不难想到,可以把CPU目前访问的地址"周围"的部分数据1放在Cache中
设tc为访问一次Cache所需时间,tm为访问一次主存所需时间‘
命中率H:CPU欲访问的信息已在Cache中的比率
缺失(未命中)率M=1-H
Cache-主存 系统的平均访问时间t为
t=Htc+(1-H)(tc+tm)
先访问Cache,若Cache未命中再访问主存
或 t=Htc+(1-H)tm:同时访问Cache和主存,若Cache命中则立即停止访问主存
例题:
有待解决的问题
基于局部性原理,不难想到,可以把CPU目前访问的地址'周围:的部分数据放到Cache中,如何界定"周围"?
将主存的存储空间"分块',如:每1KB为一块,主存与Cache之间以"快"为单位进行数据交换
- 如何区分Cache与主存的数据块对应关系?--Cache和主存的映射方式
- Cache很小,主存很大.如果Cache满了怎么办?--替换算法
- CPU修改了Cache中的数据副本,如何确保主存中数据母本的一致性?--Cache写策略
下面的章节我将跟大家一起学习:
Cache和主存的映射方式
全相联映射--主存块可以放在Cache的任意位置
不了解有效位和标记是啥的可以先往下看,最后面有讲解
采用这种方式,CPU如何访问一个主存地址囊?
假设CPU访问主存地址,1..1101001110:
1.主存地址的前22位对比Cache中所有块的标记:
2.若标记匹配且有效位=1,则Cache命中,访问块内地址为001110的单元.
3.若未命中或有效位=0,则正常访问主存
直接映射--每个主存快只能放到一个特定的位置:Cache块号=主存块号%Cache总块数
直接映射,主存在Cache中的位置=主存块号%Cache总块数
例如主存中块号为0的0%8=0存储在Cache0的位置,主存中块号8,8%8=0,也是存储在0的位置,
缺点:其他地方有空闲Cache块,但是8号主存块不能使用
能否优化标记?
这里Cache有8行,主存块号%2^3,相当于留下最后三位二进制数;那么就意味着计算机只要读取22位中的后三位;
若Cache总块数=2^n则主存块号末尾n位直接反映它在Cache中的位置,将主存块号的其余位作为标记即可,Cache中只需要标记前19位,末尾三位不需要标记;
如何访存?
CPU访问主存地址:0...01000 001110:
1.根据主存号的后3位确定Cache行。
2.若主存块号的前19位与Cache标记匹配且有效位=1,则Cache命中,访问块内地址位001110的单元
组相联映射--Cache块分为若干组,每个主存块可放到特定分组中的任意一个位置组号=主存块号%分组数
主存块号%2^2,相当于我们只保留了主存块号的末尾两位,因此只需要看末尾两位就可以确定在被分配到哪,因此Cache中的标记只需要采用前20位即可。
CPU访问主存地址:1...1101001110:
1.根据主存块号的后两位确定所属分组号
2.若主存块号的前20位与分组内的某个标记匹配且有效位=1,则Cache名中,访问块内地址为001110的单元.
那么如何区分Cache中存放的是哪个主存块?
给每个Cache块增加一个"标记",记录对应的主存块号?光有"标记"就行了嘛?
假设9,8,5代表的是主存中数字在Cache中存放的位置;0代表没有空闲的位置,那主存中也存在0这个位置,不就表达有歧义了嘛?所以还要增加"有效位:1代表存储,0代表空闲
Cache替换算法
全相联映射
Cache完全满了才需要替换需要在全局选择替换哪一块
直接映射
如果对应位置非空,则毫无选择地直接替换
组相联映射
分组内满了才需要替换需要在分组内选择替换哪一块
随机算法--若Cache已满,则随机选择一块替换;
设总共有4个Cache快,初始整个Cache为空.采用全相联映射,依次访问主存块{1,2,3,4,1,2,5,1,2,3,4,5}
随机算法--实现简单,但完全没考虑局部性原理,命中率低,实际效果很不稳定
先进先出算法--若Cache已满,则替换最先被调入Cache的块
设总共有4个Cache快,初始整个Cache为空,采用全相联映射,依次访问主存块
{1,2,3,4,1,2,5,1,2,3,4,5}
先进先出算法--实现简单,最开始按#0#1#2#3放入Cache,之后轮流替换#0#1#2#3FIFO依然没考虑局部性原理,最先被调入Cache的块也有可能是被频繁访问的
近期最少使用算法--为每一个Cache块设置一个"计数器",用于记录每个Cache块已经有多久没被访问了,当Cache满后替换"计数器"最大的
设总共有4个Cache快,初始整个Cache为空,采用全相联映射,依次访问主存块
{1,2,3,4,1,2,5,1,2,3,4,5}
1.命中时,所命中的行的计数器清零,比其低的计数器加1,其余不变
2.未命中且还有空闲行时,新装入的行的计数器置为0,其余非空闲行全加1
3.未命中且无空闲行时,计数值最大的行的信息块被淘汰,新装行的块的计数器置为0,其余全加1
上面演示了部分步骤,剩下大家可以试着算一下
LRU算法--基于"局部性原理,近期被访问过得主存块,在不久的将来也很可能被再次访问,因此淘汰最久没被访问过得快是合理的.LRU算法的实际运行效果优秀,Cache命中率高.
最不经常使用算法--为每一个Cache块设置一个"计数器:"用于记录每个Cache块被访问过几次,当Cache满后替换"计数器"最小的
设总共有4个Cache快,初始整个Cache为空,采用全相联映射,依次访问主存块{1,2,3,4,1,2,5,1,2,3,4,5}
新调入的块计数器=0,之后每被访问一次计数器+1,需要替换时,选择计数器最小的一行
若有多个计数器最小的行,可按行号递增,或FIFO策略进行选择
LFU算法1--曾经被经常访问的主存块在未来不一定会用到(如;微信视频聊天相关的块)
并没有很好地遵循局部性原理,因此实际运行效果不如LRU
Cache写策略
写回法--当CPU对Cache写命中时,只修改Cache的内容,而不立即写入主存,只有当此块被换出时才写回主存,减少了访存次数,但存在数据不一致的隐患
增加一个脏位表示是否被修改过.
全写法--当CPU对Cache写命中时,必须把数据同时写入Cache和主存,一般使用写缓冲
访存次数增加,速度变慢,但更能保证数据一致性
使用写缓冲,CPU写的速度很快,若写操作不频繁,则效果很好,若写操作很频繁,可能会因为写缓冲饱和而发生阻塞
写分配法--当CPU对Cache写不命中时,把主存中的块调入Cache,在Cache中修改。通常搭配写回法使用
非写分配法--当CPU对Cache写不命中时只写入主存,不调入Cache,搭配全写法使用
现在计算机通常采用多级Cache,离CPU越近速度越快,容量越小;离CPU越远的速度越慢,容量越大;各级Cache间常采用"全写法+非全写分配法",Cache和主存间通常采用"写回法+写分配法"
页式存储器
假如一个微信有1GB大小,全部放入内存,并且需要连续存放,在很多时候会导致主存的利用率不高;为了让主存的利用率更高,就拿某个程序(4KB)来说,我们会把4KB的程序分为4个"页",每个页面的大小相同
页面存储系统:一个程序在(进程)在逻辑上被分为若干个大小相等的"页面","页面"大小与"块"的大小相同,每个页面可以离散地放入不同的主存块中.
虚地址VS实地址
逻辑地址(虚地址):程序员视角看到的地址
物理地址(实地址):实际在主存中的地址
逻辑页号->主存块号
地址变换过程
地址变换过程(增加TLB)
虚拟存储器
思考:打游戏时候的"Loading"界面背后是在干嘛?
--将游戏地图相关数据调入内存
页式虚拟存储器
有效位:当有效位为0说明程序还在辅存中,还没有被调入到主存;反之亦然
外存块号:可以找到每个页面在外存中存放的位置
访问位:页面替换算法;解决主存和辅存之间的替换
脏位:这个页面是否被修改过
段式虚拟存储器
按照功能模块拆分如:#0段是自己写的代码,#1段是库函数代码,#2是变量