【Hello AI】通过Docker安装并使用cGPU服务

简介: cGPU服务可以隔离GPU资源,实现多个容器共用一张GPU卡。该服务作为阿里云容器服务Kubernetes版ACK(Container Service for Kubernetes)的组件对外提供服务,本文介绍如何通过Docker安装并使用cGPU服务。

cGPU服务可以隔离GPU资源,实现多个容器共用一张GPU卡。该服务作为阿里云容器服务Kubernetes版ACK(Container Service for Kubernetes)的组件对外提供服务,本文介绍如何通过Docker安装并使用cGPU服务。

前提条件

在进行本操作前,请确保GPU实例满足以下要求:

  • GPU实例规格为gn7i、gn6i、gn6v、gn6e、gn5i、gn5、ebmgn7i、ebmgn6i、ebmgn7e、ebmgn6e、ebmgn7ex或sccgn7ex。
  • GPU实例操作系统为CentOS、Ubuntu或Alibaba Cloud Linux。
  • GPU实例已安装418.87.01或更高版本的NVIDIA驱动。
  • GPU实例已安装19.03.5或更高版本的Docker。

背景信息

cGPU服务的隔离功能不支持以UVM的方式申请显存,即调用CUDA API cudaMallocManaged(),请使用其他方式申请显存,例如调用cudaMalloc()等。更多信息,请参见NVIDIA官方文档

安装cGPU服务

无论您是企业认证用户还是个人实名认证用户,推荐您通过ACK的Docker运行时环境安装和使用cGPU服务。具体操作,请参见安装共享GPU调度组件

运行cGPU服务

影响cGPU服务的环境变量如下表所示,您可以在创建容器时指定环境变量的值,该值可以控制容器通过cGPU服务获得算力。

环境变量名称

取值类型

说明

示例

CGPU_DISABLE

Boolean

是否禁用cGPU服务,取值范围:

  • false:启用cGPU服务。
  • true:禁用cGPU服务,使用默认的NVIDIA容器服务。

当不设置环境变量CGPU_DISABLE时,默认值为false。

通过设置环境变量CGPU_DISABLE=true禁用cGPU服务。

ALIYUN_COM_GPU_MEM_DEV

Integer

设置GPU实例上每张显卡的总显存大小,和实例规格有关。

说明

显存大小按GiB取整数。

一台GPU实例规格为ecs.gn6i-c4g1.xlarge,配备1张NVIDIA ® Tesla ® T4显卡。在GPU实例上执行nvidia-smi查看总显存大小为15109 MiB,取整数为15 GiB。

ALIYUN_COM_GPU_MEM_CONTAINER

Integer

设置容器内可见的显存大小,和ALIYUN_COM_GPU_MEM_DEV结合使用。如果不指定本参数或指定为0,则不使用cGPU服务,使用默认的NVIDIA容器服务。

在一张总显存大小为15 GiB的显卡上,设置环境变量ALIYUN_COM_GPU_MEM_DEV=15ALIYUN_COM_GPU_MEM_CONTAINER=1,效果是为容器分配1 GiB的显存。

ALIYUN_COM_GPU_VISIBLE_DEVICES

Integer或uuid

指定容器内可见的GPU显卡。

在一台有4张显卡的GPU实例上,执行nvidia-smi -L查看GPU显卡设备号和UUID。返回示例如下所示:

 

GPU 0: Tesla T4 (UUID: GPU-b084ae33-e244-0959-cd97-83****)
GPU 1: Tesla T4 (UUID: GPU-3eb465ad-407c-4a23-0c5f-bb****)
GPU 2: Tesla T4 (UUID: GPU-2fce61ea-2424-27ec-a2f1-8b****)
GPU 3: Tesla T4 (UUID: GPU-22401369-db12-c6ce-fc48-d7****)

然后,设置以下环境变量:

  • ALIYUN_COM_GPU_VISIBLE_DEVICES=0,1,效果是为容器分配第1和第2张显卡。
  • ALIYUN_COM_GPU_VISIBLE_DEVICES=GPU-b084ae33-e244-0959-cd97-83****,GPU-3eb465ad-407c-4a23-0c5f-bb****,GPU-2fce61ea-2424-27ec-a2f1-8b****,效果是为容器分配3张指定UUID的显卡。

ALIYUN_COM_GPU_SCHD_WEIGHT

Integer

设置容器的算力权重,取值范围:1~max_inst。

ALIYUN_COM_GPU_HIGH_PRIO

Integer

