第11章 大模型训练系统 - 千卡集群的挑战 (Large Model Training Systems: Challenges of Thousand-GPU Clusters)
一、导读
1.1 本章学习目标
通过本章的学习,读者将能够:
理解大语言模型训练的系统挑战和规模特征
掌握3D并行策略(数据并行、流水线并行、张量并行)的组合方法
深入分析Megatron-LM和DeepSpeed的架构设计
了解大规模训练中的故障恢复和容错机制
掌握混合精度训练在大模型场景下的特殊考虑
理解训练稳定性问题和解决方案
能够设计和评估千卡级别的训练方案
了解大模型训练的成本分析和优化策略
1.2 为什么本章如此重要
大语言模型(LLM)的出现彻底改变了人工智能领域。从GPT-3的1750亿参数到PaLM的5400亿参数,再到万亿参数的混合专家模型,模型规模的指数级增长对训练系统提出了前所未有的挑战。
训练这些模型不再是简单的算法问题,而是复杂的系统工程。千卡甚至万卡集群的协调、数月的连续运行、海量的数据传输、频繁的硬件故障——这些因素使得大模型训练成为当今最具挑战性的计算任务之一。
理解大模型训练系统对于多个方面至关重要。首先,它是构建前沿AI能力的必要条件。其次,大模型训练的技术正在向下渗透,影响中小模型的训练方式。第三,随着开源大模型的兴起,更多组织需要掌握大规模训练的能力。最后,大模型训练中发展的技术(如ZeRO、自动并行)正在重塑整个深度学习系统的格局。
1.3 核心问题引导
在学习本章内容时,请思考以下问题:
大模型训练的规模有多大?参数量、数据量、计算量分别达到什么级别?
为什么单GPU无法训练大模型?显存、计算、通信的限制各是什么?
3D并行如何组合数据并行、流水线并行和张量并行?每种并行的作用是什么?
Megatron-LM的张量并行设计有什么创新?它如何减少通信开销?
DeepSpeed的ZeRO优化器如何消除冗余?三个级别的区别是什么?
大规模训练中的故障率有多高?如何设计高效的检查点和恢复机制?
训练不稳定(loss spike、divergence)的原因有哪些?如何应对?
训练一个大模型的成本是多少?如何优化成本效益?
二、核心概念详解
大模型训练的规模特征
要理解大模型训练的挑战,首先需要量化其规模。
参数量:
- GPT-3: 1750亿参数
- PaLM: 5400亿参数
- GPT-4: 估计约1.8万亿参数(混合专家)
- 最新模型:已达万亿级别
显存需求:
使用FP16精度,每个参数占用2字节。但训练时需要存储:
- 参数:2字节/参数
- 梯度:2字节/参数
- 优化器状态(Adam):8字节/参数(momentum + variance)
总计:12字节/参数
对于1750亿参数的GPT-3:
- 仅参数+梯度+优化器:$175 \times 10^9 \times 12 = 2.1$ TB
这远超任何单GPU的显存容量(最大约80GB)。
计算量:
训练一个Transformer模型的FLOPs约为:
$$\text{FLOPs} \approx 6 \times N \times D$$
其中$N$是参数量,$D$是训练token数量。
对于GPT-3(175B参数,300B token):
$$\text{FLOPs} \approx 6 \times 175 \times 10^9 \times 300 \times 10^9 \approx 3.15 \times 10^{23}$$
即约315 ZettaFLOPs。
使用1000张A100 GPU(每张约312 TFLOPS FP16),理论训练时间:
$$\frac{3.15 \times 10^{23}}{1000 \times 312 \times 10^{12}} \approx 10^6 \text{秒} \approx 12 \text{天}$$
考虑到实际效率(约30-50%),实际需要约1个月。
数据量:
- 训练数据:数百GB到数TB的文本
- 检查点:每个完整检查点数TB
- 日志:训练过程中产生的大量指标和调试信息
3D并行策略
由于单GPU无法容纳大模型,必须使用并行策略将计算分布到多个设备上。现代大模型训练通常结合三种并行方式,称为3D并行。
数据并行(Data Parallelism)
原理:在每个设备上保存完整的模型副本,但处理不同的数据子集。
优点:
- 实现简单
- 线性扩展吞吐量
缺点:
- 每个设备需要存储完整模型,显存效率低
- 需要梯度同步,通信开销大
在大模型中的应用:数据并行通常作为外层并行,与模型并行结合使用。
流水线并行(Pipeline Parallelism)
原理:将模型的层分组分配到不同设备上。
GPipe调度:
将大批次拆分为多个微批次(micro-batch),依次送入流水线。
对于$P$个设备和$M$个微批次:
- 无气泡的流水线利用率:$\frac{M}{M + P - 1}$
- 为了达到90%利用率,需要$M \approx 9P$
1F1B调度:
PipeDream提出的 interleaved 1F1B(one forward one backward)调度,每个设备交替执行前向和后向传播,进一步减少气泡。
优点:
- 可以训练超出单卡显存的模型
- 实现相对简单
缺点:
- 流水线气泡降低效率
- 跨设备传递中间激活值,通信开销大
- 负载不均衡问题
张量并行(Tensor Parallelism)
原理:将单个层的权重矩阵分割到多个设备上。
Megatron-LM的设计:
Megatron-LM的关键创新是设计了通信高效的张量并行方案。通过分析Transformer层的结构,发现可以将某些操作重新排列,使得通信只在特定位置发生。
具体来说:
自注意力层的并行:
- QKV投影:将权重按列分割,每个设备计算部分Q、K、V
- 注意力得分:可以在各设备独立计算(因为只涉及局部数据)
- 注意力输出:需要AllReduce同步
MLP层的并行:
- 第一个线性层:按列分割
- GeLU激活:局部计算
- 第二个线性层:按行分割
- 输出:天然完成归约,无需额外通信
这种设计使得每个Transformer层只需要2次AllReduce通信,而不是每步都通信。
优点:
- 有效利用大量设备
- 没有流水线气泡
缺点:
- 通信开销大
- 实现复杂
- 要求维度可整除
3D并行的组合
典型的配置:
- 张量并行度 $TP$:4-8(层内并行)
- 流水线并行度 $PP$:8-64(层间并行)
- 数据并行度 $DP$:剩余设备数
总设备数:$N = TP \times PP \times DP$
例如,使用512张GPU训练GPT-3:
- $TP = 8$
- $PP = 16$
- $DP = 512 / (8 \times 16) = 4$
Megatron-LM架构
Megatron-LM是NVIDIA开发的大模型训练框架,其核心贡献是高效的张量并行实现。
关键设计
张量并行Transformer:
如前所述,通过精心设计,将每层的通信减少到2次AllReduce。
序列并行(Sequence Parallelism):
对于长序列,LayerNorm和Dropout等操作也可以并行化。序列并行将序列维度分割到不同设备上。
重叠通信和计算:
在反向传播过程中,尽早启动梯度同步,与后续层的反向传播重叠。
高效的CUDA内核:
手写优化的Fused kernels,将多个操作融合为一个内核。
性能
Megatron-LM在数千张GPU上实现了良好的扩展效率:
- 512张A100:约40-50%的MFU(Model FLOPs Utilization)
- 可扩展到数千张GPU
DeepSpeed架构
DeepSpeed是Microsoft开发的深度学习优化库,其核心创新是ZeRO优化器。
ZeRO(Zero Redundancy Optimizer)
标准数据并行中,每个设备存储完整的参数、梯度和优化器状态,存在大量冗余。ZeRO通过分片消除这些冗余。
ZeRO-1(优化器状态分片):
- 将优化器状态(momentum、variance)分片到不同设备
- 每个设备只存储部分优化器状态
- 更新时通过通信获取所需部分
- 显存节省:约4倍
ZeRO-2(优化器状态+梯度分片):
- 在ZeRO-1基础上,还将梯度分片
- 反向传播后,每个设备只保留部分梯度
- 显存节省:约8倍
ZeRO-3(优化器状态+梯度+参数分片):
- 进一步将参数本身分片
- 每个设备只存储部分参数
- 前向传播时,动态获取所需参数;使用后释放
- 显存节省:约$N$倍($N$为数据并行度)
ZeRO-Offload:
将部分数据(如优化器状态)卸载到CPU内存,进一步节省GPU显存。代价是引入PCIe传输开销。
ZeRO-Infinity:
结合NVMe SSD,理论上可以训练无限大的模型。
DeepSpeed的其他特性
管道并行:与Megatron类似的流水线并行实现。
混合精度:支持FP16、BF16等混合精度训练。
通信优化:梯度压缩、延迟更新等。
检查点:高效的分布式检查点保存和加载。
Megatron-DeepSpeed
结合Megatron的张量并行和DeepSpeed的ZeRO,形成最强大的训练框架。
架构:
- 内层:张量并行(Megatron风格)
- 中层:流水线并行
- 外层:ZeRO数据并行
支持的模型规模:
- 万亿参数级别
- 数千张GPU
代表工作:
- BLOOM(176B)
- MT-NLG(530B)
- GLM系列
故障恢复与容错
在千卡集群上运行数月,硬件故障是常态而非例外。
故障率估算:
假设单GPU月故障率为1%,则1000张GPU的月故障率为:
$$1 - (1 - 0.01)^{1000} \approx 99.996\%$$
即几乎每月都会遇到至少一次故障。
检查点策略:
完整检查点:
保存所有参数、优化器状态、训练进度。
- 优点:可以完全恢复
- 缺点:体积大(数TB),保存耗时
局部检查点:
只保存必要信息。
- 优点:快速、体积小
- 缺点:恢复能力有限
异步检查点:
在后台线程保存检查点,不阻塞训练。
- 优点:不影响训练速度
- 缺点:可能保存不一致的状态
检查点频率:
需要在恢复时间和存储成本之间权衡。通常每1-4小时保存一次。
弹性训练:
支持动态添加/移除设备,适应资源变化。
训练稳定性
大模型训练经常出现不稳定现象,如loss spike、divergence等。
常见问题:
Loss Spike:
损失突然大幅上升,然后可能恢复或持续高位。
- 原因:梯度爆炸、数值不稳定、学习率过高
- 解决:梯度裁剪、降低学习率、更好的初始化
Divergence:
损失发散到NaN或Inf。
- 原因:数值溢出、除零、log(负数)
- 解决:混合精度调整、数值稳定的实现
梯度异常:
梯度范数突然变大或变小。
- 监控:记录梯度范数直方图
- 解决:梯度裁剪、更好的归一化
稳定训练的技巧:
Warmup:逐渐增加学习率
Gradient Clipping:限制梯度范数
Layer Normalization:稳定激活值分布
混合精度管理:适当的损失缩放
监控:实时监控关键指标
成本分析
大模型训练的成本极其高昂。
硬件成本:
- A100 GPU:约$10,000-15,000/张
- 1000张:约$10-15M
- 网络基础设施:额外数百万
电力成本:
- A100功耗:约400W
- 1000张×400W = 400kW
- 运行一个月:约$100,000电费
云成本:
- A100实例:约$3-5/小时
- 1000张×30天×24小时×$3 ≈ $2.16M/月
总成本估算:
训练GPT-3级别模型:
- 硬件折旧 + 电力 + 人力:约$5-10M
- 云服务:约$2-5M/次
优化策略:
提高MFU(Model FLOPs Utilization)
减少重新训练次数
使用spot实例降低成本
模型复用和微调而非从头训练
三、程序员的视角
3.1 在实际项目中的应用
选择合适的框架:对于百亿级以上模型,使用Megatron-DeepSpeed或类似框架。对于较小模型,PyTorch DDP可能足够。
配置并行策略:根据模型大小和设备数量选择TP、PP、DP的组合。一般原则:TP尽量小(4-8),PP根据层数确定,DP占据剩余设备。
监控和调试:建立完善的监控系统,跟踪loss、梯度、显存等关键指标。设置告警以便及时发现异常。
3.2 常见陷阱与误区
忽视通信开销:在高并行度下,通信可能成为瓶颈。需要仔细分析通信模式。
检查点不足:故障发生时,如果没有最近的检查点,可能损失数天的训练成果。
忽略数值稳定性:大模型对数值问题更敏感。需要使用稳定的实现和适当的精度管理。
过度并行:过多的并行维度会增加复杂性,可能适得其反。
3.3 与其他层级的联系
大模型训练系统整合了之前章节讨论的所有技术:自动微分、张量运算、内存管理、分布式训练、通信优化、编译器优化。它是这些技术的综合应用。
四、代码实战
示例1:Megatron风格的张量并行
"""
简化的Megatron风格张量并行实现
注意:这是教学示例,实际生产应使用Megatron-LM或DeepSpeed
"""
import torch
import torch.nn as nn
import torch.distributed as dist
class TensorParallelLinear(nn.Module):
"""
张量并行的线性层
支持列并行和行并行
"""
def __init__(self, in_features, out_features, parallel_mode='column'):
super().__init__()
self.parallel_mode = parallel_mode
self.world_size = dist.get_world_size() if dist.is_initialized() else 1
self.rank = dist.get_rank() if dist.is_initialized() else 0
assert out_features % self.world_size == 0
if parallel_mode == 'column':
# 列并行:分割输出维度
self.local_out = out_features // self.world_size
self.weight = nn.Parameter(torch.randn(in_features, self.local_out))
elif parallel_mode == 'row':
# 行并行:分割输入维度
assert in_features % self.world_size == 0
local_in = in_features // self.world_size
self.weight = nn.Parameter(torch.randn(local_in, out_features))
self.reset_parameters()
def reset_parameters(self):
nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))
def forward(self, x):
if self.parallel_mode == 'column':
# 列并行:局部计算,然后AllGather
local_output = x @ self.weight
# 收集所有部分的输出
outputs = [torch.empty_like(local_output) for _ in range(self.world_size)]
dist.all_gather(outputs, local_output)
return torch.cat(outputs, dim=-1)
elif self.parallel_mode == 'row':
# 行并行:先Scatter输入,然后局部计算并Reduce
input_chunks = torch.chunk(x, self.world_size, dim=-1)
local_input = input_chunks[self.rank]
local_output = local_input @ self.weight
# Reduce散射的结果
dist.all_reduce(local_output)
return local_output
class TensorParallelTransformerLayer(nn.Module):
"""
简化的张量并行Transformer层
"""
def __init__(self, hidden_size, num_heads):
super().__init__()
self.hidden_size = hidden_size
self.num_heads = num_heads
# QKV投影(列并行)
self.qkv_proj = TensorParallelLinear(hidden_size, hidden_size * 3, 'column')
# 输出投影(行并行)
self.out_proj = TensorParallelLinear(hidden_size, hidden_size, 'row')
# MLP(列+行并行)
self.mlp_fc1 = TensorParallelLinear(hidden_size, hidden_size * 4, 'column')
self.mlp_fc2 = TensorParallelLinear(hidden_size * 4, hidden_size, 'row')
self.ln1 = nn.LayerNorm(hidden_size)
self.ln2 = nn.LayerNorm(hidden_size)
self.activation = nn.GELU()
def forward(self, x):
# 自注意力
residual = x
x = self.ln1(x)
# QKV
qkv = self.qkv_proj(x)
q, k, v = torch.chunk(qkv, 3, dim=-1)
# 简化注意力计算
# 实际实现需要更复杂的逻辑
attn_output = self.attention(q, k, v)
# 输出投影
x = self.out_proj(attn_output)
x = x + residual
# MLP
residual = x
x = self.ln2(x)
x = self.mlp_fc1(x)
x = self.activation(x)
x = self.mlp_fc2(x)
x = x + residual
return x
def attention(self, q, k, v):
"""简化的注意力计算"""
scale = 1 / math.sqrt(q.size(-1))
scores = torch.matmul(q, k.transpose(-2, -1)) * scale
weights = torch.softmax(scores, dim=-1)
return torch.matmul(weights, v)示例2:ZeRO优化器简化实现
"""
简化的ZeRO优化器实现
注意:这是教学示例,实际应使用DeepSpeed的ZeRO
"""
import torch
class ZeroOptimizer:
"""
ZeRO-1优化器的简化实现
将优化器状态分片到不同进程
"""
def __init__(self, model, optimizer_class=torch.optim.Adam, lr=0.001):
self.model = model
self.rank = dist.get_rank()
self.world_size = dist.get_world_size()
# 将参数分组
self.param_groups = self._partition_parameters()
# 每个进程只优化自己的参数组
local_params = self.param_groups[self.rank]
self.optimizer = optimizer_class(local_params, lr=lr)
def _partition_parameters(self):
"""将参数均匀分配到各进程"""
all_params = list(self.model.parameters())
partitions = [[] for _ in range(self.world_size)]
for i, param in enumerate(all_params):
partitions[i % self.world_size].append(param)
return partitions
def step(self):
"""执行优化步骤"""
# 本地更新
self.optimizer.step()
# 广播更新后的参数到其他进程
for rank in range(self.world_size):
if rank != self.rank:
# 从拥有该参数组的进程广播
pass # 简化处理
def zero_grad(self):
"""清零梯度"""
self.optimizer.zero_grad()
class ZeroStage3Optimizer:
"""
ZeRO-3优化器的简化概念
参数也进行分片,使用时动态获取
"""
def __init__(self, model, lr=0.001):
self.model = model
self.rank = dist.get_rank()
self.world_size = dist.get_world_size()
# 参数分片
self.param_shards = self._shard_parameters()
# 本地优化器
self.optimizer = torch.optim.Adam(self.param_shards, lr=lr)
def _shard_parameters(self):
"""将参数分片"""
all_params = list(self.model.parameters())
shards = []
for i, param in enumerate(all_params):
if i % self.world_size == self.rank:
shards.append(param)
return shards
def gather_params_for_forward(self, layer):
"""在前向传播前收集所需参数"""
# 从其他进程获取缺失的参数
pass
def release_unused_params(self):
"""释放不再需要的参数以节省显存"""
pass
def step(self):
self.optimizer.step()
self.release_unused_params()示例3:训练稳定性监控
"""
大模型训练稳定性监控工具
"""
import torch
import numpy as np
from collections import deque
class TrainingMonitor:
"""
训练监控器
跟踪关键指标并检测异常
"""
def __init__(self, window_size=100):
self.loss_history = deque(maxlen=window_size)
self.grad_norm_history = deque(maxlen=window_size)
self.param_norm_history = deque(maxlen=window_size)
self.alert_thresholds = {
'loss_spike': 3.0, # loss突增倍数
'grad_explosion': 100.0, # 梯度范数阈值
'nan_detected': True,
}
def record_step(self, loss, grad_norm=None, param_norm=None):
"""记录一步训练的数据"""
self.loss_history.append(loss.item())
if grad_norm is not None:
self.grad_norm_history.append(grad_norm)
if param_norm is not None:
self.param_norm_history.append(param_norm)
def check_anomalies(self):
"""检查是否有异常"""
alerts = []
# 检查loss spike
if len(self.loss_history) > 10:
recent_avg = np.mean(list(self.loss_history)[-10:])
previous_avg = np.mean(list(self.loss_history)[:-10])
if previous_avg > 0 and recent_avg / previous_avg > self.alert_thresholds['loss_spike']:
alerts.append(f"Loss spike detected: {previous_avg:.4f} -> {recent_avg:.4f}")
# 检查梯度爆炸
if self.grad_norm_history:
latest_grad = self.grad_norm_history[-1]
if latest_grad > self.alert_thresholds['grad_explosion']:
alerts.append(f"Gradient explosion: norm={latest_grad:.2f}")
# 检查NaN
if self.loss_history and np.isnan(list(self.loss_history)[-1]):
alerts.append("NaN detected in loss!")
return alerts
def get_statistics(self):
"""获取统计信息"""
stats = {}
if self.loss_history:
losses = list(self.loss_history)
stats['loss_mean'] = np.mean(losses)
stats['loss_std'] = np.std(losses)
stats['loss_min'] = np.min(losses)
stats['loss_max'] = np.max(losses)
if self.grad_norm_history:
grads = list(self.grad_norm_history)
stats['grad_norm_mean'] = np.mean(grads)
stats['grad_norm_max'] = np.max(grads)
return stats
def plot_history(self):
"""绘制历史曲线"""
try:
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
if self.loss_history:
axes[0].plot(list(self.loss_history))
axes[0].set_title('Loss History')
axes[0].set_xlabel('Step')
axes[0].set_ylabel('Loss')
if self.grad_norm_history:
axes[1].plot(list(self.grad_norm_history))
axes[1].set_title('Gradient Norm History')
axes[1].set_xlabel('Step')
axes[1].set_ylabel('Grad Norm')
if self.param_norm_history:
axes[2].plot(list(self.param_norm_history))
axes[2].set_title('Parameter Norm History')
axes[2].set_xlabel('Step')
axes[2].set_ylabel('Param Norm')
plt.tight_layout()
plt.savefig('training_monitor.png')
print("Plot saved to training_monitor.png")
except ImportError:
print("matplotlib not available")
def gradient_clipping(model, max_norm=1.0):
"""
梯度裁剪
Args:
model: 模型
max_norm: 最大梯度范数
"""
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=max_norm)
def mixed_precision_stability_check(loss_scaler, scaler_factor=2.0):
"""
检查混合精度训练的稳定性
如果频繁出现overflow,可能需要调整loss scale
"""
if loss_scaler.get_scale() < 1e-10:
print("Warning: Loss scale is very low, consider adjusting")
return False
return True
# 使用示例
def training_loop_with_monitoring():
"""带监控的训练循环示例"""
monitor = TrainingMonitor()
# 模拟训练
for step in range(1000):
# 模拟损失和梯度
loss = torch.tensor(1.0 / (step + 1) + np.random.randn() * 0.1)
grad_norm = torch.randn(1).item() * 10
monitor.record_step(loss, grad_norm)
# 检查异常
if step % 100 == 0:
alerts = monitor.check_anomalies()
if alerts:
for alert in alerts:
print(f"ALERT: {alert}")
stats = monitor.get_statistics()
print(f"Step {step}: {stats}")
monitor.plot_history()
if __name__ == "__main__":
training_loop_with_monitoring()五、深入思考
5.1 历史背景
大模型训练的发展有几个关键节点:
- 2018年:BERT和GPT开启了Transformer时代
- 2019年:GPT-2展示了规模化的力量
- 2020年:GPT-3证明了千亿参数模型的可行性
- 2021-2022年:Megatron-Turing NLG、PaLM等推动边界
- 2023年至今:GPT-4、Claude、Llama等百花齐放
训练框架也随之演进:从简单的DataParallel到Megatron、DeepSpeed,再到Megatron-DeepSpeed的组合。
5.2 前沿方向
MoE(Mixture of Experts):稀疏激活的模型架构,可以在不增加计算成本的情况下扩大模型规模。
自动并行:编译器自动决定最优的并行策略,减轻人工配置的负担。
绿色训练:降低能耗,提高能效比。
联邦学习:在保护隐私的前提下利用分布式数据。
持续学习:在不遗忘旧知识的情况下学习新任务。
5.3 延伸阅读
- "Efficient Large-Scale Language Model Training on GPU Clusters Using Megatron-LM" - NVIDIA论文
- DeepSpeed官方文档和论文
- "PaLM: Scaling Language Modeling with Pathways" - Google的Pathways系统
- "Training Compute-Optimal Large Language Models" - Chinchilla论文
六、实验笔记
实验1:模拟3D并行配置
目标:理解不同并行配置的影响
步骤:
给定模型规格和设备数量
计算不同TP、PP、DP组合下的显存占用和通信开销
找出最优配置
预期结果:存在一个最优平衡点,过度增加某一维度会降低效率
分析要点:
- 各维度的扩展性如何?
- 通信开销的变化趋势?
- 实际约束(如维度整除)的影响?
实验2:故障恢复测试
目标:评估不同检查点策略的效果
步骤:
模拟训练过程中的随机故障
使用不同频率的检查点
测量有效训练时间占比
预期结果:检查点频率需要平衡恢复时间和训练效率
分析要点:
- 最优检查点频率是多少?
- 异步检查点的优势有多大?
- 如何处理检查点损坏?
七、本章小结
本章深入探讨了大模型训练系统的各个方面,从规模特征到并行策略,从框架设计到故障恢复。我们理解了千卡集群训练的独特挑战,以及应对这些挑战的技术方案。
大模型训练代表了当前深度学习系统的最高水平,它整合了之前章节讨论的所有技术。随着模型规模的持续增长,这一领域的创新将继续推动系统设计的边界。
八、习题
估算训练一个5000亿参数Transformer模型所需的显存、计算量和时间。假设使用1024张A100 GPU。
解释Megatron-LM如何将Transformer层的通信减少到2次AllReduce。详细推导这个过程。
比较ZeRO-1、ZeRO-2、ZeRO-3的显存节省和通信开销。在什么情况下应该选择哪个级别?
对于一个有96层的Transformer模型,设计一个3D并行配置。说明你的选择理由。
大模型训练中loss spike的可能原因有哪些?列举至少五种并提出对应的解决方案。
解释流水线并行的1F1B调度如何工作。相比简单GPipe调度,它的优势是什么?
阅读Megatron-DeepSpeed论文,解释它如何结合两种框架的优势。存在什么挑战?
估算GPT-3训练的总成本,包括硬件、电力和人力。与云计算成本对比。
设计一个分布式检查点方案,能够在最小化训练中断的同时保证一致性。
调研MoE(Mixture of Experts)架构,解释它如何在保持计算成本可控的情况下扩大模型规模。