DeepSpeed团队近日发布了v0.17.4版本,这是继v0.17.3之后的一个重要补丁更新。本次更新主要围绕序列并行训练和内存效率优化展开,引入了多项关键改进,包括修复了维度变量错误、新增分片融合对数损失函数以及相关bug修复。本文将详细解析这些更新的技术细节、实现原理以及对大规模语言模型训练的实际影响。
DeepSpeed v0.17.4版本包含以下主要变更:
这些更新主要集中在序列并行训练领域,特别是针对超长序列训练场景的优化,相关技术源自论文《Arctic Long Sequence Training: Scalable And Efficient Training For Multi-Million Token Sequences》。
DeepSpeed在序列并行方面的核心组件包括:
UlyssesSPDataLoaderAdapter
:数据加载器适配器,用于将普通数据批次分片以供UlyssesSPAttentionHF
使用SequenceTiledCompute
:通用自动微分函数,用于在序列维度分片后执行计算TiledMLP
:特定的自动微分函数,用于执行分片MLP计算TiledFusedLogitsLoss
:新增的自动微分函数,无需完整生成对数张量即可计算损失在v0.17.4中,这些组件得到了进一步优化,特别是在梯度计算和内存管理方面。
TiledFusedLogitsLoss
是本次更新的核心功能之一,它通过分片计算损失函数,避免了生成完整的对数(logits)张量,从而显著降低了内存使用。其主要特点包括:
该功能的典型使用场景如下: .
def loss_fn(self, x, y):
logits = self.lm_head(x)
return self.cross_entropy_loss(logits.view(-1, self.vocab_size), y.view(-1))
loss = TiledFusedLogitsLoss.apply(
loss_fn,
self,
x,
y,
mask,
shards,
compute_params,
output_reduction,
)
TiledFusedLogitsLoss
的实现基于PyTorch的autograd.Function
,其核心思想是将输入张量在序列维度上进行分片,然后分别计算每个分片的损失,最后合并结果。关键技术点包括:
torch.chunk
将输入张量分割为多个分片特别值得注意的是,由于该自动微分函数通常位于调用堆栈的最后,它在forward
方法内部执行backward
,并人工补偿output_reduction
的影响,这消除了在backward
中重新运行forward
的需要。
本次更新修复了关于变量'dim'的UnboundLocalError问题。该问题出现在反向传播过程中,当某些输入不需要梯度时,'dim'变量可能未被定义。修复方案是在使用前明确定义'dim'变量: .
dim = grad_output.dim()
if ctx.needs_input_grad[0]:
grad_input = grad_output.matmul(weight)
if ctx.needs_input_grad[1]:
if dim > 2:
grad_weight = grad_output.reshape(-1, grad_output.shape[-1]).t().matmul(input.reshape(-1, input.shape[-1]))
在初步实现中发现并修复了TiledFusedLogitsLoss
的几个问题,包括:
DeepSpeed团队为这些更新添加了全面的单元测试,验证内容包括:
测试用例覆盖了不同批次大小(batch size)和ZeRO阶段(1和3)的组合,包括边界情况如非2^n长度的序列。
在实际应用中,这些更新带来了以下优势:
测试数据显示,在保持数值精度的前提下,内存使用量可降低30%-50%(取决于模型配置和序列长度)。
对于现有DeepSpeed用户,建议通过以下方式升级: .
pip install deepspeed==0.17.4
基于v0.17.4的更新,DeepSpeed在序列并行方面的路线图可能包括:
DeepSpeed v0.17.4虽然是一个小版本更新,但在序列并行和内存效率方面带来了重要改进。特别是TiledFusedLogitsLoss的引入,为训练大规模语言模型提供了新的内存优化手段。这些更新使得在有限硬件资源下训练更长序列的模型成为可能,为自然语言处理和多模态研究提供了有力支持。