ML 与线性代数
机器学习的核心运算是矩阵乘法等 BLAS 操作,Level 3 BLAS 的算术强度使其天然适合并行加速。
CS267 · 第 12 课
从线性代数到深度网络:机器学习中的并行化策略
机器学习包含多种学习范式,每种有其独特的并行化需求:
| 类型 | 定义 | 示例 |
|---|---|---|
| 监督学习 | 从标注数据学习输入→输出映射 | 分类、回归 |
| 无监督学习 | 从未标注数据发现结构 | 聚类、降维 |
| 半监督学习 | 结合少量标注与大量未标注数据 | 自训练、图方法 |
| 强化学习 | 通过与环境交互学习策略 | 游戏、机器人控制 |
常见混淆:"方法"与"任务"是不同的概念。例如,分类是一个任务,支持向量机(SVM)是完成该任务的一种方法。同一任务可以有多种方法,同一方法可以解决多种任务。
几乎所有机器学习方法的核心计算都可以归结为线性代数运算。BLAS(Basic Linear Algebra Subprograms)层次结构是理解这一点的关键:
| 级别 | 操作类型 | 复杂度 | 示例 |
|---|---|---|---|
| Level 1 BLAS | 向量-向量 | O(n) | 点积、向量加法 |
| Level 2 BLAS | 矩阵-向量 | O(n²) | GEMV(矩阵乘向量) |
| Level 3 BLAS | 矩阵-矩阵 | O(n³) | GEMM(矩阵乘法) |
为什么 Level 3 BLAS 重要:矩阵乘法(GEMM)具有极高的算术强度(计算/访存比),能充分利用缓存层次结构和并行硬件。现代 ML 框架(PyTorch、TensorFlow)底层大量依赖 GEMM。
机器学习中的并行可以分为两类:
实践建议:对于单机训练,优先使用隐式并行(配置好多线程 BLAS)。对于多机分布式训练,需要显式并行策略。
理解并行系统的扩展行为对 ML 至关重要:
// 强扩展:固定 N=100万样本,从 1 核到 1024 核 // 理想:1024 核应快 1024 倍(实际因通信开销达不到) // 弱扩展:每核 1000 样本,1024 核处理 102.4 万样本 // 理想:时间保持不变(实际因通信开销会增加)
深度神经网络(DNN)的训练基于两个核心算法:
# 简化的 SGD 训练循环
for epoch in range(num_epochs):
for batch in data_loader: # mini-batch
# 前向传播
predictions = model(batch.inputs)
loss = loss_fn(predictions, batch.targets)
# 反向传播
gradients = backward(loss, model.parameters())
# 参数更新
for param, grad in zip(model.parameters(), gradients):
param -= learning_rate * grad
Mini-batch SGD 是实践中的标准做法:每个更新步骤使用一小批样本(而非单个样本或全部样本)计算梯度,兼顾梯度估计质量和计算效率。
大规模 DNN 训练有多种并行化策略:
| 并行类型 | 划分对象 | 通信模式 |
|---|---|---|
| 数据并行 | 训练样本(batch) | 梯度聚合(allreduce) |
| 模型并行 | 模型层/参数 | 激活/梯度传递 |
| 张量并行 | 单个张量(如权重矩阵) | 矩阵乘法中间结果 |
| 流水线并行 | 网络层(阶段) | 阶段间激活传递 |
| 专家并行 | MoE 中的专家 | 门控路由 |
数据并行是最常用的并行策略:每个 worker 持有模型完整副本,处理不同的数据子集,然后聚合梯度。
# 数据并行伪代码
# 每个 rank 执行
for batch in local_data_split:
grad = compute_gradient(model, batch)
all_gradients = allreduce(grad, op="sum") # 全局聚合
model.update(all_gradients / world_size)
批量并行(Batch Parallelism)将大 batch 拆分到多个设备上。当 batch 很大时(如 GPT-3 使用 1024+ GPUs),全局 batch 可以非常大。
线性缩放规则:当 batch size 增大 k 倍时,学习率也可以增大 k 倍(在一定范围内)。这使得大 batch 训练能在更少迭代内收敛。
参数服务器(Parameter Server)是另一种经典架构:
// 参数服务器工作流程 // Worker: params = server.pull(key) // 拉取最新参数 grad = compute_gradient(params, data) // 计算梯度 server.push(key, grad) // 推送梯度 // Server: grads = collect_from_workers(params) params -= lr * average(grads) // 更新参数
参数服务器问题:大规模训练时,server 可能成为通信瓶颈。Ring AllReduce(Horovod)等去中心化方法可以缓解这一问题。
DNN 训练可以完全用矩阵运算表示。考虑一个全连接层:
Y = XW + b 其中: X: [batch_size, input_dim] 输入矩阵 W: [input_dim, output_dim] 权重矩阵 b: [output_dim] 偏置向量 Y: [batch_size, output_dim] 输出矩阵
反向传播也可以写成矩阵形式:
dX = dY · W^T # 对输入的梯度 dW = X^T · dY # 对权重的梯度 db = sum(dY, axis=0) # 对偏置的梯度
这种矩阵形式使得我们可以直接利用高度优化的 BLAS 库(cuBLAS、MKL)进行计算。
实际大规模训练通常组合多种并行策略。例如,Megatron-LM 使用张量并行(机内)+ 流水线并行(机间):
// Megatron-LM 风格的混合并行 // 同一节点内:张量并行(矩阵按列/行切分) // 跨节点:流水线并行(不同层在不同节点) // 全局:数据并行(不同节点组处理不同数据) // 矩阵乘法的张量并行示例(列切分) // W = [W1 | W2] (按列切分到两个 GPU) // Y = XW = [XW1 | XW2] = [Y1 | Y2] // 每个 GPU 计算部分结果,最后 allgather
CNN 通过卷积核提取局部特征,其并行化策略包括:
// 域并行:将图像切分到 4 个设备 // 设备 1: 左上区域 // 设备 2: 右上区域 // 设备 3: 左下区域 // 设备 4: 右下区域 // 需要 halo 交换处理边界(类似 MPI 域分解)
Transformer 是 NLP 和视觉领域的主流架构。长序列训练面临显存和计算瓶颈:
自注意力(Self-Attention)是 Transformer 的核心:
Attention(Q, K, V) = softmax(QK^T / √d_k) · V 其中: Q: Query 矩阵 [seq_len, d_k] K: Key 矩阵 [seq_len, d_k] V: Value 矩阵 [seq_len, d_v] d_k: 注意力维度
注意力的计算复杂度为 O(n²d),其中 n 是序列长度。这是长序列的主要瓶颈。
Ring Attention 是一种处理超长序列的并行策略。设备排成环状,每个设备持有一部分 KV 和完整的 Q:
// Ring Attention 工作流程
// 设备 i 持有 Q_i, K_i, V_i
// 步骤 1: 设备 i 计算 Q_i 与 K_i 的本地 attention
// 步骤 2: 将 K_i, V_i 传递给设备 i+1(环状)
// 步骤 3: 收到 K_{i-1}, V_{i-1} 后继续计算
// 重复直到所有 KV 被处理
Ring Attention 优势:通过通信与计算重叠,将 attention 的显存需求从 O(n) 降低到 O(n/p),其中 p 是设备数。这使得训练百万级序列长度成为可能。
流水线并行将网络层分配到不同设备,像流水线一样处理不同 micro-batch:
| 方法 | 特点 | 代表 |
|---|---|---|
| GPipe | 同步更新,等待所有 micro-batch 完成 | Google, 2019 |
| PipeDream | 异步更新,不同 micro-batch 可能在不同版本 | Microsoft, 2019 |
| 1F1B | 一进一出调度,减少显存 | PipeDream-Flush |
// GPipe 流水线示意(4 个 stage) // Stage 1: layers 1-3 ← micro-batch 1, 2, 3, 4 // Stage 2: layers 4-6 ← micro-batch 1, 2, 3, 4 // Stage 3: layers 7-9 ← micro-batch 1, 2, 3, 4 // Stage 4: layers 10-12 ← micro-batch 1, 2, 3, 4 // // 时间线: // t1: [mb1] [ ] [ ] [ ] // t2: [mb2] [mb1] [ ] [ ] // t3: [mb3] [mb2] [mb1] [ ] // t4: [mb4] [mb3] [mb2] [mb1] // t5: [ ] [mb4] [mb3] [mb2] // t6: [ ] [ ] [mb4] [mb3] // t7: [ ] [ ] [ ] [mb4]
流水线气泡(Bubble):流水线并行存在空闲时间(bubble),因为第一个 micro-batch 需要时间填满流水线。bubble 比例约为 (p-1)/m,其中 p 是 stage 数,m 是 micro-batch 数。
MoE(Mixture of Experts)模型包含多个"专家"子网络和门控网络。每个输入只激活少数专家,从而在不增加计算量的情况下增大模型容量。
// MoE 工作流程 // 1. 门控网络决定每个 token 发送给哪些专家 // 2. 将 token 路由到对应专家(跨设备通信) // 3. 专家处理 token // 4. 将结果路由回原设备,加权求和 // 专家并行:不同专家放在不同设备 // 设备 1: Expert 1, Expert 2 // 设备 2: Expert 3, Expert 4 // ...
MoE 挑战:负载均衡是 MoE 的关键问题。如果所有 token 都路由到少数专家,其他专家闲置。常用的解决方案包括辅助损失函数和专家容量限制。
支持向量机(SVM)是经典的监督学习方法,目标是找到最大化分类间隔的超平面。
// 原始优化问题 minimize: (1/2)||w||^2 + C * Σ ξ_i subject to: y_i(w·x_i + b) ≥ 1 - ξ_i, ξ_i ≥ 0 // 对偶问题(更常用) maximize: Σ α_i - (1/2) Σ Σ α_i α_j y_i y_j K(x_i, x_j) subject to: 0 ≤ α_i ≤ C, Σ α_i y_i = 0
当数据线性不可分时,通过核函数将数据映射到高维空间:
| 核函数 | 公式 |
|---|---|
| 线性核 | K(x,y) = x·y |
| 多项式核 | K(x,y) = (γ x·y + r)^d |
| RBF(高斯)核 | K(x,y) = exp(-γ||x-y||²) |
| Sigmoid 核 | K(x,y) = tanh(γ x·y + r) |
Sequential Minimal Optimization(SMO)是求解 SVM 对偶问题的高效算法,每次只优化两个 Lagrange 乘子。
// SMO 算法概要
repeat:
选择违反 KKT 条件最严重的 α_i
选择使目标函数下降最大的 α_j
在约束下优化 (α_i, α_j)
until convergence
有多种并行 SVM 方法,各有不同的并行策略和适用场景:
| 方法 | 策略 | 特点 |
|---|---|---|
| Cascade SVM | 层次化训练 | 将数据分块训练子 SVM,再合并训练上层 |
| DC-SVM | 分解协调 | 将大问题分解为子问题,协调器整合 |
| CP-SVM | 约束优化 | 基于约束优化的分布式求解 |
| CA-SVM | 通信避免 | 减少通信次数,以计算换通信 |
// Cascade SVM 示意 // Level 1: 数据分为 4 块,分别训练 SVM_1, SVM_2, SVM_3, SVM_4 // Level 2: 收集各子 SVM 的支持向量,合并后训练 SVM_12, SVM_34 // Level 3: 合并 SVM_12 和 SVM_34 的支持向量,训练最终 SVM
CA-SVM 洞察:通信避免(Communication-Avoiding)方法通过重复计算来减少通信,在通信昂贵时特别有效。这与本章前面讨论的 PGAS one-sided 通信思想一致。
机器学习的核心运算是矩阵乘法等 BLAS 操作,Level 3 BLAS 的算术强度使其天然适合并行加速。
数据并行、模型并行、张量并行、流水线并行、专家并行各有适用场景,实际系统常组合使用。
反向传播计算梯度,SGD 更新参数,mini-batch 平衡梯度质量与计算效率。
序列并行、上下文并行、Ring Attention 是处理长序列的关键技术。
GPipe、PipeDream 等方法通过 micro-batch 流水线化减少空闲时间,但仍有 bubble 开销。
核技巧将线性 SVM 扩展到非线性问题,SMO 是高效求解算法,多种并行 SVM 方法针对不同场景。
问题 1:在 BLAS 层次结构中,哪个级别的操作算术强度最高,最适合作为并行优化的目标?
问题 2:数据并行(Data Parallelism)中,什么被划分到不同设备?
问题 3:在 GPipe 流水线并行中,"bubble"(气泡)指的是什么?
问题 4:核技巧(Kernel Trick)的主要目的是什么?
问题 5:Ring Attention 如何支持超长序列训练?