Transcript Cache实验讲解
实验:Cache Simulator Gu Rong [email protected] 2014/05/28 背景回顾 • 为什么我们需要cache(高速缓存器)? • 何为块,何为行,何为字? • 为便于cache和主存间交换信息,cache和主存空间都被划分成相 等的区域。主存中区域称为块(主存块),cache中存放一个主存 块的区域称为行或槽,它是cache和主存之间的信息交换单位。 CPU与Cache之间的数据交换是以字为单位的,而Cache与主存 之间的数据交换则是以块为单位的。一个块由若干个定长字组 成。 背景回顾 • 主存块和cache行之间有以下三种映射方式 • 直接映射。每个主存块映射到cache的固定行中。 • 全相联映射。每个主存块映射到cache的任意行中。 • 组相联映射。每个主存块映射到cache的固定组的任意行中。 • 替换算法 • • • • 先进先出算法(FIFO) 最近最少用算法(LRU) 最不经常用算法(LFU) 随机替换算法(Random) 实验一要求 • 配置参数 • 输入 s 0x1fffff50 1 l 0x1fffff58 1 • Cache大小 • Cache行大小 • 关联方式 • 替换策略 • 写策略° • 缺失损失* • 输出 • 总/读/写次数 • 平均/读/写命中率 • 总运行周期* 核心流程 • 配置参数决定各个步骤 获得主存地址 Cache大小、Cache行大小 关联方式 替换策略、写策略 计算主存块号 N 替换 Hit ? Y 更新 Cache 配置 → 基本结构 • Cache大小、Cache行大小 • Cache行数 = Cache大小 / Cache行大小 • 块大小 = Cache行大小 • 块内地址长度 = log2(Cache行大小) • 主存地址 → Cache 主存块号 • 主存块号 = 主存地址 / 块大小 主存地址 >> 块内地址长度 • 块内地址 = 主存地址 % 块大小 标记 数据 … … 块内地址 编码上的细节(1) • Cache中的标记(tag) • 以string(char[])的方式保存二进制 o(>_<)o • 二进制、十进制、十六进制间的转换 • 查找时字符串比较 • int(unsigned int、long) o(≧v≦)o • 十六进制转十进制(scanf(“%x”, n)) • 移位、模、位运算 关联方式 → hit or miss • 直接映射 标记 Cache行号 块内地址 • 需要:有效位valid[Cache行数],标记tag[Cache行数] • 目标标记 T = 主存块号 / Cache行数 • 目标行号 L = 主存块号 % Cache行数 • (valid[L] && tag[L] == T) → hit 关联方式 → hit or miss • 全相联映射 标记 块内地址 • 需要:有效位valid[Cache行数],标记tag[Cache行数] • 目标标记 T = 主存块号 • for(i = 0 to Cache行数-1) (valid[i] && tag[i] == T) → hit miss 关联方式 → hit or miss • 组相联映射 标记 Cache组号 块内地址 • 需要:有效位valid[Cache行数],标记tag[Cache行数], 组相联系数 S,Cache组数 G(G = Cache行数 / S) • 目标标记 T = 主存块号 / G • 目标组号 g = 主存块号 % G • for(i = g*S to (g+1)*S-1) (valid[i] && tag[i] == T) → hit miss 编码上的细节(2) • DM.cpp、FA.cpp、SA.cpp • 重复的代码、bug难调 • 映射函数区分DM、SA、FA • DM和FA是特殊的SA • 1-路组相联(直接映射)、∞-路组相联(全相联) • for(i = begin to end) (valid[i] && tag[i] == T) → hit miss 替换策略 • 替换策略只适用于全相联和组相联 • Random随机替换 • srand(seed)、srand((unsigned)time(NULL)) • 0~N-1的随机数:rand() % N • LRU最近最少用替换 • 每次访问时,被访问的那行计数清零,其他行加1 • 需要替换时,将计数最大的行换出 写策略 • 对实验结果毫无影响 • Write Through直写 • 什么事也没发生 • Write Back回写 • dirtyBits[Cache行数] • 当操作为“写”时对应的dirty bit置为1 编码上的细节(3) • 替换策略的作用范围 • 全相联:所有Cache行 • rand() % Cache行数 • for(i = 0 to Cache行数-1) • m-路组相联:某一组内 • rand() % m • for(i = 0 to m -1) 缺失损失* • 要求输出总运行周期 • = 指令执行周期 + 指令间隔 + 缺失损失 • 对于每条指令 • 指令执行周期 = 1 • 指令间隔(从文件读入) • 缺失损失 = hit: 0 miss: 100 设计 —— 流程图 计算标记、 组号 SA 计算主存块号 关联方式 访存地址 FA 计算标记 Hit or Miss 累加缺失损失 随机 替换策略 N 更新脏位 Y 回写 随机替换 LRU替换 Y Miss 计算标记、 行号 DM Hit 更新LRU计数 LRU LRU替换 N 结果 & 分析 • 指令数统计 gcc gzip mcf swim twolf 总数 515683 481044 727230 303193 482824 Load 318197 320441 5972 220668 351403 Store 197486 160603 721258 82525 131421 swim twolf • 256KB,8 Byte/行,直接映射 gcc gzip mcf 命中率 0.958347 0.667072 0.010379 0.934319 0.988443 总周期 3688164 17098654 72981908 3167602 2009027 结果 & 分析 • 64KB,32 Byte/行,4-路组相联,LRU 命中率 0.987636 0.668253 0.752378 0.978618 0.996578 总周期 2177764 17041854 19021508 1824502 1616227 • 64KB,32 Byte/行,4-路组相联,Random 命中率 0.987091 0.668253 0.752375 0.97779 0.996508 总周期 2205864 17041854 19021708 1849602 1619627 • 8KB,64 Byte/行,全相联,LRU 命中率 0.989703 0.668319 0.876024 0.986652 0.997067 总周期 2071164 17038654 10029608 1580902 1592627