从监控到隔离,阿里云容器服务提升您的GPU资源使用体验

从监控到隔离,阿里云容器服务提升您的GPU资源使用体验

推动人工智能不断向前的动力来自于强大的算力,海量的数据和优化的算法,而Nvidia GPU是最流行的异构算力提供者,是高性能深度学习的基石。但是GPU不菲的价格一直是用户的心头之痛,而从使用率的角度来看,模型预测场景下,应用独占GPU模式实际上会对这种宝贵的资源造成大量的浪费。但是共享GPU实际上也不是一蹴而就,比如一方面用户需要判断多少的分配GPU资源可以达到成本和QPS平衡的最优,另一方面也要考虑同时当多个应用运行在一个GPU设备上时,应用的SLA如何保障。
从监控到隔离,阿里云容器服务提升您的GPU资源使用体验
而通过使用阿里云容器服务,一方面借助托管的Prometheus,提升GPU资源管理的可见性,快速了解到需要多少的GPU资源可以支撑图像识别,语音识别,在线翻译等业务,如何能用最少的成本满足业务需求;而另一方面,借助昊天cGPU,在无需修改现有GPU程序的前提下,保障多个容器共享同一个GPU时,彼此互相隔离。
我们通过一个实际的例子向您展示如何利用托管Prometheus的监控能力查看GPU的显存使用,并且通过昊天cGPU进行资源隔离。

前置条件

使用步骤

通过托管Prometheus监控独享GPU

  1. 登录ARMS控制台, 选择Kubernetes所在的集群
  2. 在ARMS控制台中Prometheus界面中,点击集群列表中需要监控集群的安装按钮。此过程需要2分钟左右,请点击确认。

从监控到隔离,阿里云容器服务提升您的GPU资源使用体验

  1. 在该集群的已安装插件中可以看到 GPU NodeGPU APP,分别从节点维度和应用维度监控GPU资源

从监控到隔离,阿里云容器服务提升您的GPU资源使用体验

  1. 运行测试应用

利用命令行部署如下应用, 参考文档

apiVersion: apps/v1beta1
kind: StatefulSet

metadata:
  name: app-3g-v1
  labels:
    app: app-3g-v1
spec:
  replicas: 1
  serviceName: "app-3g-v1"
  podManagementPolicy: "Parallel"
  selector: # define how the deployment finds the pods it manages
    matchLabels:
      app: app-3g-v1
  updateStrategy:
    type: RollingUpdate
  template: # define the pods specifications
    metadata:
      labels:
        app: app-3g-v1
    spec:
      containers:
      - name: app-3g-v1
        image: registry.cn-shanghai.aliyuncs.com/tensorflow-samples/cuda-malloc:3G
        resources:
          limits:
            nvidia.com/gpu: 1

部署成功后,查看应用的状态,可以知道应用的名称是app-3g-v1-0

kubectl get po
NAME          READY   STATUS    RESTARTS   AGE
app-3g-v1-0   1/1     Running   1          2m56s
  1. 通过应用角度监控, 点击GPU App进入可以观察到GPU的显存使用率, 可以发现这个应用的GPU显存占用率仅为20%,有80%的浪费。而它使用的显存也是比较稳定在3.4GB左右,而该GPU总的显存是16GB左右。

从监控到隔离,阿里云容器服务提升您的GPU资源使用体验
此时可以发现一个应用独占一张GPU卡的模式非常浪费。因此可以考虑通过使用cGPU(container GPU)可以将多个应用部署在同一个GPU卡上。
可以先将该容器移除

kubectl delete sts app-3g-v1

使用cGPU保障多容器共享

为带有GPU设备的节点打标签

在安装cGPU相关组件之前,需要给gpu节点打上标签"cgpu=true",步骤如下:
(1)登录容器服务 Kubernetes 版控制台
(2)在 Kubernetes 菜单下,单击左侧导航栏中的集群 > 节点,进入节点列表页面。选择所需的集群,在页面右上角单击标签管理。
(3)选择所需的集群,在页面右上角单击标签管理。
从监控到隔离,阿里云容器服务提升您的GPU资源使用体验
(4)在节点列表中,批量选择节点,然后单击添加标签。
从监控到隔离,阿里云容器服务提升您的GPU资源使用体验
(5)填写标签名称和值(名称为cgpu,值为true),点击确定。
从监控到隔离,阿里云容器服务提升您的GPU资源使用体验