设置容器的高优先级,取值范围:

  • 0:不设置容器为高优先级(即普通优先级)。默认值为0。
  • 1:设置容器为高优先级。

建议每张GPU卡设置一个高优先级,多个高优先级容器之间遵循相应的调度策略(policy)。

  • 当高优先级容器有GPU任务时,不受调度策略(policy)限制,可以抢占GPU的算力。
  • 当高优先级容器无GPU任务时,容器不参与调度过程,分配的算力为0。

0

以ecs.gn6i-c4g1.xlarge为例演示2个容器共用1张显卡。

  1. 执行以下命令,创建容器并设置容器内可见的显存。
docker run -d -t --gpus all --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 --name gpu_test1 -v /mnt:/mnt -e ALIYUN_COM_GPU_MEM_CONTAINER=6 -e ALIYUN_COM_GPU_MEM_DEV=15 nvcr.io/nvidia/tensorflow:19.10-py3
docker run -d -t --gpus all --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 --name gpu_test2 -v /mnt:/mnt -e ALIYUN_COM_GPU_MEM_CONTAINER=8 -e ALIYUN_COM_GPU_MEM_DEV=15 nvcr.io/nvidia/tensorflow:19.10-py3

说明该命令以使用TensorFlow镜像nvcr.io/nvidia/tensorflow:19.10-py3为例,请根据实际情况更换为您自己的容器镜像。使用TensorFlow镜像搭建TensorFlow深度学习框架的操作,请参见在GPU实例上部署NGC环境

本示例中,通过设置环境变量ALIYUN_COM_GPU_MEM_CONTAINER和ALIYUN_COM_GPU_MEM_DEV指定显卡的总显存和容器内可见的显存。命令执行结果是创建了2个容器:

  • gpu_test1:分配6 GiB显存。
  • gpu_test2:分配8 GiB显存。
  • 执行以下命令,查看显存等GPU信息。

本示例中,以gpu_test1为例。

docker exec -i gpu_test1 nvidia-smi

容器gpu_test1中可见的显存为6043 MiB,如下图所示:

查看procfs节点

cGPU服务运行时会在/proc/cgpu_km下生成并自动管理多个procfs节点,您可以通过procfs节点查看和配置cGPU服务相关的信息。下面介绍各procfs节点的用途。

  1. 执行以下命令,查看节点信息。
ls /proc/cgpu_km/

执行结果如下所示:

0  default_memsize  inst_ctl  upgrade  version

节点信息说明如下表所示:

节点

读写类型

说明

0

读写

cGPU服务会针对GPU实例中的每张显卡生成一个目录,并使用数字作为目录名称,例如0、1、2。本示例中只有一张显卡,对应的目录ID为0。

default_memsize

读写

如果没有设置ALIYUN_COM_GPU_MEM_CONTAINER参数,默认为新创建的容器分配的显存大小。

inst_ctl

读写

控制节点。

upgrade

读写

控制cGPU服务的热升级。

version

只读

cGPU的版本。

  1. 执行以下命令查看显卡对应的目录内容。

本示例中,以显卡0为例。

ls /proc/cgpu_km/0

执行结果如下所示:

012b2edccd7a   0852a381c0cf   free_weight    major    max_inst    policy    prio_ratio

目录内容说明如下表所示:

节点

读写类型

说明

容器对应的目录

读写

cGPU服务会针对运行在GPU实例中的每个容器生成一个的目录,并使用容器ID作为目录名称。您可以执行docker ps查看已创建的容器。

free_weight

只读

用于查询和修改可用的权重。如果free_weight=0,新创建容器的权重值为0,该容器不能获取GPU算力,不能用于运行需要GPU算力的应用。

major

只读

表示cGPU的major number,即不同的设备类型。

max_inst

读写

用于设置容器的最大数量,取值范围为1~25。

policy

读写

cGPU服务支持以下算力调度策略:

  • 0:平均调度。每个容器占用固定的时间片,时间片占比为1/max_inst
  • 1:抢占调度。每个容器占用尽量多的时间片,时间片占比为1/当前容器数
  • 2:权重抢占调度。当ALIYUN_COM_GPU_SCHD_WEIGHT的取值大于1时,自动使用权重抢占调度。
  • 3:固定算力调度。用于固定算力的百分比。
  • 4:算力弱调度。隔离性弱于抢占调度。
  • 5:原生调度。即GPU驱动本身的调度方式。

您可以通过修改policy的值实时调整调度策略。更多调度策略说明,请参见cGPU服务算力调度示例

prio_ratio

读写

