Skip to content

2016年 408 计算机组成原理 第 15 题

计算机组成原理2016年选择题2分

题目

有如下 C 语言程序段:

c
for (k = 0; k < 1000; k++)
    a[k] = a[k] + 32;

若数组 a 以及变量 k 均为 int 型,int 型数据占 4B,数据 Cache 采用直接映射方式,数据区大小是 1KB,块大小是 16B,该程序段执行前 Cache 为空,则该程序段执行过程中,访问数组 a 的 Cache 的缺失率是( )。

错因

A

把"总访问次数"算大了 10 倍——例如把循环误读成 10000 次(看花眼把 1000 当 10000),缺失数仍按 250 算,得 250 / 20000 = 1.25%。或者把块大小当成 32B(一块 8 个 int),1000/8 = 125 次缺失,125 / (2×1000×5) ≈ 1.25%。本质都是某一参数的数量级出错。

B

把缺失次数少算了 5 倍——比如把块大小当作 80B(误把"块大小 16B"看成"16 字",1 字 = 4B 时变成 64B;或把 1KB 与 16B 关系搞混导致每块容纳 20 个 int),结果是 50 次缺失,50 / 2000 = 2.5%。属于对"块大小如何切数组"这一步的算式记错。

D

最常见的坑:忽略了 a[k] = a[k] + 32 每次循环对 a[k] 访问 2 次(先读再写),把总访问数当成 1000,得 250 / 1000 = 25%。题面中的赋值语句 = "右边读 + 左边写" 共 2 次访存,真要算 Cache 缺失率必须把分母算对。

总解析

第一步:算"一块装多少个 int"

块大小 16B,每个 int 占 4B → 一块装 个连续的 int。即 a[0..3] 在同一块、a[4..7] 在下一块……以此类推。

第二步:算总缺失次数(按访问数组 a 的元素来数)

数组共 1000 个 int,每 4 个一块 → 块。

直接映射 + 顺序遍历 + 块容量 (1KB / 16B = 64 块) 充足的前提下,每块只在访问其第一个元素时缺失一次

  • 访问 a[0] → miss(装入 a[0..3] 整块)→ 后续 a[1]/a[2]/a[3] 都 hit
  • 访问 a[4] → miss(装入 a[4..7])→ 后续 a[5]/a[6]/a[7] 都 hit
  • ……

总缺失数 = 250

第三步:算总访问次数(这是关键易错点)

a[k] = a[k] + 32 这一句:

  • 等号右边: a[k](1 次访问)
  • 等号左边: a[k](1 次访问)

每次循环对 a[k] 共 2 次 访问,循环 1000 次:

第四步:算缺失率

最终答案是 C(12.5%)

逐块访问示意(以前两块为例):

循环操作命中 / 缺失累计缺失数
k=0读 a[0]miss(装入 a[0..3])1
k=0写 a[0]hit1
k=1读 a[1]hit1
k=1写 a[1]hit1
k=2读 a[2]hit1
k=2写 a[2]hit1
k=3读 a[3]hit1
k=3写 a[3]hit1
k=4读 a[4]miss(装入 a[4..7])2
k=4写 a[4]hit2
............

每块 8 次访问中只有第 1 次 miss,缺失率 =

关键易错点

  1. "分母"是访问数,不是循环数:赋值语句 x = x + c 算 2 次访问。这条规则在所有 cache 题里通用。
  2. "分子"是块的入场缺失,不是元素数:直接映射 + 顺序访问 + cache 容量足够 → 每块只 miss 一次。
  3. 写入是否计为访问:是。无论 write-back 还是 write-through,对 cache 访问而言"写命中"也是一次成功访问。

最后更新:

🎬 可视化演示
加载中...

提示:可在可视化区直接操作播放、步进、修改参数