csapp-cachelab-notes

csapp-notes

Posted by X1ng on August 1, 2020

由于本周要结束csapp了,,还卡在cachelab,所以准备先放一放,以后有时间再继续做,把剩下的lab的笔记先写一下

cache

即高速缓存

当一条加载指令指示cpu从主存地址A中读取一个字时,它将地址A发送到高速缓存。如果高速缓存中正保存着A处那个字的副本,即存在主存块到高速缓存的映射,则立即将那个字发回cpu

映射方式

  • 把主存空间划分成大小相等的主存块(block),也就是上文的缓存块
  • cache中存放一个主存块的对应单位称为槽(slot)或行(line)或块(block)
  • 将主存块和cache按以下三种方式映射
    • 直接映射:每个主存块映射到cache的固定行(即组相联映射中每个组只有一个行)
    • 全相联映射:每个主存块映射到cache的任意行(即组相联映射中只有一个组,包含所有的行)
    • 组相联映射:每个主存块映射到cache固定组中的任意行

直接映射

假设一个主存分为2048个块,一个块512字节,主存大小 2048(块) * 512 (B/块) = 1024 (KB) = 2^20B

所以可以用20位二进制地址表示 7位标记,4位cache行号,9位块内地址

从主存第0块开始,相邻16块对应映射到cache的16行中,所以相邻的16块的标记相同,每往后16块,标记加一

若将每16块记作一个块群,标记和块群一一对应

特点:命中时间短,cache空间不能充分利用,命中率低

如对于0000001 0001 000001100B

第1块群 第1块 块内第12个单元 单位
0000001 0001 000001100 B

全相联映射

假设一个主存分为2048个块,一个块512字节,主存大小 2048(块) * 512 (B/块) = 1024 (KB) = 2^20B

所以可以用20位二进制地址表示 11位标记,9位块内地址(没有cache行号,因为可以任意映射)

需要11位的比较器比较标记位是否一致,开销大,成本高

特点:命中率高,时间快(同时比较),成本高,空间大(标记位长,比较器大)

如对于0000 0001 111 0 0000 1100B

第15主存块 块内第12个单元 单位
00000001111 000001100 B

组相联映射

若对于一个m=t+s+b位地址

标记 组索引 块偏移
t位 s位 b位

假设一个主存分为2048个块,一个块512字节,主存大小 2048(块) * 512 (B/块) = 1024 (KB) = 2^20B

所以可以用20位二进制地址表示 8位标记,3位组号,9位块内地址

从主存第0块开始,相邻8块对应映射到cache的8组中,所以相邻的8块的标记相同,每往后8块,标记加一

若将每16块记作一个组群,标记和组群一一对应

由于每个组都有几行(下图每组2行),所以可以同时存放不同组群中的块,通过标记位区分

如对于0000 0001 001 0 0000 1100B

第1组群 第1组 块内第12个单元 单位
00000001 001 000001100 B

特点:命中率高,时间快(同时比较),成本较低,空间小(标记位较短,比较器较小),要考虑替换算法

判断高速缓存中正保存着地址A处那个字的副本:

先从A的组索引位确定其映射应该在哪个组中,当且仅当这组中的某一行设置了有效位且该行的标记位与地址A中的标记位相匹配时,组中的这一行才包含这个字(缓存命中);若没有设置有效位或该行的标记位与地址A中的标记位不相匹配,即该行是无效的或者不是要找的缓存块,则cpu到主存请求包含 地址A处那个字 的缓存块,cpu需要等待——被请求的块到达,高速缓存将这个块存入到它的一个高速缓存行里,再从被存储的块中取出地址A处那个字返回给cpu

当该组的每行都不匹配的时候,则要考虑用组内哪一行替换包含 地址A处那个字 的缓存块

替换算法

先进先出算法(FIFO)

命中率不随组的增大而提高,不是一种好算法

最近最少用算法(LRU)

命中率随组的增大而提高

可以采用计数的方式记录最近最少用的行

写策略

两种情况:

一、写命中:要写的单元已经在cache中

​ 1.使用写缓存(write buffer,一个较小的FIFO队列),cpu同时将数据写到cache和write buffer中,存控(memory controller)将缓存内容写到主存中

​ 2.写回(write back),只写cache不写主存,将这段数据锁死,不让被访问,每行设置一个修改位(dirtybit-脏位),替换时一次写回

二、写不命中:要写的单元不在chache中

​ 1.把主存块装入cache,然后更新相应单元

​ 2.直接写主存单元

多cache

同时使用 L1 cache和L2cache ,甚至有L3 cache ,L1 cache更靠近cpu,速度比L2快,容量比L2小

分立:指数据和指令分开存放在各自的数据和指令cache中

联合:指数据和指令都放在一个cache中

一般L1 cache都是分立的(流水,让多条指令并行),命中时间比命中率更重要(未命中还能访问相对慢一点的的L2 cache)

一般L2 cache都是联合的(空间利用率高),命中率比命中时间更重要(不命中则要访问主存)