在线和离线混合使用场景下,高优先级容器最大可以抢占的算力。取值范围:20~99。

  1. 执行以下命令查看容器对应的目录内容。

本示例中,以012b2edccd7a容器为例。

ls /proc/cgpu_km/0/012b2edccd7a

执行结果如下所示:

highprio    id  meminfo  memsize  weight

目录内容说明如下表所示:

节点

读写类型

说明

highprio

读写

用于设置容器的优先级,默认值为0。

ALIYUN_COM_GPU_HIGH_PRIO参数取值为1时,表示容器最大可以抢占prio_ratio参数的算力。

说明

该功能用于在线和离线混合使用场景。更多信息,请参见安装cGPU服务中的README说明。

id

只读

容器的ID。

memsize

读写

用于设置容器内的显存大小。cGPU服务会根据ALIYUN_COM_GPU_MEM_DEV参数自动设定此值。

meminfo

只读

包括容器内剩余显存容量、正在使用GPU的进程ID及其显存用量。输出如下所示:

 

Free: 6730809344
PID: 19772 Mem: 200278016

weight

读写

用于设置容器获取显卡最大算力的权重,默认值为1。所有运行中的容器的权重之和必须小于等于max_inst。

了解procfs节点的用途后,您可以在GPU实例中执行命令进行切换调度策略、修改权重等操作,示例命令如下表所示。

命令

效果

echo 2 > /proc/cgpu_km/0/policy

将调度策略切换为权重抢占调度。

cat /proc/cgpu_km/0/free_weight

查看显卡上可用的权重。如果free_weight=0,新创建容器的权重值为0,该容器不能获取GPU算力,不能用于运行需要GPU算力的应用。

cat /proc/cgpu_km/0/$dockerid/weight

查看指定容器的权重。

echo 4 > /proc/cgpu_km/0/$dockerid/weight

修改容器获取GPU算力的权重。

升级cGPU服务

升级cGPU服务支持冷升级和热升级两种方式。

  • 冷升级

Docker未使用cGPU服务的情况下,采用冷升级方式升级cGPU服务,操作步骤如下:

  1. 执行以下脚本,关闭所有运行中的容器。
docker stop $(docker ps -a | awk '{ print $1}' | tail -n +2)
  1. 执行upgrade.sh脚本,升级cGPU服务至最新版本。
sh upgrade.sh
  • 热升级

Docker使用cGPU服务的情况下,采用热升级方式升级cGPU服务。

卸载cGPU服务

关于如何卸载节点上旧版本cGPU服务,具体操作,请参见通过命令升级节点cGPU版本

通过cgpu-smi监控容器

您可以通过cgpu-smi工具查看cGPU容器的相关信息,包括容器ID、GPU利用率、算力限制、使用的显存以及分配显存的总量等信息。

说明cgpu-smi是cGPU的监控示例。部署k8s时,您可以参考或使用cgpu-smi的示例做二次开发集成。

cgpu-smi的监控展示信息如下所示:

cGPU服务算力调度示例

cGPU服务加载cgpu_km的模块时,会按照容器最大数量(max_inst)为每张显卡设置时间片(X ms),用于为容器分配GPU算力,本示例中以Slice 1、Slice 2...Slice N表示。使用不同调度策略时的调度示例如下所示。

  • 平均调度(policy=0)

在创建容器时,为容器分配时间片。cGPU服务会从Slice 1时间片开始调度,提交任务到物理GPU,并执行一个时间片(X ms)的时间,然后切换到下一个时间片。每个容器获得的算力相同,都为1/max_inst。如下图所示。

  • 抢占调度(policy=1)

在创建容器时,为容器分配时间片。cGPU服务会从Slice 1开始调度,但如果没有使用某个容器,或者容器内没有进程打开GPU设备,则跳过调度,切换到下一个时间片。

示例如下:

  1. 只创建一个容器Docker 1,获得Slice 1时间片,在Docker 1中运行2个TensorFlow进程,此时Docker 1最大获得整个物理GPU的算力。
  2. 再创建一个容器Docker 2,获得Slice 2时间片。如果Docker 2内没有进程打开GPU设备,调度时会跳过Docker 2的时间片Slice 2。
  3. 当Docker 2内有进程打开GPU设备时,Slice 1和Slice 2都加入调度,Docker 1和Docker 2最大分别获得1/2物理GPU的算力。如下图所示。

  1. 权重抢占调度(policy=2)

