DeepSpeed是一个由微软开发的分布式训练工具,它通过ZeRO技术优化内存占用,支持更大规模的模型训练。ZeRO通过分片模型参数、优化器状态和梯度来减少显存需求,分为多个阶段,如Stage1、2和3,每个阶段逐步增加内存优化程度。混合精度训练结合FP16和FP32,降低显存使用。DeepSpeed的核心在于,GPU显存不够,CPU内存来凑。
DeepSpeed要在Linux系统上才能正常使用,所以下面的操作都是在Ubuntu系统上操作(属于Linux系统)。
安装NCCL
NCCL是什么?
NCCL(NVIDIA Collective Communications Library)是一个由 NVIDIA 开发的库,它提供了针对 NVIDIA GPU 的高性能集体通信原语。这些原语包括广播(broadcast)、规约(reduce)、全规约(all-reduce)、扫描(scan)等,这些都是并行计算中常用的操作。
NCCL 主要用于多 GPU 和多节点(即分布式)环境中的深度学习训练,以加速跨多个 GPU 或多个计算节点的数据交换。在深度学习训练过程中,特别是在使用数据并行和模型并行策略时,NCCL 可以显著提高通信效率,从而加速训练过程。
在安装之前,你可以检查系统上是否已经安装了 NCCL。你可以通过以下命令来检查:
$ dpkg -l | grep nccl
或者在 Red Hat 系统上:
$ rpm -qa | grep nccl
如果没有安装,下载安装
NCCL下载页面:
https://developer.nvidia.com/nccl/nccl-download
这里选Local Installer
选:Local installer for Ubuntu 22.04
安装
安装说明文档页面:
https://docs.nvidia.com/deeplearning/nccl/install-guide/index.html
$ sudo dpkg -i /home/heyiqiu/下载/nccl-local-repo-ubuntu2204-2.22.3-cuda12.2_1.0-1_amd64.deb
$ sudo cp /var/nccl-local-repo-ubuntu2204-2.22.3-cuda12.2/nccl-local-C4F45A8B-keyring.gpg /usr/share/keyrings/
$ sudo apt update
$ sudo apt install libnccl2=2.22.3-1+cuda12.2 libnccl-dev=2.22.3-1+cuda12.2
验证是否安装成功:
import torch
print("nccl version: ",torch.cuda.nccl.version())
如果正常打印NCCL版本,说明安装成功
在python中安装DeepSpeed
进入并激活python虚拟环境,然后安装:
$ pip install deepspeed
使用
在使用 torch.distributed 时,通常需要设置以下几个环境变量:MASTER_ADDR: 主节点的地址。MASTER_PORT: 主节点的端口。WORLD_SIZE: 参与训练的总进程数。RANK: 当前进程的排名(从0开始)。下图为Pycharm中运行配置:
在启动分布式训练之前设置这些环境变量。例如,如果你有4个进程参与训练,可以这样设置:
MASTER_ADDR="127.0.0.1"
MASTER_PORT="29500"
WORLD_SIZE=4
RANK=0 # 对于每个进程,RANK 应该不同
然后启动你的训练脚本。如果你使用的是 torch.distributed.launch 或其他启动工具,这些环境变量通常会自动设置。如果手动启动,确保每个进程都有正确的 RANK 和 WORLD_SIZE。
例如,使用 torch.distributed.launch 启动脚本时,可以这样:
$ python -m torch.distributed.launch --nproc_per_node=4 --master_port=29500 your_script.py
这样 torch.distributed.launch 会自动设置这些环境变量。
确保在每个参与训练的节点上都正确设置了这些环境变量。
DeepSpeed中配置多个服务器多个GPU
DeepSpeed 是一个用于加速大规模模型训练的深度学习优化库,它支持在多个服务器上进行分布式训练。要在多个服务器上配置 DeepSpeed,需要进行以下步骤:
在DeepSpeed的分布式训练中,通常只需要在一台服务器上运行启动脚本。这台服务器通常被称为主节点(master node)或主服务器(master server)。主节点负责协调和管理整个分布式训练过程。DeepSpeed中可能有两个配置文件, 一个是.json文件配置超参数,一个是服务器与GPU数量文本文件,前一个也可以在启动.sh脚本中配置或在运行配置中通过传参方式配置。后一个可传可不传。若不传,只能是在当前服务器上进行训练。
以下是具体步骤:
1. 主节点运行启动脚本:
- 在主节点上运行启动脚本(如 `launch.sh`)。这个脚本会使用DeepSpeed的分布式启动工具(如 `deepspeed` 命令)来启动训练过程,并自动在所有参与的服务器上启动相应的进程。
2. 配置文件和主机列表:
- 确保启动脚本中指定了正确的配置文件(如 `deepspeed_config.json`)和主机列表文件(如 `hostfile`)。主机列表文件中包含了所有参与训练的服务器的IP地址和可用GPU数量。
deepspeed_config.json如下:
{
"train_batch_size": 4,
"steps_per_print": 2000,
"optimizer": {
"type": "Adam",
"params": {
"lr": 0.001,
"betas": [
0.8,
0.999
],
"eps": 1e-8,
"weight_decay": 3e-7
}
},
"scheduler": {
"type": "WarmupLR",
"params": {
"warmup_min_lr": 0,
"warmup_max_lr": 0.001,
"warmup_num_steps": 1000
}
},
"wall_clock_breakdown": false
}
3. SSH无密码登录:
- 确保主节点可以通过SSH无密码登录到所有其他服务器。这样,主节点可以自动在其他服务器上启动训练进程,而无需手动干预。
4. 示例启动脚本:
- 以下是一个示例启动脚本 `launch.sh`:
#!/bin/bash
deepspeed --hostfile hostfile your_script.py --deepspeed_config deepspeed_config.json
- 其中 `hostfile` 是一个文本文件,包含所有服务器的IP地址和可用GPU数量。例如:
server1 slots=4
server2 slots=4
5. 运行启动脚本:
- 在主节点上运行启动脚本:
$ ./launch.sh
通过这种方式,主节点会自动在所有参与的服务器上启动训练进程,并协调它们之间的通信和数据同步。其他服务器(从节点)会根据主节点的指令执行相应的训练任务。
总结来说,只需要在主节点上运行启动脚本,它会自动在所有其他服务器上启动相应的训练进程。
确定主服务器
在DeepSpeed的分布式训练中,主服务器(也称为主节点或master node)通常是启动分布式训练过程的服务器。主服务器负责协调和管理整个分布式训练集群。确定主服务器的方法如下:
1. 手动指定:
- 在启动脚本中,你可以手动指定哪台服务器作为主服务器。通常,你会在主服务器上运行启动脚本,并在脚本中指定主机列表文件(如 `hostfile`)。
2. 主机列表文件:
- 主机列表文件(如 `hostfile`)中列出了所有参与训练的服务器的IP地址和可用GPU数量。通常,列表中的第一台服务器会被默认作为主服务器。例如:
server1 slots=4
server2 slots=4
server3 slots=4
- 在这个例子中,`server1` 会被默认作为主服务器。
3. 启动脚本示例:
- 以下是一个示例启动脚本 `launch.sh`,它会在主服务器上运行:
#!/bin/bash
deepspeed --hostfile hostfile your_script.py --deepspeed_config deepspeed_config.json
- 在这个脚本中,`hostfile` 文件的第一行对应的服务器会被作为主服务器。
4. 自动选择:
- DeepSpeed的分布式启动工具(如 `deepspeed` 命令)会自动选择主机列表文件中的第一台服务器作为主服务器。因此,确保主机列表文件中的第一台服务器是你希望作为主服务器的机器。
5. 环境变量:
- 你也可以通过环境变量来指定主服务器。例如,可以使用 `MASTER_ADDR` 和 `MASTER_PORT` 环境变量来指定主服务器的IP地址和端口。
$ export MASTER_ADDR=server1
$ export MASTER_PORT=29500
通过以上方法,可以确定和指定主服务器。通常情况下,只需要在主服务器上运行启动脚本,并确保主机列表文件中的第一台服务器是你希望作为主服务器的机器。
DeepSpeed训练、推理、压缩实例
代码地址:https://github.com/microsoft/DeepSpeedExamples
训练:
代码位置:
DeepSpeedExamples-master/applications/DeepSpeed-Chat
在python虚拟环境安装需要的依赖包,在Pycharm中解决其他编译报错问题。
如果要查询GPU的型号,命令行执行nvidia-smi,查询到GPU的型号是Quadro RTX 5000,Quadro RTX 5000是基于NVIDIA的Turing架构,其对应的CUDA架构是7.5。
永久设置TORCH_CUDA_ARCH_LIST 变量
$ echo 'export TORCH_CUDA_ARCH_LIST="7.5"' >> ~/.bashrc
$ source ~/.bashrc
MAX_JOBS环境变量应该如何设置
`MAX_JOBS`环境变量用于指定在编译过程中允许的最大并行任务数。设置这个变量可以帮助你控制编译时的CPU和内存资源使用,避免因并行任务过多导致系统资源耗尽。
以下是如何设置`MAX_JOBS`环境变量的方法:
在Linux上设置
1. 临时设置(仅对当前终端会话有效):
$ export MAX_JOBS=4
2. 永久设置(对所有终端会话有效):
可以将上述命令添加到你的Shell配置文件中,例如`~/.bashrc`、`~/.zshrc`或`~/.profile`:
$ echo 'export MAX_JOBS=4' >> ~/.bashrc
$ source ~/.bashrc
在Pycharm中运行时候,如果发现设置的环境变量没有效果,可以在运行配置中的的Environment variables那里设置,多个环境变量之间胜;分隔。
设置建议
-CPU核心数:通常建议将`MAX_JOBS`设置为你的CPU核心数。例如,如果CPU有8个核心,可以设置`MAX_JOBS=8`。
-内存限制:如果系统内存有限,可以适当减少`MAX_JOBS`的值,以避免内存不足导致编译失败。
-编译速度和资源平衡:根据系统资源和编译需求,调整`MAX_JOBS`的值,以达到最佳的编译速度和资源使用平衡。
例如,如果系统有16GB内存和8个CPU核心,但想限制内存使用,可以设置`MAX_JOBS=4`或`MAX_JOBS=6`。
通过合理设置`MAX_JOBS`环境变量,可以更好地控制编译过程中的资源使用,避免系统过载,并提高编译效率。
训练过程中检查内存使用情况:
$ free -m
可以使用 -a 选项来查看当前 shell 会话的所有资源限制:
$ ulimit -a
训练:
运行DeepSpeedExamples-master/training/cifar/cifar10_deepspeed.py,可用DeepSpeed启动训练
推理:
可以运行/home/heyiqiu/PycharmProjects/DeepSpeedExamples-master/training/stable_diffusion/inf_txt2img_loop.py进行推理(用下载的模型)
stable_diffusion模型生成的图片:
模型压缩
可运行DeepSpeedExamples-master/compression/cifar/run_compress.sh,在训练模型后,对保存的模型朝廷压缩
上面net.pkl是训练保存的模型,clean_net.pkl是压缩后保存的模型
如果安装了CUDA但运行中报类似下面问题:
kages/deepspeed/ops/csrc/adam/cpu_adam_impl.cpp -o cpu_adam_impl.o
[3/3] c++ cpu_adam.o cpu_adam_impl.o -shared -lcurand -L/opt/venv/python39venv/lib/python3.9/site-packages/torch/lib -lc10 -ltorch_cpu -ltorch -ltorch_python -o cpu_adam.so
FAILED: cpu_adam.so
c++ cpu_adam.o cpu_adam_impl.o -shared -lcurand -L/opt/venv/python39venv/lib/python3.9/site-packages/torch/lib -lc10 -ltorch_cpu -ltorch -ltorch_python -o cpu_adam.so
/usr/bin/ld: 找不到 -lcurand: 没有那个文件或目录
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
可以用下面方法解决:
$ sudo cp /usr/local/cuda/lib64/libcurand.so /usr/lib64
$ sudo cp /usr/local/cuda/lib64/libcurand.so.10 /usr/lib64
$ sudo cp /usr/local/cuda/lib64/libcurand.so.10.3.3.141 /usr/lib64