安装cGPU相关组件

(1)登录容器服务 Kubernetes 版控制台。(2)在左侧导航栏选择市场 > 应用目录,在右侧选中 ack-cgpu。(3)在应用目录 -> ack-cgpu页面上,在右侧的创建面板中选择前提条件中创建的集群和命名空间,并单击创建。
从监控到隔离,阿里云容器服务提升您的GPU资源使用体验

  1. 安装kubectl-inspect-cgpu

kubectl-inspect-gpushare是一个查询节点GPU分配情况的工具,它依赖集群的kubeconfig配置文件。请登录到linux客户端进行安装。请确保"~/.kube/config"文件已经存在,如何下载集群的kubeconfig文件,请参考用kubectl管理集群。kubeconfig文件配置完成以后,接着在该节点上执行如下操作安装kubectl-inspect-cgpu:

# cd /usr/local/bin
# wget http://aliacs-k8s-cn-beijing.oss-cn-beijing.aliyuncs.com/cgpu/kubectl-inspect-cgpu
# chmod u+x /usr/local/bin/kubectl-inspect-cgpu
  1. 通过kubectl-inspect-cgpu检查GPU资源
# kubectl inspect cgpu
NAME                       IPADDRESS      GPU0(Allocated/Total)  GPU Memory(GiB)
cn-hangzhou.192.168.2.167  192.168.2.167  0/15                   0/15
----------------------------------------------------------------------
Allocated/Total GPU Memory In Cluster:
0/15 (0%)

此时可以发现该节点的GPU资源维度已经从卡变成GPU显存

部署共享GPU工作负载

  1. 按照GPU显存维度调度重新创建工作负载

只需要将之前的部署yaml做两处的修改:

  • 将实例的副本数从1改为2,这样可以指定部署两个负载。而在原有GPU独享的配置下,单个GPU卡智能调度单个容器;修改配置后,可以部署两个Pod实例。
  • 将资源维度从nvidia.com/gpu变为aliyun.com/gpu-mem, 单位也从个变成了GiB

由于每个应用不足以独享GPU资源,因此它们可以部署到同一个GPU设备上。

apiVersion: apps/v1beta1
kind: StatefulSet

metadata:
  name: app-3g-v1
  labels:
    app: app-3g-v1
spec:
  replicas: 2
  serviceName: "app-3g-v1"
  podManagementPolicy: "Parallel"
  selector: # define how the deployment finds the pods it manages
    matchLabels:
      app: app-3g-v1
  template: # define the pods specifications
    metadata:
      labels:
        app: app-3g-v1
    spec:
      containers:
      - name: app-3g-v1
        image: registry.cn-shanghai.aliyuncs.com/tensorflow-samples/cuda-malloc:3G
        resources:
          limits:
            aliyun.com/gpu-mem: 4

从运行结果看,可以看到两个Pod都运行在同一个GPU设备上

#  kubectl inspect cgpu -d

NAME:       cn-hangzhou.192.168.2.167
IPADDRESS:  192.168.2.167

NAME         NAMESPACE  GPU0(Allocated)
app-3g-v1-0  default    4
app-3g-v1-1  default    4
Allocated :  8 (53%)
Total :      15
--------------------------------------------------------

Allocated/Total GPU Memory In Cluster:  8/15 (53%)
  1. 而分别登陆两个容器的时候可以看到他们各自的GPU显存的上限已经设置为4301MiB, 也就是在容器内使用的GPU显存不会超过这个上限
kubectl exec -it app-3g-v1-0 nvidia-smi
Mon Apr 13 01:33:10 2020
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.87.01    Driver Version: 418.87.01    CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla V100-SXM2...  On   | 00000000:00:07.0 Off |                    0 |
| N/A   37C    P0    57W / 300W |   3193MiB /  4301MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

kubectl exec -it app-3g-v1-1 nvidia-smi
Mon Apr 13 01:36:07 2020
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.87.01    Driver Version: 418.87.01    CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla V100-SXM2...  On   | 00000000:00:07.0 Off |                    0 |
| N/A   38C    P0    57W / 300W |   3193MiB /  4301MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+
  1. 而登陆到节点后,可以看到该GPU被使用的显存资源为两个容器之和6396MiB。这里可以看到cGPU资源已经起到了按容器隔离的效果。
# nvidia-smi
Mon Apr 13 09:36:43 2020
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.87.01    Driver Version: 418.87.01    CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla V100-SXM2...  On   | 00000000:00:07.0 Off |                    0 |
| N/A   37C    P0    57W / 300W |   6396MiB / 16130MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      2174      C   cuda_malloc                                 3193MiB |
|    0      2209      C   cuda_malloc                                 3193MiB |
+-----------------------------------------------------------------------------+
  1. 此时登录到容器内试图申请更多的GPU资源时,会直接报出显存分配失败的错误
kubectl exec -it app-3g-v1-1 bash
root@app-3g-v1-1:/# cuda_malloc -size=1024
cgpu_cuda_malloc starting...
Detected 1 CUDA Capable device(s)

Device 0: "Tesla V100-SXM2-16GB"
  CUDA Driver Version / Runtime Version          10.1 / 10.1
  Total amount of global memory:                 4301 MBytes (4509925376 bytes)
Try to malloc 1024 MBytes memory on GPU 0
CUDA error at cgpu_cuda_malloc.cu:119 code=2(cudaErrorMemoryAllocation) "cudaMalloc( (void**)&dev_c, malloc_size)"

通过托管Prometheus监控共享GPU

  1. 实际上用户并不需要到每个容器内执行nvidia-smi,这样做监控一方面效率低,也无法获得资源趋势。用户可以通过登录到ARMS控制台,选择相应的Kubernetes集群,进入GPU App。可以直接看到每个应用的GPU显存用量和占比

从监控到隔离,阿里云容器服务提升您的GPU资源使用体验

  1. 如果希望从节点维度观测,可以通过GPU Node查看GPU卡的显存使用量。可以看到恰好其显存使用率是两个GPU应用的使用之和为40%。

从监控到隔离,阿里云容器服务提升您的GPU资源使用体验

  1. 接下来,我们演示如何将一个害群之马关到笼子里,即当某个应用程序的声明使用GPU显存用量超过了资源上限后,cGPU如何确保当其他应用不受影响。

部署一个新的GPU应用,该应用声明使用的GPU显存是4GiB,但是它实际使用的GPU显存为6GiB

apiVersion: apps/v1beta1
kind: StatefulSet

metadata:
  name: app-6g-v1
  labels:
    app: app-6g-v1
spec:
  replicas: 1
  serviceName: "app-6g-v1"
  podManagementPolicy: "Parallel"
  selector: # define how the deployment finds the pods it manages
    matchLabels:
      app: app-6g-v1
  template: # define the pods specifications
    metadata:
      labels:
        app: app-6g-v1
    spec:
      containers:
      - name: app-6g-v1
        image: registry.cn-shanghai.aliyuncs.com/tensorflow-samples/cuda-malloc:6G
        resources:
          limits:
            aliyun.com/gpu-mem: 4

将该应用部署之后可以发现该pod一直处于CrashLoopBackOff, 而之前两个Pod还是正常运行的状态

# kubectl get po
NAME          READY   STATUS             RESTARTS   AGE
app-3g-v1-0   1/1     Running            0          7h35m
app-3g-v1-1   1/1     Running            0          7h35m
app-6g-v1-0   0/1     CrashLoopBackOff   5          3m15s

而该容器的日志报错,也很明确的显示是由于cudaErrorMemoryAllocation造成的

kubectl logs app-6g-v1-0
CUDA error at cgpu_cuda_malloc.cu:119 code=2(cudaErrorMemoryAllocation) "cudaMalloc( (void**)&dev_c, malloc_size)"

而此时其他的容器并没有收到影响,从托管的Prometheus监控中也可以看到之前的容器一直处于平稳运行之中,并没有受到新部署应用的影响。
从监控到隔离,阿里云容器服务提升您的GPU资源使用体验

总结

通过使用阿里云容器服务的GPU支持,可以提升GPU资源管理的可见性,了解到需要多少的GPU资源可以支撑图像识别,语音识别,在线翻译等业务,如何能用最少的成本满足业务需求;而可以在无需修改现有GPU程序的前提下,保障多个容器共享同一个GPU时,实现彼此互相隔离。帮助用户在享受低成本的同时,保障了应用的可靠性。

上一篇:大数据实战之spark安装部署


下一篇:“云上贵州”建立大数据灾备中心