深度学习 AMI
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

分布式 GPU 训练

本部分针对在多节点 GPU 集群上运行分布式训练。

有关 AWS Deep Learning Containers的完整列表,请参阅Deep Learning Containers映像

在 EKS 上运行分布式训练将使用 Kubeflow。Kubeflow 项目致力于简单、便携且可扩展地在 Kubernetes 上部署机器学习 (ML) 工作流。

通过安装 Kubeflow 设置您的集群进行分布式训练

  1. 安装 Kubeflow。

    $ export KUBEFLOW_VERSION=0.4.1 $ curl https://raw.githubusercontent.com/kubeflow/kubeflow/v${KUBEFLOW_VERSION}/scripts/download.sh | bash
  2. 使用 Kubeflow 程序包时,您将很快遇到 Github API 限制。您需要创建一个 Github 令牌并按以下方式导出它。您无需选择任何范围。

    $ export GITHUB_TOKEN=<token>

MXNet

本教程将指导您在多节点 GPU 集群上使用 MXNet 进行分布式训练。它使用 Parameter Server。要在 EKS 上运行 MXNet 分布式训练,我们将使用名为 MXJobKubernetes MXNet-operator。它将提供一种自定义资源,可让您轻松在 Kubernetes 上运行分布式或非分布式 MXNet 任务(训练和调整)。

在您的 Kubeflow 部署中添加 MXNet 支持

  1. 设置命名空间。

    $ NAMESPACE=kubeflow-dist-train-mx; kubectl --kubeconfig=/home/ubuntu/.kube/eksctl/clusters/training-gpu-1 create namespace ${NAMESPACE}
  2. 设置应用程序名称并将其初始化。

    $ APP_NAME=kubeflow-mx-ps; ks init ${APP_NAME}; cd ${APP_NAME}
  3. 将默认环境使用的命名空间更改为 ${NAMESPACE}

    $ ks env set default --namespace ${NAMESPACE}
  4. 安装用于 kubeflow 的 MXNet-operator。这是使用参数服务器运行 MXNet 分布式训练所需的。

    $ ks registry add kubeflow github.com/kubeflow/kubeflow/tree/${KUBEFLOW_VERSION}/kubeflow $ ks pkg install kubeflow/mxnet-job
  5. 生成与 Kubernetes 兼容的 jsonnet 组件清单文件。

    $ ks generate mxnet-operator mxnet-operator
  6. 应用配置设置。

    $ ks apply default -c mxnet-operator
  7. 使用自定义资源定义 (CRD) 将使用户能够创建和管理 MX 任务,就像 builtin K8s 资源一样。验证是否已安装 MXNet 自定义资源。

    $ kubectl get crd

    该输出应包含 mxjobs.kubeflow.org

使用参数服务器运行 MNIST 分布式训练示例

