1. 实验概述与核心目标
这个Cache实验是计算机组成原理课程中的经典实践环节,通过SPIM-CACHE模拟器来验证和理解计算机体系结构中Cache的工作原理。实验不需要自行编写复杂程序,重点在于通过调整Cache参数观察程序运行时的命中率变化,从而深入理解Cache的三大核心特性:映射规则、局部性原理和替换算法。
实验使用的SPIM-CACHE是在标准MIPS模拟器基础上扩展的版本,增加了Cache可视化功能。它能实时显示指令和数据访问过程中Cache的命中/缺失情况,是学习Cache机制的理想工具。实验涉及的三组代码(Fig.4/7/8)分别针对不同的Cache特性设计,通过有规律的访存模式来凸显特定原理。
关键提示:实验成功的前提是正确设置PC起始地址为0x400000,这是许多同学容易忽略的关键步骤。未正确设置会导致程序无法正常运行或数据异常。
2. 实验环境准备与基础配置
2.1 SPIM-CACHE安装与启动
虽然实验指导中已提供软件包,但需要注意不同操作系统下的配置差异:
- Windows用户直接运行spim-cache.exe即可
- macOS/Linux用户可能需要通过终端运行,命令格式为:
./spim -cache -file 程序名.s
首次启动时应检查以下界面元素是否正常显示:
- 寄存器窗口(包含PC值显示)
- 内存查看窗口
- Cache统计面板(含命中率数据)
- 代码执行控制按钮(特别是单步执行功能)
2.2 实验代码结构解析
老师提供的三个程序具有相似的基础结构:
assembly复制.data
array: .space 400 # 测试用数组
.text
.globl _start
_start:
# 初始化代码
# 主要测试逻辑
# 结束处理
特别需要注意:
- 所有测试代码都从_start标签开始执行
- 数组访问模式决定了Cache行为特征
- 循环结构的设计直接影响时间局部性表现
2.3 Cache参数配置方法
通过模拟器的"Cache Configuration"菜单可以设置关键参数:
- Cache总大小(建议固定为256B以保持对比一致性)
- 块大小(Block Size,实验中的主要变量)
- 映射方式(直接映射/组相联)
- 替换算法(LRU/FIFO/Random)
操作技巧:修改配置后务必点击"Reset"按钮使设置生效,否则可能继续使用之前的Cache状态。
3. 映射规则实验(Fig.4代码)
3.1 实验设计与参数选择
这个实验通过改变块大小观察命中率变化,验证空间局部性原理。建议采用对照实验法:
| 实验组 | Cache大小 | 块大小 | 映射方式 |
|---|---|---|---|
| 组1 | 256B | 16B | 直接映射 |
| 组2 | 256B | 8B | 2路组相联 |
| 组3 | 256B | 4B | 4路组相联 |
注意保持其他变量一致,仅改变目标参数才能得到有效对比数据。
3.2 操作步骤详解
- 加载Fig.4代码文件(通常命名为cache_mapping.s)
- 设置PC=0x400000(绝对必要步骤)
- 按顺序配置三组参数
- 每种配置下:
- 点击"Reset"初始化状态
- 使用F11连续执行直到程序结束
- 记录数据Cache和指令Cache的命中率
- 重复3次取平均值减少误差
3.3 数据记录与典型结果
以下是预期可能得到的实验数据:
| 块大小 | 映射方式 | 命中率(D-Cache) | 命中率(I-Cache) |
|---|---|---|---|
| 16B | 直接映射 | 72.3% | 85.6% |
| 8B | 2路组相联 | 68.5% | 83.2% |
| 4B | 4路组相联 | 65.1% | 81.7% |
3.4 原理分析与报告要点
在实验报告中需要阐述的关键点:
- 块大小影响:较大块能利用空间局部性,一次性加载更多相邻数据,减少后续访问缺失
- 映射方式对比:组相联增加映射灵活性,减少冲突缺失,但需要更复杂的硬件实现
- 指令vs数据:通常指令Cache命中率更高,因为程序流具有更好的空间局部性
常见误区警示:
- 不要混淆块大小和Cache总大小的概念
- 直接映射并非总是最差选择,它具有实现简单的优势
- 命中率不是唯一评价指标,还需考虑访问延迟等因素
4. 局部性实验(Fig.7代码)
4.1 实验设计思路
通过改变外循环次数N,观察时间局部性对命中率的影响。固定Cache配置(建议256B,直接映射),仅改变N值:
N取值:1, 5, 10, 100
4.2 关键操作步骤
- 加载temporal_locality.s文件
- 修改源代码中的N值定义:
assembly复制li $t0, 10 # 将立即数改为需要的N值
- 每种N值下:
- 重置模拟器
- 完整执行程序
- 记录D-Cache命中率
- 特别注意内循环次数保持恒定
4.3 预期实验数据
典型实验结果示例:
| N值 | 命中率变化 |
|---|---|
| 1 | 65.2% |
| 5 | 78.4% |
| 10 | 85.7% |
| 100 | 92.3% |
4.4 深度原理解析
- 时间局部性:多次访问相同数据时,后续访问可以直接从Cache获取
- 访问频度:N增大意味着热点数据被重复利用的次数增加
- Cache容量效应:当工作集超过Cache容量时,命中率会突然下降(本实验未触及)
实验技巧:可以尝试极端情况(如N=1000)观察命中率是否趋于稳定,验证Cache的容纳极限。
5. 替换算法实验(Fig.8代码)
5.1 多变量实验设计
这个实验需要同时考虑两个变量:
- 访问步长(stride):1, 2, 4, 8, 16, 32, 64
- Cache配置:
- 直接映射
- 2路组相联+LRU
- 4路组相联+LRU
- 4路组相联+FIFO
5.2 详细操作流程
- 修改stride参数:
assembly复制lw $t1, array($t2) # 通过改变$t2的增量调整stride
- 对每种Cache配置:
- 设置相应参数
- 遍历所有stride值
- 记录命中率数据
- 特别注意保持外循环次数=100
5.3 数据记录表格示例
| Stride | 直接映射 | 2路LRU | 4路LRU | 4路FIFO |
|---|---|---|---|---|
| 1 | 85% | 88% | 90% | 87% |
| 8 | 60% | 75% | 82% | 78% |
| 64 | 30% | 55% | 65% | 60% |
5.4 替换算法对比分析
- LRU优势:能有效识别并保留最近最常使用的数据
- FIFO缺陷:可能替换掉仍有使用价值的数据(Belady现象)
- 步长影响:大stride导致空间局部性下降,所有算法命中率降低
- 相联度提升:更多路数提供更大灵活性,缓解冲突缺失
实验陷阱警示:
- 确保每次修改stride后重新初始化数组访问指针
- 不同替换算法可能需要不同的预热周期
- 极小的stride可能导致所有算法表现相似,难以区分优劣
6. 实验报告撰写指南
6.1 报告结构建议
-
引言(100字)
- 实验目的与意义
- 使用工具简介
-
实验环境(150字)
- SPIM-CACHE版本
- 测试平台配置
- 基础参数设置
-
实验内容(分三个子章节)
- 每个实验的数据表格
- 结果曲线图(建议用Excel绘制)
- 现象描述
-
分析讨论(重点部分)
- 数据反映的规律
- 与理论预期的对比
- 异常现象解释
-
结论(80字)
- 验证的原理
- 获得的启示
6.2 图表制作技巧
- 使用三线表呈现数据:
code复制| 参数 | 值1 | 值2 | 值3 |
|-------------|-----|-----|-----|
| 命中率(%) | 85 | 78 | 65 |
- 折线图建议:
- X轴:自变量(如块大小、N值、stride)
- Y轴:命中率
- 不同曲线代表不同配置
6.3 常见扣分点警示
- 数据与分析脱节(仅罗列数据不做解释)
- 混淆不同实验的现象和原理
- 缺乏对照实验意识(变量控制不当)
- 未注明实验条件的局限性
- 直接复制指导书内容缺乏个人分析
7. 高级技巧与扩展探索
7.1 精确测量方法
- 使用脚本自动化:
python复制# 伪代码示例
for blocksize in [4,8,16]:
set_cache_config(blocksize)
run_program()
record_hit_rate()
- 统计显著性分析:
- 计算标准差
- 剔除异常值
- 多次测量取平均
7.2 超越实验要求的探索
- 混合工作负载测试:
- 同时运行多个测试程序
- 观察Cache共享情况
- 预取效果验证:
- 对比有无预取机制的差异
- 分析预取算法优劣
- 多级Cache模拟:
- 配置L1/L2 Cache层次
- 研究层次结构的影响
7.3 实际系统关联分析
- 现代CPU中的Cache实现:
- Intel/AMD的实际Cache结构
- ARM处理器的差异
- 编程优化启示:
- 数据结构对齐
- 循环分块技术
- 访存模式优化
经过这个系统的实验过程,你不仅能够完成课程要求,更能建立起对计算机存储体系的直观认识。当你在实际编程中遇到性能问题时,这些关于Cache的知识将成为你分析和优化程序的重要工具。记住,理解原理只是第一步,真正的掌握来自于在多样化的场景中应用这些知识解决问题。