基于ASK+TFJob快速完成分布式Tensorflow训练任务

简介: 本文介绍如何使用TFJob在ASK+ECI场景下,快速完成基于GPU的TensorFlow分布式训练任务。

本文介绍如何使用TFJob在ASK+ECI场景下,快速完成基于GPU的TensorFlow分布式训练任务。

1. 前提条件

2. 背景信息

tf分布式1.jpg

我们知道,在AI训练/推理的场景下,往往需要大量的计算资源来对复杂的模型参数进行计算推理,因此在单台机器上的计算往往无法满足用户需要。于是机器学习框架逐渐由单机迁移到集群,如图所示,但是这样又引入了新的问题。分布式训练任务能利用数据中心所有服务器构成的资源池,让大量数据能分布在不同的服务器进行参数存储和训练,这无疑是分布式训练任务的优点。然而,这还不够,它还存在一些不足之处:

  • 缺乏调度能力,需要用户手动配置和管理任务的计算资源。

  • 集群规模大时,训练任务的管理很麻烦,要跟踪和管理每个任务的状态,需要在上层做大量开发。

  • 训练时TensorFlow各个Task资源无法隔离,导致任务间因资源抢占互相影响。

随着云原生概念的不断发展,对于这种典型的AI训练/推理场景也逐渐衍生出一套完整的解决方案,基于Kubernetes架构对于分布式训练任务进行管理调度,主要有以下好处:

  • 租户隔离,保证不同的用户能够互不干扰。

  • 方便管理与扩展能力,通过简单的配置便可实现大规模集群的管理。

本文主要阐述基于Kubernetes+TFJob方式以实现对复杂的分布式tensorflow任务的训练。

TFJob,是Kubernetes中的一种用户定义资源类型。通过这个资源类型,仅通过中心化的集群配置,用户便可以在Kubernetes集群部署自己的分布式深度学习任务。

基于阿里云的容器服务平台,针对以上的问题,我们推荐您使用ASK+ECI的方案来运行您的分布式训练任务,同时该方案还具备以下优势:

  • 按需付费,免运维,极致弹性。

  • 镜像缓存功能加速Pod创建,训练任务启动快速。

3. 操作步骤

  1. 通过Kubeflow的Arena工具在Kubernetes集群中部署Tensorflow作业运行环境并安装TFJob Controller。
git clone https://github.com/kubeflow/arena.git
kubectl create ns arena-system
kubectl create -f arena/kubernetes-artifacts/jobmon/jobmon-role.yaml
kubectl create -f arena/kubernetes-artifacts/tf-operator/tf-crd.yaml
kubectl create -f arena/kubernetes-artifacts/tf-operator/tf-operator.yaml

您可以执行如下命令查看tfjob-operator是否安装成功。

kubectl  get pods -n arena-system | grep tf-job-operator 

image.png

如图所示,可以看到分布式tensorflow运行环境配置成功。

2.在ACK Serverless集群中部署CoreDNS服务。由于分布式系统需要pod节点间需要建立连接并通信,ACK Serverless集群默认可选安装CoreDNS服务,因此需要单独安装CoreDNS服务。找到组件管理-网络-CoreDNS,选择并进行安装。

image.png

如图所示,CoreDNS组件安装成功。

3.声明PV与PVC, 用于存储mnist训练所需要的数据。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: tf-mnist-nas
  labels:
    tfjob: tf-mnist-nas
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  storageClassName: nas
  flexVolume:
    driver: "alicloud/nas"
    options:
      mode: "755"
      path: /training
      server: 175dd4ad88-mae80.cn-beijing.nas.aliyuncs.com
      vers: "4.0"
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: tf-mnist-nas
spec:
  storageClassName: nas
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  selector:
    matchLabels:
      tfjob: tf-mnist-nas

4.提交分布式训练的TFJob。

apiVersion: kubeflow.org/v1
kind: TFJob
metadata:
  name: tf-mnist-gpu
  namespace: default
