第一章: 机器架构和 Rust 基础
本章主要介绍全书的前置基础知识, 且由于本书着重讲 Rust 中的并发/并行编程, 因此需要首先从比较高的层面上理解现代计算机硬件, 即 CPU 是如何工作的, 内存和 CPU 是如何沟通的, 这样才能理解计算机是如何让多个工作同时进行. 此外, 本章还会讲 Rust 的基础知识以及如何通过 Rust 生成 X86 和 ARM 的可执行程序.
本章概览:
- 讨论计算机 CPU 操作时候的高层抽象模型
- 讨论计算机 内存 的高层抽象模型
- Rust 的内存模型
- 通过 Rust 生成 X86 和 ARM 架构支持的可执行文件
- 如何 Debug Rust 程序
计算机硬件
讨论并发和并行时, 总会首先讨论硬件的原因在于: 有两种并行处理模型, 一种是 并发内存操作 以及 并行数据处理. 由于大部分时间我们都在处理和内存相关的并发问题, 因此需要对硬件有一个抽象的理解.
两种处理模型的含义:
- 并发内存操作: 即多个线程或称有多个 CPU 核心在并行地操作一块共享的可编址内存区域.
- 并行数据处理: 即 CPU 能够在同一时间对多个数据字(word)上执行一条或多条指令.
书中大 部分时间都会关注第一种模型.
使用 Rust, 我们可以很轻松地编写上述两种模型对应的代码(通过标准库或三方库), 否则我们只能自己手写这些特殊的汇编指令.
本书主要关注如下两种机器架构:
- X86
- Arm
两种架构的 PRAM 文法是类似的.
CPU
CPU 的作用是解释并执行指令, 通过指令操作存储结构中的三级(寄存器 Register, 高速缓存 Cache, 内存 Memory)存储, 以及操作和它连接的其它设备(比如通过 PCI-E 总线和 CPU 直接相连的 SSD 外存).
CPU 最简化的抽象模型: 是从某个存储位置取指令 -> 解释指令 -> 执行指令 -> 取下一条指令再往复进行的一种装置. CPU 内通过一种震荡时钟保持这样的步调运行, 且所有的指令都会花费预定的震荡脉冲个数或称一个或多个时钟周期来完成执行. 在某些 CPU 模型上, 任意指令花费的时钟周期都是相同的, 但另外一些 CPU 上, 不同指令花费的时钟周期是不同的.
现代 CPU 的两个主要特性:
- 乱序执行: 只要不会影响到程序的运行行为, CPU 可以无需等待需要读取数据的指令完成数据获取, 先执行另外的指令. 这样的优化可以显著提升程序性能.
- 分支预测: 即 CPU 可以提前执行分支的一侧而无需等待结果判断, 这样可以加速程序运行, 如果发现被执行的一侧是错误的, 则重新执行另一侧.
另外现代 CPU 为了节能, 也有很多的优化:
- 动态调节时钟周期(震荡脉冲)间隔时间: 这样在固定时间段内就会少执行一些指令以降低功耗, 降低热量
- 动态关闭核心
总地来说, 由于 CPU 的优化和节能特性, 程序的运行并非每次都是一样性能的.
分级存储结构: 寄存器, 高速缓存和内存
现代计算机结构中, 通过总线将 CPU 和内存相连. 由于内存支持随机访问, 意味着访问第 0 个字节耗时和访问第 1000 个字节耗时相同.
X86 平台上, 内存访问时的读或写可以抽象为一系列顺序执行的操作, 除了每个线程都会维护一个 FIFO 缓存, 在它们提交时批量写入内存.