一句话:CPU大量用于数据搬运而非数值运算,用流水线和分支提高效率
【计算机组成原理】
Q:什么是CPU?
A:是执行指令、处理数据的器件,用于完成基本的逻辑和算术指令,现在增加了复杂功能(内存接口、外部设备接口),包含大量晶体管(上百亿)
Q:什么是指令?
A:包括算术、访存、控制。对于一个编译好的程序,最优化目标:CPI(每条指令所需时钟周期:cycles/instruction)× 时钟周期(seconds/cycle)。这两个指标彼此并不独立
桌面应用多为轻量级进程,少量线程,有大量分支和交互操作,需要大量的存储器访问,而真正用于数值运算的指令很少(大量用于搬运数据,于是CPU不是计算机,而是是吞吐机、存储机)
摩尔定律:芯片的集成密度每2年翻一翻,且成本下降一半。但目前硅基芯片达到物理极限(量子效应明显)
流水线 Pipeline
- 利用指令级并行,极大的减小时钟周期,同时增加一些延迟和芯片面积
- 带来处理具有依赖关系指令和分支处理的问题
- 流水线长度(流水线分级):级数多不一定能带来性能提升
旁路 Bypassing
- (开后门)处理具有依赖关系的指令
停滞 Stalls
分支 Branches
- 等待判断条件,要不要执行
分支预测 Branch Prediction
- 基于过去的分支记录,猜测下一条指令
- 现代预测器准确度大于90%。提升性能及能量效率,面积增加,可能会增加延迟(猜也需要时间)
分支断定 Another option: Predication
- 不使用分支预测器,用条件语句替换分支(所有分支都做)
- 在GPU中使用分支断定
提升 IPC
- 常规 IPC (instructions/cycle) 受限于 1 instruction / clock
- 超标量 (Superscalar) – 增加流水线宽度(类似于三头六臂,为了处理更多的数据)
- N倍资源使用,旁路网络N^2,需要更多的寄存器和存储器带宽(但三头六臂吃的饭也多了,需要的床也大了)
指令调度 Scheduling :
- 指令直接是否依赖
寄存器重命名 Register Renaming
- 替换寄存器,让指令可以并行执行
乱序执行 Out-of-Order(OoO) Execution
- 重排指令,获得最大的吞吐率:Fetch → Decode → Rename → Dispatch → Issue → Register-Read → Execute → Memory → Writeback → Commit (调节顺序,用更合理的顺序做事情)
- 重排缓冲区Reorder Buffer (ROB):记录所有执行中的指令状态
- 发射队列/调度器Issue Queue/Scheduler:选择下一条执行的指令
缓存 Caching
- 将数据放在尽可能接近的位置(手机放在口袋里,而不是放包里)
- 利用时间临近性(刚刚使用过的数据很可能会被再使用)和空间临近性(倾向于使用周围的临近的数据)
CPU内部的并行性
- 指令级并行 Instruction-Level (ILP) extraction :超标量Superscalar、乱序执行Out-of-order(OoO)
- 数据级并行 Data-Level Parallelism (DLP) :矢量计算Vectors (数据间没有相关性,可以同时运算)
- 线程级并行 Thread-Level Parallelism (TLP) :同步多线程Simultaneous Multithreading (SMT) 、多核 Multicore
锁、一致性、同一性 Locks,Coherence,Consistency
- 多线程读写同一块数据?加锁(我用完了再把锁给你,你来用)
- 谁的数据是正确的 (Coherence)? 缓存一致性协议
- 什么样的数据是正确的 (Consistency)?存储器同一性模型
现实的困境
- 能量墙: Power Wall(拿掉散热器片,芯片煎鸡蛋)
- 存储器墙:处理器的存储器带宽无法满足处理能力的提升
结论
- CPU 为串行程序优化
Pipelines, branch prediction, superscalar, OoO
Reduce execution time with high clock speeds and high utilization
- 缓慢的内存带宽(存储器带宽)将会是大问题
- 并行处理是方向