您的第一个任务是根据可用的集群配置和要运行的任务为您的任务创建一个 pod 文件 (mx_job_dist.yaml)。您需要指定 3 个任务模式:计划程序、服务器和工作线程。您可以指定要使用字段副本生成的 pod 的数量。

  • 计划程序:只有一个计划程序。计划程序的作用是设置集群。这包括等待每个节点已启动以及节点正在侦听哪个端口的消息。然后,计划程序向所有进程通知集群中的每个其他节点,以便它们可以相互通信。

  • 服务器:可能具有多个服务器,它们存储模型的参数并与工作线程进行通信。服务器可能与工作线程进程位于同一位置,也可能位于不同的位置。

  • 工作线程:工作线程节点实际对一批训练样本进行训练。在处理每个批次之前,工作线程从服务器中提取权重。在每个批次后,工作线程还会将梯度发送到服务器。根据模型训练工作负载,在同一计算机上运行多个工作线程可能并不是一个好主意。

  • 提供要用于字段映像的容器映像。

  • 您可以从“Always”、“OnFailure”和“Never”之一提供 restartPolicy。它确定 pod 是否在其退出时重新启动。

  • 提供要用于字段映像的容器映像。

  1. 根据之前的讨论,您将根据您的要求修改以下代码块并将其保存在名为 mx_job_dist.yaml 的文件中。

    apiVersion: "kubeflow.org/v1alpha1" kind: "MXJob" metadata: name: "gpu-dist-job" spec: jobMode: "dist" replicaSpecs: - replicas: 1 mxReplicaType: SCHEDULER PsRootPort: 9000 template: spec: containers: - image: 763104351884.dkr.ecr.us-east-1.amazonaws.com/aws-samples-mxnet-training:1.4.0-gpu-py36-cu90-ubuntu16.04-example name: mxnet restartPolicy: OnFailure - replicas: 2 mxReplicaType: SERVER template: spec: containers: - image: 763104351884.dkr.ecr.us-east-1.amazonaws.com/aws-samples-mxnet-training:1.4.0-gpu-py36-cu90-ubuntu16.04-example name: mxnet restartPolicy: OnFailure - replicas: 2 mxReplicaType: WORKER template: spec: containers: - image: 763104351884.dkr.ecr.us-east-1.amazonaws.com/aws-samples-mxnet-training:1.4.0-gpu-py36-cu90-ubuntu16.04-example name: mxnet command: ["python"] args: ["/incubator-mxnet/example/image-classification/train_mnist.py","--num-epochs","1","--num-layers","2","--kv-store","dist_device_sync","--gpus","0,1"] resources: limits: nvidia.com/gpu: 2 restartPolicy: OnFailure
  2. 使用您刚创建的 pod 文件运行分布式训练任务。

    $ # Create a job by defining MXJob kubectl create -f mx_job_dist.yaml
  3. 列出正在运行的任务。

    $ kubectl get mxjobs
  4. 要获取正在运行的任务的状态,请运行以下命令。将 JOB 变量替换为任务的任何名称。

    $ JOB=gpu-dist-job kubectl get -o yaml mxjobs $JOB

    该输出值应该类似于以下内容:

    apiVersion: kubeflow.org/v1alpha1 kind: MXJob metadata: creationTimestamp: 2019-03-21T22:00:38Z generation: 1 name: gpu-dist-job namespace: default resourceVersion: "2523104" selfLink: /apis/kubeflow.org/v1alpha1/namespaces/default/mxjobs/gpu-dist-job uid: c2e67f05-4c24-11e9-a6d4-125f5bb10ada spec: RuntimeId: j1ht jobMode: dist mxImage: jzp1025/mxnet:test replicaSpecs: - PsRootPort: 9000 mxReplicaType: SCHEDULER replicas: 1 template: metadata: creationTimestamp: null spec: containers: - image: 763104351884.dkr.ecr.us-east-1.amazonaws.com/aws-samples-mxnet-training:1.4.0-gpu-py36-cu90-ubuntu16.04-example name: mxnet resources: {} restartPolicy: OnFailure - PsRootPort: 9091 mxReplicaType: SERVER replicas: 2 template: metadata: creationTimestamp: null spec: containers: - image: 763104351884.dkr.ecr.us-east-1.amazonaws.com/aws-samples-mxnet-training:1.4.0-gpu-py36-cu90-ubuntu16.04-example name: mxnet resources: {} - PsRootPort: 9091 mxReplicaType: WORKER replicas: 2 template: metadata: creationTimestamp: null spec: containers: - args: - /incubator-mxnet/example/image-classification/train_mnist.py - --num-epochs - "15" - --num-layers - "2" - --kv-store - dist_device_sync - --gpus - "0" command: - python image: 763104351884.dkr.ecr.us-east-1.amazonaws.com/aws-samples-mxnet-training:1.4.0-gpu-py36-cu90-ubuntu16.04-example name: mxnet resources: limits: nvidia.com/gpu: 1 restartPolicy: OnFailure terminationPolicy: chief: replicaIndex: 0 replicaName: WORKER status: phase: Running reason: "" replicaStatuses: - ReplicasStates: Running: 1 mx_replica_type: SCHEDULER state: Running - ReplicasStates: Running: 2 mx_replica_type: SERVER state: Running - ReplicasStates: Running: 2 mx_replica_type: WORKER state: Running state: Running

    注意

    状态提供有关资源的状态的信息。

    阶段 - 表示任务的阶段且将为“Creating (正在创建)”、“Running (正在运行)”、“CleanUp (清除)”、“Failed (失败)”、“Done (完成)”之一。

    状态 - 提供任务的总体状态且将为“Running (正在运行)”、“Succeeded (成功)”、“Failed (失败)”之一。

  5. 清除并重新运行任务:

    $ eksctl delete cluster --name=<cluster-name>

    如果要删除任务,请将目录更改为您启动任务的位置并运行以下命令:

    $ ks delete default $ kubectl delete -f mx_job_dist.yaml

