计算机体系结构 09:五级流水线
五级流水线:不同指令怎样在同一拍推进 多周期处理器在一条指令完成以后才取下一条。若一条指令正在访问数据存储器,取指和运算部件可能空闲。流水线把不同指令分配到不同阶段,在同一拍分别完成工作;阶段之间的寄存器保存每条指令自己的数据与控制信息。 中心问题是:同时存在多条尚未完成的指令时,怎样既增加完成速率,又保持程序规定的结果?本篇先研究没有依赖和分支的短程序,再用累计求和程序检查结果。证据等级是“教学时序模型”;周期长度的例子另标为“手算”。数据冒险的具体修复在第 10 篇,错误路径恢复在第 11 篇。 阶段寄存器保存的是一条指令的执行上下文 五级分别是 IF 取指、ID 译码与读寄存器、EX 运算或算地址、MEM 数据访存、WB 写回。每拍结束,阶段寄存器把本拍产出的信息交给下一阶段。即使某条 ALU 指令不访问内存,它仍穿过本模型的 MEM 位置,避免和较早的 load 争抢写回位置。 CS61C 流水线总结强调,阶段寄存器有时需要携带下下级才使用的信息。例如目标寄存器 rd 在 WB 才真正参与写回;不能到了 WB 再从当前 IF 的指令字提取 rd,那时正在取的已经是另一条指...
计算机体系结构 10:数据与结构冒险
数据与结构冒险:为什么正确的指令会读到错误的值 下面四条指令顺序执行时,x2 应为 14,x3 应为 21,地址 160 最后保存 21。把它们直接放进五级流水线,若没有前递和互锁,第二条却可能用初始的 x1=0 算出 x2=0。 1234addi x1, x0, 7add x2, x1, x1add x3, x2, x1sw x3, 160(x0) 中心问题是:一个源寄存器在当前拍应从哪里获得数值,又在什么时候必须等待?本篇在第 09 篇的执行器中故意关闭保护,保存真实错误输出,再用前递与停顿恢复正确行为。全部周期与数据均属于“教学时序模型”,没有使用真机 PMU 或 gem5。 RAW 依赖需要确定最新的生产者 RAW 指先写后读的真实数据依赖。第一条 addi 在第三拍 EX 已经计算出 7,但要第五拍 WB 才写入 x1。第二条 add 在第三拍 ID 读 x1,读到的仍是旧值。它在第四拍 EX 使用这个旧值,就会产生错误结果。 CS61C 数据冒险材料分别讨论了停顿、同拍先写后读寄存器堆,以及向 EX 前递的路径。本模型采用 WB 先写、ID 后读的约定:距离较...
计算机体系结构 11:分支预测与恢复
分支预测与恢复:猜错以后怎样取消副作用 五级流水线在 EX 才比较分支操作数。此时 IF 和 ID 已经处理了更年轻的指令。若取指必须一直等到比较完成,取指速率会下降;预测允许先选择一个后继地址,但必须能够撤销错误路径上的操作。 中心问题包含两个部分:怎样给出预测,以及预测错误时哪些状态必须恢复。本篇使用静态不跳转和标准两位饱和计数器,对固定结果序列计算误预测次数,再执行带错误路径 store 的 .hex。证据等级为“手算”和“教学时序模型”;没有测量真实芯片的分支预测率,也不声称复现某款商业预测器。 方向与目标是两份不同的信息 预测方向回答是否跳转,预测目标回答跳到哪里。知道“会跳转”但不知道目标 PC,仍然不能从正确位置取指。直接条件分支的目标可以从指令 PC 与立即数算出;间接跳转需要的目标则可能来自寄存器或内存中的运行时值。 本模型只支持 beq/bne/blt/bge,IF 取得指令字后就解码 B-immediate,以原始分支 PC 加偏移得到候选目标。预测为不跳转时选择 PC+4。这样无需建立 BTB,就能单独观察方向预测;它没有模拟实际前端得到指令字、识别分支和...
计算机体系结构 12:重命名与乱序执行窗口
重命名与乱序执行窗口 一条长延迟指令尚未完成时,后面的独立指令能否先执行?第 09–11 篇的顺序流水线通过前递、停顿和分支恢复保持正确,但遇到队首等待时,后面的就绪操作仍可能受阻。乱序执行把“按程序顺序进入机器”和“按操作数就绪情况开始计算”分开。寄存器重命名进一步区分不同指令产生的同名寄存器值,使多个版本可以同时存在。 本篇的核心问题是:哪些依赖必须等待,哪些只是寄存器名字重复造成的限制;消除后者以后,加宽发射是否就能缩短执行时间?核心案例只有六条算术操作,支持逐项手算和 Python 事件模型复跑。证据等级为教学时序模型,关键路径另有手算核对。它没有取指、缓存、分支、提交或操作系统,因此六周期的结果不能称为一台完整 CPU 的运行时间。 实验目录为 examples/computer-architecture/ooo/。完整轨迹见 rename.json.txt,独立可运行附件见 rename_model.py.txt。模型的算术语法是题设,不是新增的 RISC-V 指令。 同名寄存器可以表示不同版本的值 设初始架构寄存器满足 ri=i。程序按表中 A 到 F 的顺序执行;...
计算机体系结构 13:ROB 与精确异常
ROB 与精确异常 重命名允许年轻指令提前计算,也允许多个尚未提交的寄存器版本同时存在。程序仍需要一种可解释的异常状态:若某条指令失败,异常处理程序看到的状态应对应顺序执行到该指令之前,而不能是几条年轻指令已经生效、几条较老指令尚未完成的混合结果。 本篇的核心问题是:执行顺序被打乱以后,怎样让异常边界仍然对应一段完整的程序前缀?案例在长延迟操作之后注入异常,并让更年轻的 store 最先完成。验收同时检查寄存器和内存,尤其检查提前完成的 store 没有污染架构状态。 证据等级为教学时序模型。四个条目的完成时刻是题设;模型运行后产生完成、提交和异常事件。它没有真实访存延迟、页表、RISC-V 陷阱 CSR 或异常处理程序。原始记录见 rob.json.txt,可独立执行的附件见 rob_model.py.txt。 架构状态需要对应一个程序前缀 设程序顺序为 A、B、C、D。A 需要很久,B 最终报告异常,C 是写内存的操作,D 写寄存器。异常处理时允许 A 已生效,不允许 B 自己的正常结果、C 的 store 或 D 的寄存器写入生效。 “精确”描述的是这个边界。它不表示异常一...
计算机体系结构 14:LSQ 与内存依赖重放
LSQ 与内存依赖重放 寄存器重命名可以在译码附近确定每个源值对应的生产者,内存访问更难:两条不同形式的地址表达式可能在运行时指向同一位置。年轻 load 若绕过了一个尚未算出地址的较老 store,可能读到旧值;即使它所读的缓存行已经命中,程序结果仍然会错。 本篇的核心问题是:store 的数据先准备好、地址稍后才确定时,load 应等待,还是可以先推测执行?核心案例比较两种策略,要求最终结果与同一个顺序程序一致。例子还包含两个较老 store,避免把“找到一个同地址写”误当成“找到正确的写”。 证据等级为教学时序模型。实验限定单线程、四字节、自然对齐访问,没有缓存、地址翻译、多核、原子操作或部分字节重叠。实际事件见 lsq.json.txt,独立可执行模型见 lsq_model.py.txt。 store 有地址和数据两组依赖 一条 sw rs2,offset(rs1) 需要从 rs1 计算有效地址,也需要 rs2 提供待写数据。这两项可能分别依赖不同的较老指令。知道“要写 22”并不能确定应该阻塞哪一个 load;知道“要写地址 128”但数据仍未产生,则已经足以判断某个 ...
计算机体系结构 15:仿真结果怎样可信
仿真结果怎样可信 一个模型输出“程序结果为 25,耗时 100 周期”,包含两类不同的断言。结果为 25 需要检查指令语义;100 周期需要检查阶段、端口、队列和延迟假设。即使两者都符合模型定义,仍不能直接推出某台真实处理器也会耗时 100 周期。 本篇的核心问题是:怎样把功能正确、模型内部一致和硬件拟合分开验收?已执行的核心案例是同一批 RV32I 程序的独立解释器差分,并通过故意破坏 x0 规则验证检查器确实能发现错误。统计口径另用第 13 篇事件记录手算。gem5 部分提供指定版本的待运行配置,状态为 NOT_RUN,没有本系列的 gem5 仿真结果。 实验目录为 examples/computer-architecture/ooo/。可下载 差分结果、统计口径记录、运行环境 和 Python 功能解释器。这些文件对应功能执行或手算证据,不是硬件测量。 三个验证问题分别需要什么证据 功能验证关心给定输入是否产生规定的架构状态变化。对第 07 篇的有限执行器,可以逐条比较 PC、目标寄存器和值、内存地址和值、分支方向,以及正常结束或拒绝原因。 时序验证关心程序在声明的资源和事...
总统制、内阁制与半总统制:历史沿革、权力分立与各国实践
美国总统不能因为不喜欢国会就解散国会,英国首相却可能通过提前大选重新争取议会支持。法国总统可以解散国民议会,但一个得到议会多数支持的总理,并不因此成为总统能够随意撤换的下属。韩国也有总理,却不因此属于半总统制。日本让国会议员出任首相和大臣,同时又在宪法中规定司法独立与违宪审查。 这些差异需要同时从两个方向理解:政府凭什么成立、怎样下台,以及国家权力受到什么限制。总统制、内阁制和半总统制,主要回答第一个方向;权力分立、议会主权、司法独立和民主集中制,则涉及第二个方向中的不同问题。 内阁制不等于没有权力分立,总统制也不等于三个机关互不联系。 把制度理解为三个彼此隔绝的部门,既解释不了美国总统的否决权,也解释不了英国法院为什么能够判政府违法。 本文以截至 2026 年 9 月检索到的宪法、基本法、议会说明与比较政治研究为依据。历史案例标明发生时期;国家比较以中央层级为准。香港、澳门是中国特别行政区,另列制度层级和中央权限;台湾地区按其实际运行的制度与现行规范分析。比较表不讨论主权承认问题,也不把制度名称直接当作民主程度的排名。 判断政体,先看政府如何产生和存续 国家元首与政府首脑不是...
从零构建现代搜索引擎(E05):磁盘 ANN 与引擎工程对照
主线第 19 篇把向量全部加载到内存中的 HNSW 图里。100 篇文档、512 维 float32,总共 200 KB——任何机器都装得下。但如果语料从 100 篇增长到 100 万篇,200 KB 变成 2 GB;到 1 亿篇,就是 200 GB。常规服务器的内存通常在 64-256 GB 之间,向量数据已经不够放了。 这是向量检索的内存墙问题。解法有三个方向:量化压缩(第 22 篇)、分片分散(第 26 篇)、把向量放到磁盘上。本篇讨论第三个方向——磁盘 ANN,以及在什么规模下应该考虑从 Lucene 切换到专用向量引擎。 内存墙 向量数据的内存占用计算: 123456789内存 = 文档数 × 向量维度 × 每维字节数512d float32: 1K 文档: 2 MB 100K 文档: 200 MB 1M 文档: 2 GB 10M 文档: 20 GB 100M 文档: 200 GB 1B 文档: 2 TB int8 量化(第 22 篇)把每维从 4 字节降到 1 字节,内存降到 1/4。但 1 亿篇文档量化后仍需 50 GB,加上 HNSW ...
从零构建现代搜索引擎(E04):有界多步搜索与引用答案
用户搜"Java 虚拟线程和平台线程的性能差异",搜索引擎返回 10 篇文档链接。用户点开第一篇,发现只讲了虚拟线程的概念;点开第二篇,有性能数据但对比的是 Go 协程;翻到第五篇才找到需要的对比数据。 这个场景暴露了传统检索的局限:搜索引擎只负责找文档,把"从多篇文档中提取、整合、回答问题"的工作留给了用户。RAG(Retrieval-Augmented Generation)把这最后一步自动化——检索文档后用语言模型生成带引用的答案。 但 RAG 不是无限制的。模型可能幻觉,检索可能失败,生成可能超时。有界多步搜索在 RAG 之上加入资源预算:限定最大检索轮次、总耗时和 token 消耗,在可控成本内给出最佳答案。 单次检索的失败模式 主线 30 篇建立的搜索管线是单次检索:query → BM25 + 向量 → 融合 → 重排 → Top-K。这条管线在以下场景失败: 模糊 query:用户搜"那个 Java 的东西"——query 信息量太低,召回的文档分散在多个无关主题上。 多跳问题:回答需要综合多篇文档的信...










