COMPUTER ORGANIZATION · 组成原理 / 底层架构
计算机组成速查
CPU 指令执行与流水线冒险、Cache 映射与写策略、运算器溢出判断、中断与 DMA、总线带宽与接口速率、性能指标与 Amdahl 定律、性能问题的硬件视角——组成原理最常追问的 43 个核心考点一张表收齐,随查随用。
43条速查
7大主题
∞持续更新
📖 速查表
点击展开各小节
🖥️ CPU 与指令执行
| 名称 | 说明 | 要点 / 示例 |
|---|---|---|
| 冯诺依曼架构要点 | 存储程序思想:指令与数据同存于主存、按地址访问、顺序执行;五大部件:运算器、控制器、存储器、输入设备、输出设备 | 现代 CPU 演化为「以存储为中心」,指令与数据 Cache 分离(哈佛结构思想)必背 |
| 指令周期 | 取指 → 译码 → 执行(→ 访存/写回);PC 自动加「一条指令长度」指向下一条指令 | 取指阶段访存取的是指令,执行阶段访存取的是数据;指令周期由若干机器周期组成 |
| 指令流水线 | 把指令周期切成取指/译码/执行等阶段,各阶段并行处理不同指令;理想加速比 = 流水线级数 k | 流水线周期取决于最慢一级;实际加速受冒险与停顿限制,吞吐提升而非单条指令变快 |
| 结构冒险 | 多条指令同时争抢同一硬件资源(如同一周期既取指又取数访问存储器) | 解法:指令/数据 Cache 分离、资源加倍、流水线停顿一拍 易混淆 |
| 数据冒险 | 后一条指令依赖前一条尚未写回的结果,RAW(写后读)最常见 | 解法:转发/旁路(forwarding)把结果直送下一条指令、load-use 插入 1 拍停顿、编译器指令调度 |
| 控制冒险 | 分支指令改变 PC,后续预取的指令可能全部作废 | 解法:分支预测(静态/动态 + BTB 分支目标缓冲)、延迟槽;预测错误需冲刷流水线 面试高频 |
| 超标量与乱序执行 | 超标量:一个周期发射多条指令(多条流水线并行);乱序执行:按操作数就绪而非程序顺序调度(记分板/Tomasulo),对外仍按序提交 | 一句话:前端按序取指、中端乱序执行、后端按序(Reorder Buffer)提交,保证异常语义一致 |
🧊 Cache 与存储层次
三种映射方式按「能放哪、怎么找、硬件多贵」三问对比记忆;写策略先分清写命中 / 写不命中,再记两组典型配对。
| 名称 | 说明 | 要点 / 示例 |
|---|---|---|
| 存储层次量级 | 寄存器(<1ns)→ L1/L2/L3(SRAM,1~30ns)→ 主存(DRAM,约 100ns)→ SSD(约 100µs)→ 机械磁盘(约 10ms) | 越往上越快越贵越小;「每下一层速度差约百倍」是数量级记忆口径 必背 |
| 局部性原理 | 时间局部性:刚访问过的项很快被再次访问;空间局部性:被访问项的相邻地址将被访问 | Cache、预取、缓冲的根本依据;二维数组按行遍历比按列快即典型体现 |
| Cache 行与地址划分 | 主存地址划分为「标记 Tag + 组号 Index + 块内偏移 Offset」;Cache 与主存以块(行)为单位交换数据 | 行结构关键字段:有效位(valid)、脏位(dirty,写回法用)、替换算法位 |
| 直接映射 | 每个主存块只能映射到唯一的 Cache 行(块号 % Cache 行数) | 硬件最简单、命中判断最快;冲突率高,两个热点块交替访问会乒乓颠簸 |
| 组相联 | 主存块映射到固定组(块号 % 组数),组内任意一行可存放,命中时并行比较组内所有 Tag | 现代 CPU 主流方案(L1 常 8/16 路);路数是冲突率与硬件成本的折中 面试高频 |
| 全相联 | 主存块可放入任意 Cache 行,需全量并行比较 Tag(CAM 内容寻址存储器) | 命中率最高、硬件最贵,只适合小容量结构,如 TLB(页表缓存) |
| 写策略 | 写命中:写穿透(同时写 Cache 与主存,简单一致但慢)vs 写回(只写 Cache 置脏位,换出时才写主存);写不命中:写分配 vs 非写分配 | 典型配对:写回 + 写分配,写穿透 + 非写分配 易混淆 记配对关系 |
| MESI 缓存一致性 | 一句话:缓存行四状态 Modified(已改独占)/ Exclusive(独占干净)/ Shared(多副本一致)/ Invalid(失效),写共享行前先广播失效,保证多核视图一致 | 伪共享:不同核心反复互失效同一缓存行上的不同变量,按 64B 缓存行对齐或 padding 规避 实战技能 |
🔢 运算器与数据通路
| 名称 | 说明 | 要点 / 示例 |
|---|---|---|
| ALU 功能 | 算术运算(加减)、逻辑运算(与/或/非/异或)、移位;核心是加法器,减法用「加补码」实现 | 标志位:ZF 零标志、CF 进位/借位(无符号溢出)、OF 溢出(有符号溢出)、SF 符号标志 |
| 溢出判断(双符号位) | 补码统一加减法并让符号位参与运算;双符号位(变形补码)判溢出:两符号位不同即溢出,01 正溢出、10 负溢出 | 单符号位判别:同号相加结果异号 → 溢出;或最高数值位进位 XOR 符号位进位 面试高频 |
| 乘除实现 | 一句话:乘法用「移位 + 加法」多次迭代实现(Booth 算法支持补码直接相乘),除法用恢复余数法/加减交替法 | 硬件乘除器本质是移位寄存器 + ALU 循环迭代,所以乘除比加减慢得多 |
| 浮点运算要点 | 规格化表示 N = M × r^E(尾数 × 基^阶码);IEEE 754 单精度 1 符号 + 8 阶码 + 23 尾数,双精度 1 + 11 + 52,隐含首位 1 | 运算流程:对阶(小阶向大阶)→ 尾数运算 → 规格化 → 舍入 → 溢出判断 |
| 浮点精度 | 0.1 无法精确表示(二进制无限循环);比较浮点数用误差范围,金额计算用 BigDecimal/十进制 | 相加顺序影响结果;对阶时小数尾数右移丢失精度,「大数吃小数」 易混淆 |
🔔 中断与 DMA
| 名称 | 说明 | 要点 / 示例 |
|---|---|---|
| 中断处理流程 | 中断请求 → 中断判优 → 中断响应(关中断、保存断点 PC/PSW、引出服务程序入口)→ 执行服务程序 → 恢复现场 → 中断返回 | 保护现场 = 硬件保存断点 + 软件保存通用寄存器;单重中断处理期间保持关中断 必背 |
| 中断向量表 | 中断类型号 × 向量长度 = 向量地址,表中存放对应服务程序的入口地址;现代 x86 采用 IDT(中断描述符表) | 陷阱(trap)是有意触发的软中断,系统调用即经此机制陷入内核 |
| 中断嵌套 | 处理中断时允许更高优先级中断打断;需开中断且新中断优先级更高,返回时按栈序逐层恢复现场 | 屏蔽字可动态调整响应优先级;服务程序要短小,耗时逻辑交给下半部处理 |
| 轮询 vs 中断 vs DMA | 轮询:CPU 反复查设备状态,最浪费;中断:设备就绪才打断 CPU,适合低速小数据量;DMA:DMA 控制器直接在设备与内存间搬运数据 | DMA 一次传输结束才发一次中断,磁盘读写等高速块设备的标配 面试高频 |
| DMA 传输流程 | CPU 初始化 DMA 控制器(源/目的地址、长度、方向)→ DMA 向 CPU 申请总线周期窃取 → 逐字/块搬运 → 全部完成后发中断通知 CPU | 周期挪用(窃取)方式对 CPU 影响最小;数据通路不经过 CPU,可与 CPU 并行 |
🚌 总线与接口
| 名称 | 说明 | 要点 / 示例 |
|---|---|---|
| 总线分类 | 数据总线(双向,宽度决定一次传输的位数)、地址总线(单向,宽度 n 决定寻址空间 2^n)、控制总线(时序与应答命令) | 按层次分:片内总线、系统总线、通信总线;地址总线 32 位 → 4GB 寻址空间 |
| 总线带宽计算 | 带宽 = 工作频率 × 总线宽度(字节)× 每周期传输次数(DDR ×2、QDR ×4) | 例:32 位总线 100MHz 每周期 1 次 = 400MB/s;注意 B 与 b(字节/位)8 倍关系 易混淆 |
| 总线仲裁 | 集中式:链式查询(优先级固定、对故障敏感)、计数器定时查询、独立请求(速度最快、成本最高);分布式:自举式/竞争仲裁 | 链式查询离总线控制器越近优先级越高,设备摘除影响后续设备 |
| 常见接口速率对照 | USB 2.0 ≈ 480Mbps、USB 3.0 ≈ 5Gbps、SATA 3.0 ≈ 6Gbps(约 600MB/s)、PCIe 3.0 x1 ≈ 8GT/s(约 1GB/s)、NVMe 走 PCIe 4x 达 4GB/s 级 | 记数量级即可:SATA 接口百 MB/s 级 → NVMe GB/s 级,SSD 快慢的分水岭在接口协议 |
| IO 编址方式 | 统一编址(存储器映射 IO):设备端口当作内存地址访问,无需专用指令;独立编址:端口地址空间独立,需专用 IN/OUT 指令 | 统一编址可借用全部访存指令但挤占内存空间;独立编址译码简单、程序可读性差 |
📊 性能指标
计算题先写出「CPU 时间 = 指令数 × CPI × 时钟周期」这个万能公式再逐步代入;概念题重点记 Amdahl 定律的加速上限含义。
| 名称 | 说明 | 要点 / 示例 |
|---|---|---|
| CPU 时间公式 | CPU 时间 = 指令数 × CPI × 时钟周期;性能优化三变量:编译更少指令、降低 CPI、提高主频 | 组成原理性能计算题的万能公式 必背 |
| 主频与 CPI | 主频 = 1/时钟周期;CPI = 执行一条指令所需平均时钟周期数 = Σ(CPIi × 指令占比 Fi) | 主频高 ≠ 快:还要看 CPI 与指令数,不同架构指令功能强弱不同 |
| MIPS | 每秒百万条指令 = 主频 / (CPI × 10^6) | 只反映指令吞吐量;不同机器指令功能不同,MIPS 不能直接横向比较 易混淆 |
| 响应时间与吞吐率 | 响应时间(延迟):完成单个任务耗时,面向交互场景;吞吐率:单位时间完成的任务量,面向批处理场景 | 两者通常此消彼长;说性能提升必须先说清「以什么为代价换什么」 |
| Amdahl 定律 | 加速比 = 1 / ((1-p) + p/s),p 为可优化部分占比,s 为该部分加速倍数;受串行部分限制,加速上限 = 1/(1-p) | 串行占比 5% → 即使无限并行,整体上限也只有 20 倍 面试高频 |
| 基准测试注意 | 警惕厂商「峰值性能」与针对特定负载的调优;看真实业务负载(TPC-C/TPC-H 类)、多轮测试取分布、关注长尾 P99 而非仅均值 | 微基准与宏基准结合;预热与缓存/JIT 状态会显著影响结果 |
🧯 性能问题的硬件视角
很多软件性能问题的根子在硬件开销——知道时间花在哪一层,优化手段才不会打偏。
| 现象 | 硬件视角一句话 | 软件层优化手段 |
|---|---|---|
| cache miss | 数据不在 Cache,一次访存要多花约两个数量级的等待周期 | 顺序访问代替随机跳转;结构紧凑(数组替代链表、热点字段集中布局);热数据靠近处理位置 高频 |
| 伪共享 false sharing | 多个核心高频写的变量落进同一 64B 缓存行,MESI 反复互踢失效,多核吞吐骤降 | 按缓存行隔离:Java @Contended 或手工 padding,C/C++ alignas(64);计数器按线程分片再汇总 |
| NUMA 远端内存 | 跨 NUMA 节点访存延迟约为本地内存的 1.5~2 倍 | numactl / taskset 绑核绑节点、内存本地分配;大内存应用确认 numactl --interleave=all 等策略是否匹配 |
| TLB miss | 地址翻译穿透多级页表,一次映射要多次访存,随机大范围访存尤甚 | 大页(HugePage)减少映射项数量;大堆 JVM、Redis、数据库可评估开启,同时实测 THP 合并带来的停顿副作用 |
| 分支预测失败 | 预测错则冲刷流水线,一次损失十几个到几十个周期 | 让分支变规律(经典演示:先排序再按条件累加快数倍);热路径减少不可预测分支,用条件移动/查表改写 面试高频 |
| 内存屏障与一致性开销 | 多核同步靠广播失效消息与屏障等待,强同步指令会拖慢整条流水线 | 减少不必要的 volatile / 原子操作、缩小锁粒度;用 acquire/release 弱序语义替代全屏障;合并写、批量提交 |
| 磁盘 IO 等待 | 机械盘一次寻道毫秒级,比内存慢约十万倍,iowait 高说明 CPU 在等盘 | 顺序化 IO、提高 PageCache 命中率、异步 IO 批量下发;热点数据上 NVMe;先查慢 SQL 与刷盘策略再谈硬件升级 先查应用层 |