llamafactory用多卡4090服务器,训练qwen14B大模型时报错GPU显存不足oom(out of memory),已解决

(llamafactory用多张4090卡,训练qwen14B大模型时oom(out of memory)报错,torch.OutOfMemoryError:CUDA out of memory,Tried to allocate 136MB,GPU 5 has a total capacity of 23.64GB which 16.56MB is free,已解决)

1.问题描述

通过export CUDA_VISIBLE_DVICES=0,1,2,3,4,5,6,7指定使用8张显卡,训练qwen2.5-7B大模型时正常,但训练qwen2.5-14B,qwen2.5-32B模型时报错,torch.OutOfMemoryError:CUDA out of memory,Tried to allocate 136MB,GPU 5 has a total capacity of 23.64GB which 16.56MB is free 。
大概意思就是说GPU显存不足,很明显不符合实际,我的8张4090卡总显存是8*24GB,理论上14B的大模型肯定能跑起来。

linux服务器环境:
系统:Ubuntu22;
硬件:本机512G内存,8张4090显卡;
python:3.10版本;
llamafactory版本:0.9.1.dev0;
cuda版本:12.4版本;
pytorch版本:2.4.0+cuda121(GPU);
大模型:qwen2.5(7B,14B,32B,72B)Instruct版;
在这里插入图片描述

2.解决方案

  1. 减小大模型训练参数: 查一些帖子说是大模型训练参数太大,尝试减小数据量,减小步数,fp16位精度等,依旧不行,未解决,说明不是模型训练参数太大;
  2. 多余的内存分配给CPU: 从上面的oom报错原因我们可以看出,给GPU分配了136M内存,但实际GPU只剩16M了,导致oom报错,使用ZeRO-offload 技术通过一系列策略,将原本在GPU上处理的一部分数据和任务转移到CPU上,以此来降低GPU内存的占用,解决oom报错问题。
    **具体解决方案:**在LLaMA-Factory目录下新建一个run_train_bash.sh新件,具体目录如下图:
    在这里插入图片描述
    在run_train_bash.sh文件中,设置参数如下:
    model_name_or_path和output_dir 改成你自己的本地大模型和输出路径就行;
    src/train.py 取决于你src目录下的训练启动文件名,这个是llamafactory自带的;
    CUDA_VISIBLE_DEVICES:看你有几张卡,需要用几张卡,我的是8张卡;
    其它都是训练参数,根据实际需要修改。最重要的是deepspeed ds_config_zero3.json这行,
    这个是qwen官网给的。deepspeed 库可以用pip install deepspeed 安装一下。

run_train_bash.sh文件中内容:

CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 accelerate launch  src/train.py \
    --deepspeed ds_config_zero3.json \
    --stage sft \
    --do_train True \
    --model_name_or_path /home/admin1/Qwen2.5
### LlamaFactory GPU分布式训练配置教程 对于希望利用GPU 提升训练效率的研究者而言,在 LlamaFactory 项目中实现这一点可以通过采用 `torch.nn.DataParallel` 或更推荐的 `torch.distributed.launch` 来达成[^1]。 #### 使用 DataParallel 进行简单并行化处理 当选择较为简单的方案,可以考虑使用 PyTorch 自带的 `DataParallel` 类来快速启动一个 GPU训练环境。然而需要注意的是,这种方法虽然易于设置却可能不是最高效的解决方案,因为它会在每个批次结束收集所有设备上的梯度再更新参数,容易造成性能瓶颈[^3]。 ```python from torch import nn model = ModelLoader.load_model() # 加载模型实例来自定义函数或类 parallel_model = nn.DataParallel(model).cuda() ``` #### 推荐做法:Distributed 数据并行模式 为了获得更好的扩展性和更高的计算资源利用率,建议使用基于进程组(Process Group)的方式来进行分布式训练。这种方式允许每一块显运行独立的 Python 进程,并通过消息传递接口(MPI)或其他通信库同步状态。具体操作如下: - **Step 1**: 修改命令行指令以适应新的启动方式。假设已经按照官方指南安装好了必要的依赖项,则可以在终端执行下面这条命令开启服务端口监听以及指定参与运算的具体 GPU 编号列表: ```bash CUDA_VISIBLE_DEVICES="0,1,2,3" python -m torch.distributed.launch --nproc_per_node=4 train.py ``` 这里 `-m torch.distributed.launch` 是用来发起个子进程中每一个都将负责一部分工作负载;而 `--nproc_per_node=4` 参数指定了在同一节点内部署四个进程分别对应四块不同的 GPU 设备。 - **Step 2**: 对于实际编写代码部分来说,需要引入额外的支持以便能够正确初始化这些分布式的组件并且调整原有程序逻辑使之兼容新架构下的运作机制。以下是简化后的模板片段展示了如何改造原有的训练循环使其支持跨机器间的协作学习过程: ```python import os import torch import torch.distributed as dist from torch.nn.parallel import DistributedDataParallel as DDP def setup(rank, world_size): """ 初始化分布式环境 """ os.environ['MASTER_ADDR'] = 'localhost' os.environ['MASTER_PORT'] = '12355' # initialize the process group dist.init_process_group("nccl", rank=rank, world_size=world_size) def cleanup(): """ 清理分布式环境 """ dist.destroy_process_group() class Trainer(object): def __init__(self, model, device_id=None): self.model = model.to(device_id) self.ddp_model = DDP(self.model) def train_step(self, batch_data): output = self.ddp_model(batch_data) loss = compute_loss(output) optimizer.zero_grad() loss.backward() optimizer.step() if __name__ == "__main__": local_rank = int(os.getenv('LOCAL_RANK', '0')) setup(local_rank, world_size=4) # 假设有4个GPU try: trainer = Trainer(ModelLoader.load_model(), f'cuda:{local_rank}') dataset_loader = DataLoader(DataWorker.prepare_dataset()) for epoch in range(num_epochs): for data_batch in dataset_loader: trainer.train_step(data_batch) finally: cleanup() ``` 上述代码段实现了基本的功能需求——即让各个 worker 能够协同作业而不至于因为空闲等待而导致整体进度受阻。值得注意的地方在于,DDP 构造器会自动管理不同 ranks 上面的数据切分与聚合任务,从而有效减少了不必要的通讯开销提升了吞吐量表现[^2]。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值