spec:
  tfReplicaSpecs:
    PS:
      replicas: 1
      template:
        metadata:
          annotations:
            k8s.aliyun.com/eci-image-cache: 'true' # 开启镜像缓存自动匹配
        spec:
          containers:
            - command:
                - python
                - /app/main.py
              env:
                - name: TEST_TMPDIR
                  value: /training
              image: >-
                registry.cn-beijing.aliyuncs.com/eci/tf-dist-mnist:cpu
              imagePullPolicy: Always
              name: tensorflow
              volumeMounts:
                - mountPath: /training
                  name: tf-mnist-nas
          restartPolicy: OnFailure
          volumes:
            - name: tf-mnist-nas
              persistentVolumeClaim:
                claimName: tf-mnist-nas
    MASTER:
      replicas: 1
      template:
        metadata:
          annotations:
            k8s.aliyun.com/eci-image-cache: 'true' # 开启镜像缓存自动匹配
            k8s.aliyun.com/eci-use-specs: ecs.gn7i-c8g1.2xlarge # 指定GPU规格
        spec:
          containers:
            - command:
                - python
                - /app/main.py
              env:
                - name: TEST_TMPDIR
                  value: /training
              image: >-
                registry.cn-beijing.aliyuncs.com/eci/tf-dist-mnist:gpu
              name: tensorflow
              resources:
                limits:
                  nvidia.com/gpu: 1
              volumeMounts:
                - mountPath: /training
                  name: tf-mnist-nas
          restartPolicy: OnFailure
          volumes:
            - name: tf-mnist-nas
              persistentVolumeClaim:
                claimName: tf-mnist-nas
    WORKER:
      replicas: 1
      template:
        metadata:
          annotations:
            k8s.aliyun.com/eci-image-cache: 'true' # 开启镜像缓存自动匹配
            k8s.aliyun.com/eci-use-specs: ecs.gn7i-c8g1.2xlarge # 指定GPU规格
        spec:
          containers:
            - command:
                - python
                - /app/main.py
              env:
                - name: TEST_TMPDIR
                  value: /training
              image: >-
                registry.cn-beijing.aliyuncs.com/eci/tf-dist-mnist:gpu
              imagePullPolicy: Always
              name: tensorflow
              resources:
                limits:
                  nvidia.com/gpu: 1
              volumeMounts:
                - mountPath: /training
                  name: tf-mnist-nas
          restartPolicy: OnFailure
          volumes:
            - name: tf-mnist-nas
              persistentVolumeClaim:
                claimName: tf-mnist-nas

5.查看TFJob运行状态及容器日志输出。

image.png

 kubectl logs tf-mnist-gpu-master-0 --tail=150

image.png

6.部署tensorboard,查看训练效果。

说明

tensorboard是tensorflow自带的一个强大的可视化工具,也是一个Web应用程序套件。tensorboard通过运行一个本地服务器,来监听6006端口。在浏览器发出请求时,分析训练时记录的数据,绘制训练过程中的图像。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: tensorboard
  name: tensorboard
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tensorboard
  template:
    metadata:
      labels:
        app: tensorboard
    spec:
      volumes:
      - name: tf-mnist-nas
        persistentVolumeClaim:
            claimName: tf-mnist-nas
      containers:
      - name: tensorboard
        image: tensorflow/tensorflow:1.7.0
        imagePullPolicy: Always
        command:
         - /usr/local/bin/tensorboard
        args:
        - --logdir
        - /training/tensorflow/logs
        volumeMounts:
        - name: tf-mnist-nas
          mountPath: "/training"
        ports:
        - containerPort: 6006
          protocol: TCP
      dnsPolicy: ClusterFirst
      restartPolicy: Always

查看部署是否成功。

kubectl get pods| grep tensorboard

image.png

tensorboard创建成功后,通过kubectl port-forward命令进行访问。

kubectl port-forward tensorboard-cc746c797-98w2f 6006:6006

