环境部署

环境支持列表

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 registry.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: registry.baidubce.com/paddle-operator/demo-wide-and-deep:v1
  ps:
    replicas: 2
    template:
      spec:
        containers:
          - name: paddle
            image: registry.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: registry.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

https://cloud.baidu.com/product/cce.html

阿里云

ACK

https://help.aliyun.com/product/85222.html

华为云

CCE

https://www.huaweicloud.com/product/cce.html

更为方便的是使用百度提供的全功能 AI 开发平台 BML 来使用,详细的使用方式请参考 BML 文档

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

  • 检查超时设置是否过长