Lec 20向量计算机(Vector Computers)
Lec 20 向量计算机(Vector Computers)
MIT 6.5900 Fall 2024 · Joel Emer 主题:超级计算机、向量处理器(Vector Processor)、多媒体 SIMD 扩展
TL;DR
- 向量体系结构精髓:通过单条短指令编码包含数十甚至数百个独立元素的操作,在指令级极大压缩取指与译码带宽,直接规避标量超标量处理器的复杂发射队列与重命名开销。
- 访存与硬件交错:向量处理高度依赖分体内存(Memory Banking)与流水化访存通道,结合步长(Stride)与分散/聚集(Scatter/Gather)机制高效支持稀疏与多维数据并行。
- 向量链与演进:通过流水线链接(Chaining)允许后继向量指令在操作数生成阶段直接重叠执行;现代通用处理器的多媒体与 SIMD 扩展逐步吸收完整向量机制以提升能效比。
一、超级计算机(Supercomputer)
对超级计算机的几种"定义"(半开玩笑):
- 在给定任务上世界上最快的机器;
- 一种把计算受限(compute-bound)问题转化为 I/O 受限(I/O-bound)问题的设备;
- 任何造价 $30M 以上的机器;
- 任何由 Seymour Cray 设计的机器。
第一台被公认的超级计算机是 CDC 6600(Cray,1964)。
典型应用领域:军事研究(核武器、密码学)、科学研究、天气预报、石油勘探、工业设计(汽车碰撞仿真)、生物信息学。这些任务的共同点是:对大数据集做巨量计算。
在 70—80 年代,"超级计算机"几乎等价于"向量机"(Supercomputer ≡ Vector Machine)。
二、为什么需要向量
考虑一段简单循环:
for (i = 0; i < N; i++)
B[i] = A[i] + C;
在标量处理器上做循环展开(loop unrolling)后,需要靠编译器精细地调度各个功能单元(整数单元、访存单元、浮点加法/乘法单元)来填满流水线。这种做法的本质问题是:每条指令携带的工作量太小,取指带宽和调度复杂度都成了瓶颈。
向量 ISA 的核心思想:用一条短指令编码 N 个操作。
三、Cray-1(1976):向量超级计算机的范本
Cray-1 的体系结构特征:
-
标量单元:采用 Load/Store 架构;
-
向量扩展
:
- 向量寄存器(Vector Registers);
- 向量指令(Vector Instructions);
-
实现特征
:
- 硬连线控制(Hardwired Control);
- 高度流水化的功能单元;
- 没有数据 Cache;
- 交错式存储系统(Interleaved Memory System);
- 没有虚拟内存。
关键参数:处理器周期 ();8 个向量寄存器 ,每个 64 个元素;存储体(memory bank)周期 ;16 个 64-bit 字的存储体 + 8-bit SECDED 纠错。
四、向量编程模型(Vector Programming Model)
寄存器组织:
- 标量寄存器 ;
- 向量寄存器 ,每个含
VLRMAX个元素; - 向量长度寄存器(Vector Length Register,
VLR):指定本次操作实际处理的元素个数。
向量算术指令,例如:
ADDV v3, v1, v2 # v3[i] = v1[i] + v2[i], i = 0 .. VLR-1
向量访存指令(带基址与步长):
LV v1, r1, r2 # 基址 = r1, 步长(Stride) = r2
编译器自动向量化(Compiler-based Vectorization)
编译器通过循环依赖分析(loop dependence analysis)识别相互独立的操作,把标量代码转换为向量代码:
for (i = 0; i < N; i++)
C[i] = A[i] + B[i];
向量代码示例
标量处理器处理数组循环时,必须在每次迭代中显式维护循环记账开销:包括计数器递减、数据指针步进以及条件分支判定。而在向量体系结构中,整个循环被折叠为由向量长度寄存器控制的紧凑指令流。
标量代码 vs 向量代码,处理 64 个双精度浮点元素:
# 标量代码(标量循环展开前) # 向量代码(显式数据并行)
LI x14, 64 LI vlr, 64
loop: LV v1, x11
FLD f0, 0(x11) LV v2, x12
FLD f2, 0(x12) ADDV.D v3, v1, v2
FADD.D f4, f2, f0 SV v3, x13
FSD f4, 0(x13)
ADDI x11, 8
ADDI x12, 8
ADDI x13, 8
ADDI x14, -1
BNEZ x14, loop
开销剖析与机制对比:
- 指令吞吐与动态开销:标量版本总计需要执行 条动态指令,循环控制与指针步进指令(
ADDI与BNEZ)占据了过半的执行频次,对分支预测器和重命名寄存器造成极大压力;向量版本仅需 5 条指令即完成了全部 64 个元素的计算与内存回写。 - 控制逻辑与硬件解耦:标量循环必须由前端逐周期取指并依靠流水线重命名和分支预测维持在飞指令;向量版本设置
LI vlr, 64后,执行逻辑完全由底层向量通道(Lanes)以流水线方式自主排空,免除了循环展开、分支误预测与动态调度的大量硬件记账。
五、向量 ISA 的属性与硬件含义
ISA 属性:
-
紧凑(Compact):一条短指令编码 N 个操作(外加少量记账信息);
-
富表达力
(
Expressive
):向量指令告诉硬件这 N 个操作满足:
- 彼此独立;
- 使用同一功能单元;
- 访问向量寄存器中互不相交的元素;
- 访问寄存器的模式与前序指令一致;
- 访问连续的内存块(单位步长 load/store,unit-stride);
- 或以已知模式访问内存(带步长 load/store,strided)。
对硬件的含义:
| ISA 属性 | 硬件收益 |
|---|---|
| 每条指令工作量大 | 降低取指带宽需求,简化取指设计 |
| 向量内部无数据依赖 | 适合深度流水/并行设计(无冒险) |
| 向量元素访问互不相交 | 用分体(banked)寄存器文件代替多端口 |
| 已知规则的访存模式 | 用分体存储器获得更高带宽 |
六、向量执行机制
1. 向量算术执行
使用深流水线(→ 更快时钟)来逐元素执行。由于向量内各元素相互独立(无冒险),深流水线的控制被极大简化。
对 64 元素的寄存器、6 级乘法流水线,计算 需要 个周期(流水线填充 6 级 + 后续 63 个元素)。
2. 多功能单元并行
可用多个流水化功能单元(lane)同时处理向量的不同元素,例如用 4 条流水线,每条处理 [0,4,8,...]、[1,5,9,...] 这样交错的元素。
3. 向量单元结构(Vector Unit Structure):通道(Lane)
每条 Lane 含自己的功能单元(加法器、乘法器)与对应的向量寄存器分片,从存储子系统取交错的元素。
4. 向量指令并行(Vector Instruction Parallelism)
可重叠执行多条向量指令。
示例机器:每个向量寄存器 32 个元素、8 条 lane,可在每周期发射 1 条短指令的同时完成 24 个操作/周期。
5. 向量链接(Vector Chaining)
- 向量版的寄存器旁路(register bypassing),由 Cray-1 引入;
- 解决问题:RAW 寄存器依赖带来的长延迟;
- 链接的优势:依赖指令可在第一个结果元素出现时就开始执行,而不必等整个结果向量写完。
LV v1
MULV v3, v1, v2 # 与 LV 链接
ADDV v5, v3, v4 # 与 MULV 链接
七、向量存储系统(Vector Memory System)
- Cray-1:16 个存储体,存储体忙时间(bank busy time)4 周期,访问延迟 12 周期;
- 存储体忙时间:对同一存储体连续两次访问之间需间隔的周期数;
- 只要数据分布在不同存储体,就可支持 16 路并行访问。
八、关键编程技术
1. 向量分段(Stripmining)
问题:向量寄存器长度有限。 解法:把循环切成能放进寄存器的片段("采矿/分段")。
for (i = 0; i < N; i++)
C[i] = A[i] + B[i];
处理逻辑:先做 的"余数"段,再以 64 为单位循环处理剩余部分。
2. 向量条件执行(Vector Conditional Execution)
问题:要向量化含条件分支的循环:
for (i = 0; i < N; i++)
if (A[i] > 0) A[i] = B[i];
解法:增加向量掩码寄存器(vector mask / flag register),每元素 1 bit,是谓词寄存器的向量版本。掩码位为 0 的元素上,向量操作变成 NOP。
CVM # 打开所有元素的掩码
LV vA, xA # 载入整个 A 向量
SGTVS.D vA, f0 # A>0 处置掩码位
LV vA, xB # 在掩码下把 B 载入 A
SV vA, xA # 在掩码下把 A 写回
掩码向量指令的两种实现:
- 简单实现:执行全部 N 个操作,按掩码关闭结果写回;
- 密度-时间实现(Density-time):扫描掩码向量,只执行掩码非零的元素(可节省时间)。
3. 向量分散/聚集(Scatter / Gather)
向量化间接访问的循环:
for (i = 0; i < N; i++)
A[i] = B[i] + C[D[i]];
索引 load(Gather,聚集):
LV vD, xD # 载入索引向量 D
LVI vC, xC, vD # 以 xC 为基址间接载入
LV vB, xB
ADDV.D vA, vB, vC
SV vA, xA
上述翻译正确的前提:A 不与其他向量重叠。
Scatter(分散)示例:
for (i = 0; i < N; i++)
A[B[i]]++;
若 B 中含有重复值,naïve 的 gather→increment→scatter 翻译不正确(重复索引会丢失累加)。
九、后代向量超级机:NEC SX-6(2003)
- CMOS 工艺, CPU,单芯片,SDRAM 主存(最多 64GB);
- 标量单元:4 路超标量,乱序 + 推测执行,64KB I-cache + 64KB D-cache;
- 向量单元:8 个前台 + 64 个后台向量寄存器(每个 256×64-bit 元素),多个功能单元,8 条 lane(峰值 8 GFLOPS,16 FLOPS/cycle),单处理器 32 GB/s 访存带宽;
- SMP 结构:8 个 CPU 经交叉开关连内存,共享访存带宽 256 GB/s(4096 个交错存储体)。
十、多媒体 / SIMD 扩展(Multimedia / SIMD Extensions)
把短向量加进既有的通用 ISA。
- 思想最早见于 1957 年 Lincoln Labs TX-2(36-bit 数据通路可拆为 2×18b 或 4×9b);
- 早期实现常复用已有寄存器(如 64-bit 拆成 2×32b / 4×16b / 8×8b);
- 微处理器中向量宽度的发展趋势(x86):
| 扩展 | 年份 | 宽度 |
|---|---|---|
| MMX | 1996 | 64-bit(8×8b / 4×16b / 2×32b 整数) |
| SSE | 1999 | 128-bit |
| AVX | 2010 | 256-bit |
| AVX-512 | 2017 | 512-bit(新增 scatter/gather、掩码寄存器) |
多媒体扩展 vs 真正的向量机
多媒体扩展的局限:
- 指令集受限:无向量长度控制、通常无掩码、(早期)无步长/分散聚集、单位步长 load 须对齐到 64/128-bit;
- 向量寄存器长度受限:需靠超标量发射填满功能单元,循环展开隐藏延迟会增大寄存器压力;
- 趋势是逐步补全:更好的非对齐访存支持、双精度(64-bit FP)支持、掩码操作支持。
Knights Landing(KNL)CPU
Intel KNL(IEEE Micro, 2016)的特征:2 路译码/退休、6 路执行、72 项 ROB、64B cache 端口、2 load/1 store 端口、快速非对齐访问、快速 scatter/gather、4 线程 SMT,许多共享资源(ROB、重命名缓冲、保留站)动态分区。 互连采用 Mesh of Rings(半环行/列、YX 路由),缓存一致用 MESIF 协议 + 分布式目录过滤侦听;支持 All-to-all / Quadrant / Sub-NUMA 三种分区模式。
向量体系结构与数据并行总结
- 向量 ISA 通过"一条指令多个独立操作"同时获得紧凑性与表达力,从而简化取指、支持深流水与分体存储;
- 链接、分段、掩码、分散/聚集是把更广泛循环映射到向量硬件的关键技术;
- 现代通用处理器以多媒体/SIMD 扩展的形式吸收了向量思想,并持续向"完整向量支持"演进。
向量体系结构对经典冯·诺依曼取指瓶颈的降维打击
在传统乱序多发射超标量处理器中,为了挖掘几十个元素的循环级数据并行度,前端必须以极高功耗执行循环展开、重命名数百个临时物理寄存器、并在容量有限的保留站中做动态调度与唤醒匹配。而向量体系结构通过显式指定向量长度寄存器(VLR)和数据并行语义,仅用一条 32 位指令便声明了整批无循环相关的数据级操作。这不仅将前端取指与译码带宽消耗压缩了几个数量级,更彻底旁路了复杂的动态调度逻辑,将宝贵的硅片面积与能耗预算全部归还给流水线计算阵列与分体内存交叉开关。现代 GPU 的 SIMT 范式与 RISC-V Vector 扩展,本质上都是这一设计哲学的现代重生。
下一讲:GPUs