如果在创建容器时设置ALIYUN_COM_GPU_SCHD_WEIGHT大于1,则自动使用权重抢占调度。cGPU服务按照容器数量(max_inst)将物理GPU算力划分成max_inst份,但如果ALIYUN_COM_GPU_SCHD_WEIGHT大于1,cGPU服务会将数个时间片组合成一个更大的时间片分配给容器。

设置示例如下:

  • Docker 1:ALIYUN_COM_GPU_SCHD_WEIGHT=m
  • Docker 2:ALIYUN_COM_GPU_SCHD_WEIGHT=n

调度效果如下:

  • 如果只有Docker 1运行, Docker 1抢占整个物理GPU的算力。
  • 如果Docker 1和Docker 2同时运行,Docker 1和Docker 2获得的理论算力比例是m:n。和抢占调度不同的是,即使Docker 2中没有GPU进程也会占用n个时间片的时间。

说明m:n设置为2:1和8:4时的运行表现存在差别。在1秒内切换时间片的次数,前者是后者的4倍。

权重抢占调度限制了容器使用GPU算力的理论最大值。但对算力很强的显卡(例如NVIDIA ® V100显卡),如果显存使用的较少,在一个时间片内即可完成计算任务。此时如果m:n值设置为8:4,则剩余时间片内GPU算力会闲置,限制基本失效。

  • 固定算力调度(policy=3)

您可以通过指定ALIYUN_COM_GPU_SCHD_WEIGHT和max_inst的占比,固定算力的百分比。

  • 算力弱调度(policy=4)

在创建容器时,为容器分配时间片,隔离性弱于抢占调度。更多信息,请参见本文《抢占调度(policy=1)》的相关内容。

  • 原生调度(policy=5)

只用来做显存的隔离。原生调度表示NVIDIA GPU驱动本身的调度方式。

算力调度策略支持阿里云所有的异构GPU实例,以及GPU实例所配备的NVIDIA显卡,其型号包含Tesla P4、Tesla P100、Tesla T4、Tesla V100、Tesla A10。以下测试项使用2个容器共享一台单卡A10的GPU实例,并将2个容器的算力比设置为1:2,将显存均分,每个容器的显存为12 G。

说明以下性能测试结果数据为实验室数据,仅供参考。

  • 测试项1: 在基于TensorFlow框架训练的ResNet50模型、精度为FP16的场景下,测试不同batch_size下的性能数据比较。结果如下所示:

框架

模型

batch_size

精度

images/sec(容器1)

images/sec(容器2)

TensorFlow

ResNet50

16

FP16

151

307

TensorFlow

ResNet50

32

FP16

204

418

TensorFlow

ResNet50

64

FP16

247

503

TensorFlow

ResNet50

128

FP16

257

516

  • 测试项2:在基于TensorRT框架训练的ResNet50模型、精度为FP16的场景下,测试不同batch_size下的性能数据比较。结果如下所示:

框架

模型

batch_size

精度

images/sec(容器1)

images/sec(容器2)

TensorRT

ResNet50

1

FP16

568.05

1132.08

TensorRT

ResNet50

2

FP16

940.36

1884.12

TensorRT

ResNet50

4

FP16

1304.03

2571.91

TensorRT

ResNet50

8

FP16

1586.87

3055.66

TensorRT

ResNet50

16

FP16

1783.91

3381.72

TensorRT

ResNet50

32

FP16

1989.28

3695.88

TensorRT

ResNet50

64

FP16

2105.81

3889.35

TensorRT

ResNet50

128

FP16

2205.25

3901.94

从上述实际测试结果可以看出,基于不同框架下的性能结果接近1:2,调度策略算法能够支持Ampere系列显卡。以下测试以其它系列显卡T4和P4为例,基于TensorFlow框架推理ResNet50模型,实测性能结果同样接近1:2。

综合以上不同场景,不同算力的GPU显卡测试数据,使用cGPU能够指定每个容器的算力大小,限制了多容器之间的争抢,从而保障高优先级的容器获得更多的算力。算力调度算法能够支持Ampere、Volta、Turing以及Pascal等多种NVIDIA GPU架构,可以为企业客户定制适合实际场景的调度策略。

cGPU服务多卡划分示例

本示例以设置4卡为例,设置0卡为3 G、1卡为4 G、2卡为5 G、3卡为6 G。多卡划分示例代码如下所示:

docker run -d -t --runtime=nvidia  --name gpu_test0123 --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 -v /mnt:/mnt -e ALIYUN_COM_GPU_MEM_CONTAINER=3,4,5,6 -e ALIYUN_COM_GPU_MEM_DEV=23 -e NVIDIA_VISIBLE_DEVICES=0,1,2,3 nvcr.io/nvidia/tensorflow:21.03-tf1-py3
docker exec -i gpu_test0123   nvidia-smi

