分布式训练
约3分钟
分布式训练
ESPnet2 提供多种数据并行分布式训练方式。
| DP/DDP | 单机/多机 | 选项 | |
|---|---|---|---|
| Multi-processing with single host | DistributedDataParallel | Single | --ngpu N-GPU --multiprocessing_distributed true |
| Multi-threading with single host | DataParallel | Single | --ngpu N-GPU --multiprocessing_distributed false |
Multi-processing with N-HOST jobs with N-GPU for each host (=N-HOSTxN-GPU nodes) | DistributedDataParallel | Multi | --dist_world_size N-HOST --ngpu N-GPU --multiprocessing_distributed true |
Multi-threading with N-HOST jobs with N-GPU for each host (=N-HOSTxN-GPU nodes) | DistributedDataParallel | Multi | --dist_world_size N-HOST --ngpu N-GPU --multiprocessing_distributed false |
N-NODE jobs with 1-GPU for each node | DistributedDataParallel | Single/Multi | --dist_world_size N-NODE --ngpu 1 |
示例
注意:ESPnet2在多GPU训练时的批次大小行为与ESPnet1不同。在ESPnet2中,无论使用多少GPU,总批次大小都不会改变。因此,如果增加GPU数量,您需要手动增加批次大小。更多信息请参阅此文档。
4GPU单节点分布式模式
% python -m espnet2.bin.asr_train --ngpu 4 --multiprocessing_distributed true您可以按以下方式禁用分布式模式并切换到基于线程的数据并行:
% python -m espnet2.bin.asr_train --ngpu 4 --multiprocessing_distributed false如果在分布式模式下遇到错误,请在报告问题前尝试单GPU模式或使用--multiprocessing_distributed false参数的多GPU模式。
启用分片训练
我们支持由fairscale提供的分片训练
% python -m espnet2.bin.asr_train --ngpu 4 --multiprocessing_distributed true --sharded_ddp true请注意,fairscale的其他功能目前暂不支持。
每个主机2个主机和2个GPU的多进程分布式模式
请注意,多进程分布式模式假设每个节点具有相同数量的GPU。
(host1) % python -m espnet2.bin.asr_train \
--multiprocessing_distributed true \
--ngpu 2 \
--dist_rank 0 \
--dist_world_size 2 \
--dist_master_addr host1 \
--dist_master_port <any-free-port>
(host2) % python -m espnet2.bin.asr_train \
--multiprocessing_distributed true \
--ngpu 2 \
--dist_rank 1 \
--dist_world_size 2 \
--dist_master_addr host1 \
--dist_master_port <any-free-port>RANK和WORLD_SIZE
--dist_rank 和 --dist_world_size 分别表示MPI中的RANK和WORLD_SIZE;即它们分别表示每个进程的ID和进程总数。这些参数也可以通过环境变量${RANK}和${WORLD_SIZE}来指定。
关于初始化方法
See: https://pytorch.org/docs/stable/distributed.html#tcp-initialization
有两种初始化方法,这些方法在所有示例中可以互换使用。
TCP初始化
# 以下三种方式是等效的: --dist_master_addr <rank0-host> --dist_master_port <any-free-port> --dist_init_method "tcp://: export MASTER_ADDR=<rank0-host> MASTER_PORT=<any-free-port>" 共享文件系统初始化
--dist_init_method "file:///nfs/some/where/filename"如果之前的文件已存在,此初始化可能会失败。建议使用随机文件名以避免重复使用。例如:
--dist_init_method "file://$(pwd)/.dist_init_$(openssl rand -base64 12)"
分别拥有2块GPU和1块GPU的2台主机
(host1) % python -m espnet2.bin.asr_train \
--ngpu 1 \
--multiprocessing_distributed false \
--dist_rank 0 \
--dist_world_size 3 \
--dist_master_addr host1 \
--dist_master_port <any-free-port>
(host1) % python -m espnet2.bin.asr_train \
--ngpu 1 \
--multiprocessing_distributed false \
--dist_rank 1 \
--dist_world_size 3 \
--dist_master_addr host1 \
--dist_master_port <any-free-port>
(host2) % python -m espnet2.bin.asr_train \
--ngpu 1 \
--multiprocessing_distributed false \
--dist_rank 2 \
--dist_world_size 3 \
--dist_master_addr host1 \
--dist_master_port <any-free-port>每个节点使用2台主机和2个GPU,通过Slurm实现多进程分布式
% srun -c2 -N2 --gres gpu:2 \
python -m espnet2.bin.asr_train --ngpu 2 --multiprocessing_distributed true \
--dist_launcher slurm \
--dist_init_method "file://$(pwd)/.dist_init_$(openssl rand -base64 12)"在这种情况下,我推荐使用共享文件初始化方式,因为主机信息将在提交作业后确定,因此我们无法提前获知空闲端口号。
使用Slurm在3个节点上部署5个GPU
(未经测试)
% srun -n5 -N3 --gpus-per-task 1 \
python -m espnet2.bin.asr_train --ngpu 1 --multiprocessing_distributed false \
--dist_launcher slurm \
--dist_init_method "file://$(pwd)/.dist_init_$(openssl rand -base64 12)"每个节点使用2台主机和2个GPU,通过MPI实现多进程分布式
% mpirun -np 2 -host host1,host2 \
python -m espnet2.bin.asr_train --ngpu 2 --multiprocessing_distributed true \
--dist_launcher mpi \
--dist_init_method "file://$(pwd)/.dist_init_$(openssl rand -base64 12)"espnet2.bin.launch
即将推出...
以太网环境下NCCL故障排查指南
NCCL WARN Connect to 192.168.1.51<51890> failed : No route to host- 原因:防火墙?
- 需要释放所有端口吗?
NCCL INFO Call to connect returned Connection refused, retrying- 原因:检测到NIC,但连接被拒绝?
- 设置
NCCL_SOCKET_IFNAME=
NCCL WARN Bootstrap : no socket interface found- 原因:未找到任何网络接口卡。(可能是NCCL_SOCKET_IFNAME设置不正确)
- 设置
NCCL_SOCKET_IFNAME=。
NCCL WARN peer mapping resources exhausted- ???
- https://devtalk.nvidia.com/default/topic/970010/cuda-programming-and-performance/cuda-peer-resources-error-when-running-on-more-than-8-k80s-aws-p2-16xlarge-/post/4994583/#4994583
NCCL_SOCKET_IFNAME的使用规则
See: https://docs.nvidia.com/deeplearning/sdk/nccl-developer-guide/docs/env.html
- 默认值为
NCCL_SOCKET_IFNAME=^lo,docker。 - 支持两种语法:白名单或黑名单
- White list e.g.:
NCCL_SOCKET_IFNAME=eth,em- 只需指定前缀即可,无需设置为
eth0。
- 只需指定前缀即可,无需设置为
- 黑名单示例:
^virbr,lo,docker。 - If multiple network interfaces are found in your environment, the first is selected.
- 你可以通过例如
ifconfig来检查你的环境。https://www.cyberciti.biz/faq/linux-list-network-interfaces-names-command/ - 请注意,
lo通常是第一个,因此必须过滤lo。
- 你可以通过例如
针对非虚拟环境的推荐设置
NCCL_SOCKET_IFNAME=en,eth,em,bond- 或者,
NCCL_SOCKET_IFNAME=^lo,docker,virbr,vmnet,vboxnet,wl,ww,ppp
| 网络接口名称的前缀 | 备注 |
|---|---|
| lo | 回环接口。 |
| eth | 以太网。经典网络类型。 |
| em | 以太网。戴尔机器? |
| en | 以太网(用于较新的Linux系统,例如CentOS7) |
| wlan | 无线网络 |
| wl | 无线局域网(用于最新版Linux系统) |
| ww | 无线广域网(用于最新版Linux系统) |
| ib | 基于InfiniBand的IP协议 |
| bond | 多网卡绑定 |
| virbr | 虚拟网桥 |
| docker,vmnet,vboxnet | 虚拟机 |
| ppp | 点对点 |
