You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置DeepSpeed Stage3后,Lightning模型未层并行且报CUDA OOM错误

问题:DeepSpeed Stage3下PyTorch Lightning模型未实现层并行导致显存溢出

我想用PyTorch Lightning搭建基于DeepSpeed的示例,已设置deepspeed_stage_3策略,但模型层未被并行化。为测试,我添加了18000个全连接层,期望这些层能分布到6个GPU上,却触发了CUDA显存不足错误:

torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate
2.00 MiB (GPU 3; 15.00 GiB total capacity; 14.00 GiB already allocated; 5.25 MiB free; 14.00 GiB reserved in total by PyTorch) If
reserved memory is >> allocated memory try setting max_split_size_mb
to avoid fragmentation. See documentation for Memory Management and
PYTORCH_CUDA_ALLOC_CONF

推测所有层都被部署到了单个GPU。核心代码如下:

模型定义代码

class TelModel(L.LightningModule):
    def __init__(self):
        super().__init__()
        embed_dim = 512
        component_list = [
                nn.Linear(512, embed_dim)
        #] + [nn.TransformerEncoderLayer(d_model=512, nhead=8, batch_first=True) for _ in range(n_layers)] + [
        ] + [nn.Linear(embed_dim, 512) for _ in range(n_layers)] + [
                nn.Linear(embed_dim, 512)
        ]
        self.net = torch.nn.Sequential(*component_list)

DeepSpeed初始化代码

tel_model = TelModel()
train_ds = RandomDataset(100)
train_loader = DataLoader(train_ds, batch_size=BATCH_SIZE)
trainer = L.Trainer(accelerator="gpu", devices=6, strategy="deepspeed_stage_3", precision=32)
trainer.fit(tel_model, train_loader)

运行命令

deepspeed lightning-deepspeed-tel.py

解决方案

1. 明确DeepSpeed Stage3的并行逻辑

DeepSpeed Stage3是ZeRO优化+流水线并行的组合,默认不会自动将nn.Sequential中的层拆分到多个GPU。要实现层级分布,需要手动划分模型阶段,让流水线并行机制识别并分配。

2. 手动拆分Sequential模型为多阶段

将大量全连接层按GPU数量拆分到不同的子模块中,让DeepSpeed能将每个子模块分配到对应GPU:

class TelModel(L.LightningModule):
    def __init__(self, num_gpus=6):
        super().__init__()
        embed_dim = 512
        n_layers = 18000
        layers_per_gpu = n_layers // num_gpus
        
        # 按GPU数量拆分模型为多个阶段
        self.stages = torch.nn.ModuleList()
        # 初始输入层
        self.stages.append(nn.Linear(512, embed_dim))
        
        # 拆分全连接层到各个阶段
        for gpu_idx in range(num_gpus):
            start = gpu_idx * layers_per_gpu
            # 处理最后一个GPU的剩余层
            end = start + layers_per_gpu if gpu_idx < num_gpus - 1 else n_layers
            stage_layers = [nn.Linear(embed_dim, 512) for _ in range(start, end)]
            self.stages.append(torch.nn.Sequential(*stage_layers))
        
        # 最终输出层
        self.stages.append(nn.Linear(embed_dim, 512))

    def forward(self, x):
        for stage in self.stages:
            x = stage(x)
        return x

3. 配置流水线并行参数

在Trainer中显式指定流水线并行的阶段数,或者通过DeepSpeed配置文件更精细地控制:

方式1:直接在Trainer中设置

trainer = L.Trainer(
    accelerator="gpu", 
    devices=6, 
    strategy="deepspeed_stage_3", 
    precision=32,
    pipeline_parallel_size=6  # 与GPU数量匹配
)

方式2:使用DeepSpeed配置文件(推荐,更灵活)

from pytorch_lightning.strategies import DeepSpeedStrategy

ds_config = {
    "train_batch_size": BATCH_SIZE * 6,  # 全局batch size
    "train_micro_batch_size_per_gpu": BATCH_SIZE,  # 单GPU的micro batch
    "pipeline_parallel": {
        "enabled": True,
        "num_stages": 6  # 流水线阶段数,对应GPU数量
    },
    "zero_optimization": {
        "stage": 3,
        "offload_param": {
            "device": "cpu"  # 开启参数CPU卸载,进一步降低显存占用
        }
    }
}

trainer = L.Trainer(
    accelerator="gpu", 
    devices=6, 
    strategy=DeepSpeedStrategy(config=ds_config), 
    precision=32
)

4. 关键注意事项

  • ZeRO Stage3主要优化显存使用,但不会自动做层拆分,流水线并行需要手动划分模型阶段。
  • 确保pipeline_parallel_size与实际使用的GPU数量一致,或者根据需求调整阶段数。
  • 开启ZeRO的参数卸载(offload_param)可以大幅降低单GPU的显存占用,尤其适合超大模型。

内容的提问来源于stack exchange,提问作者Romeo Kienzler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 05:50:18