执行结果显示如下,您可以看到4卡显存详情。

多卡设置显存参数(即ALIYUN_COM_GPU_MEM_CONTAINER参数)说明如下所示:

参数取值

说明

ALIYUN_COM_GPU_MEM_CONTAINER=3

表示4卡的显存都被设置为3 G。

ALIYUN_COM_GPU_MEM_CONTAINER=3,1

表示4卡的显存依次被设置为3 G、1 G、1 G、1 G。

ALIYUN_COM_GPU_MEM_CONTAINER=3,4,5,6

表示4卡的显存依次被设置为3 G、4 G、5 G、6 G。

ALIYUN_COM_GPU_MEM_CONTAINER未设置

表示禁用cGPU服务。

ALIYUN_COM_GPU_MEM_CONTAINER=0

ALIYUN_COM_GPU_MEM_CONTAINER=1,0,0

好啦!小弹的分享到此为止。我们更欢迎您分享您对阿里云产品的设想、对功能的建议或者各种吐槽,请扫描提交问卷并获得社区积分或精美礼品一份。https://survey.aliyun.com/apps/zhiliao/P4y44bm_8

【扫码填写上方调研问卷】

欢迎每位来到弹性计算的开发者们来反馈问题哦~

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
2月前
|
关系型数据库 MySQL Linux
Docker安装Mysql5.7,解决无法访问DockerHub问题
当 Docker Hub 无法访问时,可以通过配置国内镜像加速来解决应用安装失败和镜像拉取超时的问题。本文介绍了如何在 CentOS 上一键配置国内镜像加速,并成功拉取 MySQL 5.7 镜像。
394 2
Docker安装Mysql5.7,解决无法访问DockerHub问题
|
29天前
|
Prometheus 监控 Cloud Native
基于Docker安装Grafana和Prometheus
Grafana 是一款用 Go 语言开发的开源数据可视化工具,支持数据监控和统计,并具备告警功能。通过 Docker 部署 Grafana 和 Prometheus,可实现系统数据的采集、展示和告警。默认登录用户名和密码均为 admin。配置 Prometheus 数据源后,可导入主机监控模板(ID 8919)进行数据展示。
70 2
|
2月前
|
负载均衡 应用服务中间件 网络安全
docker swarm添加更多的服务
【10月更文挑战第16天】
23 6
|
2月前
|
Docker 容器
docker swarm启动服务并连接到网络
【10月更文挑战第16天】
33 5
|
1月前
|
消息中间件 Linux RocketMQ
在Red Hat Enterprise Linux 9上使用Docker快速安装并部署
通过以上步骤,你可以在Red Hat Enterprise Linux 9上使用Docker快速安装并部署RocketMQ。这种方法不仅简化了安装过程,还提供了一个灵活的环境来管理和扩展消息队列系统。RocketMQ作为一款高性能的分布式消息系统,通过Docker可以实现快速部署和高效管理。
58 2
|
1月前
|
消息中间件 Linux RocketMQ
在Red Hat Enterprise Linux 9上使用Docker快速安装并部署
通过以上步骤,你可以在Red Hat Enterprise Linux 9上使用Docker快速安装并部署RocketMQ。这种方法不仅简化了安装过程,还提供了一个灵活的环境来管理和扩展消息队列系统。RocketMQ作为一款高性能的分布式消息系统,通过Docker可以实现快速部署和高效管理。
37 3
|
2月前
|
负载均衡 网络协议 关系型数据库
docker swarm 使用网络启动服务
【10月更文挑战第15天】
30 4
|
2月前
|
关系型数据库 MySQL Linux
基于阿里云服务器Linux系统安装Docker完整图文教程(附部署开源项目)
基于阿里云服务器Linux系统安装Docker完整图文教程(附部署开源项目)
295 3
|
2月前
|
Docker 容器
docker swarm 在服务中使用网络
【10月更文挑战第14天】
27 2
|
2月前
|
人工智能 自然语言处理 数据可视化
阿里云AI大模型助力客户对话分析——全方位提升服务与体验
随着数字化转型的推进,企业愈发重视客户互动数据的价值。阿里云推出了一套基于AI大模型的客户对话分析解决方案,通过自动化手段分析大量客户对话数据,提取有价值信息,优化服务流程,提升客户体验。本文将结合技术文档和实际体验,全面评测这一解决方案。
74 2

热门文章

最新文章