TensorFlow with Horovod

本教程将指导您如何在多节点 GPU 集群上设置 TensorFlow 模型的分布式训练。它还使用 Horovod。它使用已包含训练脚本的示例映像,并且将一个 3 节点集群与 node-type=p3.16xlarge 结合使用。

  1. 设置应用程序名称并将其初始化。

    $ APP_NAME=kubeflow-tf-hvd; ks init ${APP_NAME}; cd ${APP_NAME}
  2. 在此应用程序的文件夹中的 kubeflow 安装 mpi-operator。

    $ KUBEFLOW_VERSION=master $ ks registry add kubeflow github.com/kubeflow/kubeflow/tree/${KUBEFLOW_VERSION}/kubeflow $ ks pkg install kubeflow/common@${KUBEFLOW_VERSION} $ ks pkg install kubeflow/mpi-job@${KUBEFLOW_VERSION} $ ks generate mpi-operator mpi-operator $ ks apply default -c mpi-operator
  3. 创建 MPI 任务模板并定义节点数量(副本)以及每个节点具有的 GPU 数量 (gpusPerReplica),您还可以采用您的映像并自定义命令。

    IMAGE="763104351884.dkr.ecr.us-east-1.amazonaws.com/aws-samples-tensorflow-training:1.13-horovod-gpu-py36-cu100-ubuntu16.04-example" GPUS_PER_WORKER=2 NUMBER_OF_WORKERS=3 JOB_NAME=tf-resnet50-horovod-job ks generate mpi-job-custom ${JOB_NAME} ks param set ${JOB_NAME} replicas ${NUMBER_OF_WORKERS} ks param set ${JOB_NAME} gpusPerReplica ${GPUS_PER_WORKER} ks param set ${JOB_NAME} image ${IMAGE} ks param set ${JOB_NAME} command "mpirun,-mca,btl_tcp_if_exclude,lo,-mca,pml,ob1,-mca,btl,^openib,--bind-to,none,-map-by,slot,-x,LD_LIBRARY_PATH,-x,PATH,-x,NCCL_SOCKET_IFNAME=eth0,-x,NCCL_DEBUG=INFO,python,/deep-learning-models/models/resnet/tensorflow/train_imagenet_resnet_hvd.py" ks param set ${JOB_NAME} args -- --num_epochs=10,--synthetic
  4. 检查创建的任务清单以验证一切内容是否显示正常。

    $ ks show default -c ${JOB_NAME}
  5. 现在,将清单应用于默认环境。MPI 任务将创建启动 pod 并且日志将在此 pod 中聚合。

    $ ks apply default -c ${JOB_NAME}
  6. 检查状态。任务“tensorflow-training”的名称位于 tf.yaml 文件中。它现在将显示在状态中。如果您正在运行任何其他测试或之前已运行某些内容,它将显示在此列表中。多次运行此项,直到您看到状态更改为“Running (正在运行)”。

    $ kubectl get pods -o wide

    您应该可以看到类似于如下输出的内容:

    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE mpi-operator-5fff9d76f5-wvf56 1/1 Running 0 23m 192.168.10.117 ip-192-168-22-21.ec2.internal <none> tf-resnet50-horovod-job-launcher-d7w6t 1/1 Running 0 21m 192.168.13.210 ip-192-168-4-253.ec2.internal <none> tf-resnet50-horovod-job-worker-0 1/1 Running 0 22m 192.168.17.216 ip-192-168-4-253.ec2.internal <none> tf-resnet50-horovod-job-worker-1 1/1 Running 0 22m 192.168.20.228 ip-192-168-27-148.ec2.internal <none> tf-resnet50-horovod-job-worker-2 1/1 Running 0 22m 192.168.11.70 ip-192-168-22-21.ec2.internal <none>
  7. 根据上述启动程序 pod 的名称,检查日志以查看训练输出。

    $ kubectl logs -f --tail 10 tf-resnet50-horovod-job-launcher-d7w6t
  8. 您可以检查日志以观察训练进度。您还可以继续检查“get pods”以刷新状态。当状态变为“Completed (已完成)”时,您将知道该训练任务已完成。

  9. 清除并重新运行任务:

    # make sure ${JOB_NAME} and ${APP_NAME} are still set $ ks delete default -c ${JOB_NAME} $ ks delete default $ cd .. && rm -rf ${APP_NAME}

本页内容: