环境部署¶
环境支持列表¶
PaddlePaddle 分布式对不同系统和硬件的支持情况如下表所示,
| CPU | GPU | 昆仑芯 XPU | 海光 DCU | 昇腾 NPU | |
| Linux | PS/Collective | PS/Collective | PS/Collective | Collective | Collective | 
目前 Windows 只支持单机的 CPU 和 GPU,暂不支持分布式训练。
常用环境介绍¶
下面针对使用多台裸机使用分布式的场景提供指导,总体而言,
- 强烈推荐使用 docker 环境部署使用分布式训练,不建议在机器上直接安装使用 PaddlePaddle 
- 当机器数量多于 5 台且长期使用时,建议使用 Kubernetes 部署 或其他类似集群管理工具使用 
裸机及 Docker 化部署¶
paddle 环境安装¶
根据 安装 部分选择合适的 paddle 版本, 直接使用 pip 可以在环境中安装 PaddlePaddle, 例如
$ python -m pip install paddlepaddle-gpu==2.2.2.post112 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html
          或者在装有 docker 的环境中可以直接使用 PaddlePaddle 官方提供的镜像, 下载对应版本的镜像然后通过以下命令启动
$ docker run --name paddle -it --net=host -v $PWD:/paddle ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:2.2.2-gpu-cuda11.2-cudnn8 /bin/bash
          - 当使用 gpu 时请配置 nvidia docker runtime 或使用 nvidia-docker 启动容器,进入容器后使用 nvidia-smi 命令确认环境正确 
- 使用分布式时需要添加 --net=host 参数让容器使用主机网络以实现跨机建立连接 
安装后,运行以下命令
$ python -c "import paddle; paddle.utils.run_check()"
          确保输出结果符合预期以保证 paddle 环境安装正确。 至此,可以进行单机的代码开发和调试工作。
分布式启动¶
在多机中安装好环境,同步数据和代码,在任意节点上运行以下命令
$ python -m paddle.distributed.launch --nnodes=2 demo.py
          nnodes 为本次分布式任务的节点个数,这时会在看到如下输出
$ Copy the following command to other nodes to run.
$ --------------------------------------------------------------------------------
$ python -m paddle.distributed.launch --master 123.45.67.89:25880 --nnodes=2 demo.py
$ --------------------------------------------------------------------------------
          按照提示复制命令到其他所有节点即可启动分布式训练任务。
- --nnodes 为分布式任务的节点个数,默认为 1 即启动单机任务 
- --master 为分布式同步主节点,可以直接由用户设置,这是用户需要配置主节点的 ip 和任意可用端口 
更多 launch 启动参数和用法请参考 文档 或通过以下命令获得
$ python -m paddle.distributed.launch --help
          Kubernetes 部署¶
在 kubernetes 上部署分布式任务需要安装 paddle-operator 。 paddle-operator 通过添加自定义资源类型 (paddlejob) 以及部署 controller 和一系列 kubernetes 原生组件的方式实现简单定义即可运行 paddle 任务的需求。
目前支持运行 ParameterServer (PS) 和 Collective 两种分布式任务,当然也支持运行单节点任务。
paddle-operator 安装¶
安装 paddle-operator 需要有已经安装的 kubernetes (v1.8+) 集群和 kubectl (v1.8+) 工具。
本节所需配置文件和示例可以在 这里 找到, 可以通过 git clone 或者复制文件内容保存。
deploy
|-- examples
|   |-- resnet.yaml
|   |-- wide_and_deep.yaml
|   |-- wide_and_deep_podip.yaml
|   |-- wide_and_deep_service.yaml
|   `-- wide_and_deep_volcano.yaml
|-- v1
|   |-- crd.yaml
|   `-- operator.yaml
`-- v1beta1
    |-- crd.yaml
    `-- operator.yaml
          注意:kubernetes 1.15 及以下使用 v1beta1 目录,1.16 及以上使用目录 v1.
执行以下命令,
$ kubectl create -f https://raw.githubusercontent.com/PaddleFlow/paddle-operator/dev/deploy/v1/crd.yaml
          或者
$ kubectl create -f deploy/v1/crd.yaml
          注意:v1beta1 请根据报错信息添加 --validate=false 选项
通过以下命令查看是否成功,
$ kubectl get crd
NAME                                    CREATED AT
paddlejobs.batch.paddlepaddle.org       2021-02-08T07:43:24Z
          执行以下部署命令,
$ kubectl create -f https://raw.githubusercontent.com/PaddleFlow/paddle-operator/dev/deploy/v1/operator.yaml
          或者
$ kubectl create -f deploy/v1/operator.yaml
          通过以下命令查看部署结果和运行状态,
$ kubectl -n paddle-system get pods
NAME                                         READY   STATUS    RESTARTS   AGE
paddle-controller-manager-698dd7b855-n65jr   1/1     Running   0          1m
          通过查看 controller 日志以确保运行正常,
$ kubectl -n paddle-system logs paddle-controller-manager-698dd7b855-n65jr
          提交 demo 任务查看效果,
$ kubectl -n paddle-system create -f deploy/examples/wide_and_deep.yaml
          查看 paddlejob 任务状态, pdj 为 paddlejob 的缩写,
$ kubectl -n paddle-system get pdj
NAME                     STATUS      MODE   AGE
wide-ande-deep-service   Completed   PS     4m4s
          以上信息可以看出:训练任务已经正确完成,该任务为 ps 模式。 可通过 cleanPodPolicy 配置任务完成/失败后的 pod 删除策略,详见任务配置。
训练期间可以通过如下命令查看 pod 状态,
$ kubectl -n paddle-system get pods
          paddlejob 任务提交¶
在上述安装过程中,我们使用了 wide-and-deep 的例子作为提交任务演示,本节详细描述任务配置和提交流程供用户参考提交自己的任务。
示例 wide and deep
本示例为 PS 模式,使用 cpu 进行训练,需要配置 ps 和 worker。
准备配置文件,
$ cat demo-wide-and-deep.yaml
apiVersion: batch.paddlepaddle.org/v1
kind: PaddleJob
metadata:
  name: wide-ande-deep
spec:
  withGloo: 1
  intranet: PodIP
  cleanPodPolicy: OnCompletion
  worker:
    replicas: 2
    template:
      spec:
        containers:
          - name: paddle
            image: ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddle-operator/demo-wide-and-deep:v1
  ps:
    replicas: 2
    template:
      spec:
        containers:
          - name: paddle
            image: ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddle-operator/demo-wide-and-deep:v1
          说明:
- 提交命名需要唯一,如果存在冲突请先删除原 paddlejob 确保已经删除再提交; 
- ps 模式时需要同时配置 ps 和 worker,collective 模式时只需要配置 worker 即可; 
- withGloo 可选配置为 0 不启用, 1 只启动 worker 端, 2 启动全部(worker 端和 Server 端), 建议设置 1; 
- cleanPodPolicy 可选配置为 Always/Never/OnFailure/OnCompletion,表示任务终止(失败或成功)时,是否删除 pod,调试时建议 Never,生产时建议 OnCompletion; 
- intranet 可选配置为 Service/PodIP,表示 pod 间的通信方式,用户可以不配置, 默认使用 PodIP; 
- ps 和 worker 的内容为 podTemplateSpec,用户可根据需要遵从 kubernetes 规范添加更多内容, 如 GPU 的配置. 
提交任务: 使用 kubectl 提交 yaml 配置文件以创建任务,
$ kubectl -n paddle-system create -f demo-wide-and-deep.yaml
          示例 resnet¶
本示例为 Collective 模式,使用 gpu 进行训练,只需要配置 worker,worker 配置中需要声明使用的 gpu 信息。
准备配置文件,
$ cat resnet.yaml
apiVersion: batch.paddlepaddle.org/v1
kind: PaddleJob
metadata:
  name: resnet
spec:
  cleanPodPolicy: Never
  worker:
    replicas: 2
    template:
      spec:
        containers:
          - name: paddle
            image: ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddle-operator/demo-resnet:v1
            command:
            - python
            args:
            - "-m"
            - "paddle.distributed.launch"
            - "train_fleet.py"
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
            resources:
              limits:
                nvidia.com/gpu: 1
        volumes:
        - name: dshm
          emptyDir:
            medium: Memory
          注意:
- 这里需要添加 shared memory 挂载以防止缓存出错; 
- 本示例采用内置 flower 数据集,程序启动后会进行下载,根据网络环境可能等待较长时间。 
提交任务: 使用 kubectl 提交 yaml 配置文件以创建任务,
$ kubectl -n paddle-system create -f resnet.yaml
          卸载¶
通过以下命令卸载部署的组件,
$ kubectl delete -f deploy/v1/crd.yaml -f deploy/v1/operator.yaml
          注意:重新安装时,建议先卸载再安装
公有云和私有云部署¶
在公有云上运行 PaddlePaddle 分布式建议通过选购容器引擎服务的方式,各大云厂商都推出了基于标准 kubernetes 的云产品,然后根据上节中的教程安装使用即可。
| 云厂商 | 容器引擎 | 链接 | 
| 百度云 | CCE | |
| 阿里云 | ACK | |
| 华为云 | CCE | 
FAQ¶
怎么知道分布式启动正确?¶
典型的启动日志如下所示
LAUNCH INFO 2022-05-18 11:53:09,773 -----------  Configuration  ----------------------
LAUNCH INFO 2022-05-18 11:53:09,773 devices: 6,7
LAUNCH INFO 2022-05-18 11:53:09,773 elastic_level: -1
LAUNCH INFO 2022-05-18 11:53:09,773 elastic_timeout: 30
LAUNCH INFO 2022-05-18 11:53:09,773 gloo_port: 6767
LAUNCH INFO 2022-05-18 11:53:09,773 host: None
LAUNCH INFO 2022-05-18 11:53:09,773 job_id: default
LAUNCH INFO 2022-05-18 11:53:09,773 legacy: False
LAUNCH INFO 2022-05-18 11:53:09,773 log_dir: log
LAUNCH INFO 2022-05-18 11:53:09,773 log_level: INFO
LAUNCH INFO 2022-05-18 11:53:09,774 master: None
LAUNCH INFO 2022-05-18 11:53:09,774 max_restart: 3
LAUNCH INFO 2022-05-18 11:53:09,774 nnodes: 1
LAUNCH INFO 2022-05-18 11:53:09,774 nproc_per_node: None
LAUNCH INFO 2022-05-18 11:53:09,774 rank: -1
LAUNCH INFO 2022-05-18 11:53:09,774 run_mode: collective
LAUNCH INFO 2022-05-18 11:53:09,774 server_num: None
LAUNCH INFO 2022-05-18 11:53:09,774 servers:
LAUNCH INFO 2022-05-18 11:53:09,774 trainer_num: None
LAUNCH INFO 2022-05-18 11:53:09,774 trainers:
LAUNCH INFO 2022-05-18 11:53:09,774 training_script: demo.py
LAUNCH INFO 2022-05-18 11:53:09,774 training_script_args: []
LAUNCH INFO 2022-05-18 11:53:09,774 with_gloo: 0
LAUNCH INFO 2022-05-18 11:53:09,774 --------------------------------------------------
LAUNCH INFO 2022-05-18 11:53:09,783 Job: default, mode collective, replicas 1[1:1], elastic False
LAUNCH INFO 2022-05-18 11:53:09,784 Run Pod: gistdo, replicas 2, status ready
LAUNCH INFO 2022-05-18 11:53:09,806 Watching Pod: gistdo, replicas 2, status running
          可以通过如下信息确认符合预期:
- 检查 launch 参数是否生效, 参考 launch API 文档设置各个参数 
- Job 默认为 default,当环境共用时,为避免冲突,请设置单独的 job_id 参数以区别 
- Job replicas 对应节点数,3[2:4] 表示当前 3 节点,允许最少 2 节点,最多 4 节点,非弹性任务三者一致 
- Pod 为逻辑节点,可以在一个物理节点上部署多个逻辑节点模拟分布式,Pod name 为 hash,和日志对应 
- Pod replicas 即节点上的进程数,在 GPU 训练时,一张卡对应一个进程 
- 当 launch 日志显示 status running 即表示分布式运行已正确启动,后续默认输出 0 号进程的日志 
GPU 分布式不生效? 节点数不对?¶
在 GPU 训练时,一张卡对应一个进程, 每个节点(Pod)分配到的卡数即 Pod replicas,确认显示的数量是否符合预期,如果不符合预期请检查遗下设置:
- 首先使用环境中使用 nvidia-smi 命令查看环境中的卡是否正常 
- 检查 CUDA_VISIBLE_DEVICES 设置,卡必须可见才可用 
- 检查 --devices 设置,该设置为卡号的绝对 index 
当检查设置无误后可通过设置 --log_level 打印更多日志以排查,当任务启动后,可以查看日志文件查看节点 ip 信息,然后检查机器连通性。
为什么弹性不生效?¶
弹性使用需要满足以下条件:
- 使用 etcd 作为 master 
- 任务需要使用唯一 id,即设置 job_id 
- 设置 nnodes 需要设置范围,例如 2:4 
- 检查超时设置是否过长