image.png

通过http://127.0.0.1:6006登录tensorboard,查看分布式训练效果。

7.通过tensorflow cnn benchmark对比不同worker数目带来训练效果的差异。

说明

tensorflow cnn benchmark提供了基于cnn的多个图像分类模型用于图像数据的分类,示例在parameter server架构下采用cnn中的resnet50模型对图像进行训练。

示例YAML如下。

apiVersion: kubeflow.org/v1
kind: TFJob
metadata:
  name: tf-benchmarks-gpu
  namespace: default
spec:
  tfReplicaSpecs:
    PS:
      replicas: 1
      template:
        metadata:
          annotations:
            k8s.aliyun.com/eci-image-cache: 'true'  # 开启镜像缓存自动匹配
        spec:
          containers:
            - args:
                - python
                - tf_cnn_benchmarks.py
                - '--batch_size=128'
                - '--num_batches=100'
                - '--model=resnet50'
                - '--variable_update=parameter_server'
                - '--flush_stdout=true'
                - '--num_gpus=1'
                - '--local_parameter_device=cpu'
                - '--device=cpu'
                - '--data_format=NHWC'
              image: 'registry-vpc.cn-beijing.aliyuncs.com/eci/tf-benchmarks-cpu:1.0'
              name: tensorflow
              resources:
                limits:
                  cpu: '16'
              workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
    Worker:
      replicas: 1
      template:
        metadata:
          annotations:
            k8s.aliyun.com/eci-image-cache: 'true'  # 开启镜像缓存自动匹配
            k8s.aliyun.com/eci-use-specs: ecs.gn7i-c8g1.2xlarge # 指定GPU规格创建ECI实例
        spec:
          containers:
            - args:
                - python
                - tf_cnn_benchmarks.py
                - '--batch_size=128'
                - '--num_batches=100'
                - '--model=resnet50'
                - '--variable_update=parameter_server'
                - '--flush_stdout=true'
                - '--num_gpus=1'
                - '--local_parameter_device=cpu'
                - '--device=gpu'
                - '--data_format=NHWC'
              image: 'registry-vpc.cn-beijing.aliyuncs.com/eci/tf-benchmarks-gpu:1.0'
              name: tensorflow
              resources:
                limits:
                  nvidia.com/gpu: 1 # 指定gpu资源
              workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks

(1 )执行命令创建训练任务pod。

kubectl create -f tf-benchmarks-gpu.yaml

创建成功后执行如下命令,可查看pod运行状态。

kubectl get pods | grep tf-benchmarks-gpu

image.png

容器处于运行状态后,便开始执行训练任务,执行如下命令,可以看到对应容器的日志输出。

kubectl logs tf-benchmarks-gpu-worker-0

image.png

训练任务完成后,我们可以通过日志看到,我们此次基于resnet50模型训练性能为198.28(images/sec)。

(2)增加分布式worker数,采用多张gpu训练。

image.png

作为验证,我们修改worker副本数目,重新创建分布式训练任务,相当于在集群中增加worker实例为2个,采用多张gpu并行计算,相当于增加训练的batch_size,提高集群模型训练性能,对比日志输出得到如下结果。

image.png

由此可见,通过增加训练模型worker副本数,可以相应地提高分布式tensorflow模型训练的性能,因此可以通过水平扩展方式支持更大规模的AI训练任务。

4. Q&A

Q:master节点、ps节点、worker节点的作用分别是什么?

A:分布式任务整体遵循了PS架构,即参数放置在ps,而worker执行计算,我们其实可以把master也看作是一种worker,只不过在架构中负责会话初始化与资源调度。

Q:训练速度和什么参数有关,参数是越大越好么?

A:训练速度和batchSize、worker、ps、gpu数目等都相关,具体加速效果要视情况而定,在某些情况下加大参数可以获得相应的加速比,但是到达瓶颈后可能不会继续增加。

作者介绍
目录