多个docker容器共享GPU方法

时间:2024-03-19 16:32:00

引言

最近容器比较火,容器支持对CPU和内存的资源限制,但是GPU还不是很明朗,多个容器能不能共享一个GPU呢?如果共享的话,是并行的方式还是并发的方式呢?又如何确保GPU的资源能够被高效利用呢?本文,通过查阅大量官方文档,并通过实验验证,想一探究竟~

问题描述

GPU是深度学习的利器,相比于CPU,并行化的执行方式能够实现更高的时间效率。同时,它的价格也比较昂贵,此次想要做实验的NVIDIA TESLA V100(32G)在京东标价就高达7万人民币,楼主没钱买智能在普通的GPU上做做实验。当一个学校或者一个公司配备了一个土豪级GPU,如果想要让所有人都能使用,同时考虑到系统安全问题,可以让每个用户的编程环境被约束在一个docker容器(container)中。目前,可以实现CPU和内存的虚拟化(即限制用户可用的CPU配额和内存空间)[1],甚至可以实时地调整配额[2],但GPU在容器中虚拟化的文章还是很少。

考虑这样一个问题,当多个用户同时在同一个GPU上提交作业时,GPU资源如何进行分配,现有的技术能否满足用户需求?

现有技术

多进程服务(Mutil-Process Service, MPS)为多进程CUDA应用提供了共享NVIDA GPU的途径。特别地,Volta MPS(即Volta架构的GPU所提供的MPS服务)相对于pre-Volta GPU还增加了独立GPU地址空间和资源限制的等特性,所以可以更好地确保的QoS[3]

MPS主要包括控制守护进程(MPS Control Daemo)、客户端运行时(Client Runtime)和服务进程(Server Process)。CUDA contexts可以通过MPS Server提交作业,这样就越过了硬件的时间切片调度的限制,实现多个进程在同一个GPU上并行执行。如果没有MPS,多个进程只是在同一个GPU上并发执行,即每个进程在一个时间分片里独享GPU。特别地,官网指出只有Volta MPS支持在docker容器中使用MPS。[4]

实验测试

  • 实验环境

显卡:GeForce GTX 1080 Ti,11G显存(pre-Volta架构)

系统环境:Ubuntu 16.04.5 LTS,kernel 4.4.0-31-generic,CUDA 8.0,NVIDIA-DOCKER 1.0

测试程序:矩阵乘法(运行时约占GPU显存197MB)

  • 实验过程

由于资源限制,未能在Volta架构GPU中测试。

经测试,GPU计算模式设置为“EXCLUSIVE_PROCESS”,在开启MPS control daemon的情况下docker容器无法初始化,会出现以下错误提示信息:

cudaMalloc d_A returned error all CUDA-capable devices are busy or unavailable (code 46), line(173)。

推测,容器初始化时,GPU端的MPS Server进程也同时启动,由于GPU计算模式为“EXCLUSIVE_PROCESS”,其他进程将服务获取GPU的服务。

此时,将GPU计算模式设置为“DEFAULT”,容器可以顺利启动并执行任务,但是并没有获得并行执行带来的性能提升。

对比图1和图2,10个容器同时在1个GPU上运行任务比1个容器在1个GPU上运行任务的性能差10倍多,推测此时多个容器在GPU上并发执行。

多个docker容器共享GPU方法

                                                                            图1:单个容器在GPU执行任务性能统计

 

多个docker容器共享GPU方法

                                                                           图2:多个容器在GPU上同时执行任务性能统计

  • 实验结果

在pre-Volta架构下的GPU中,MPS对docker容器不可用,但是在时间分片调度器的作用下,多个docker容器同时提交的任务依然可以在一个GPU上并发执行。

可行方案

方案一:Volta MPS(未验证)

在满足共享GPU的同时,最大化GPU利用率(多个进程并行计算),也能提供资源限制功能以保证QoS。另外,每个GPU支持48个并发client CUDA。

方案二:pre-Volta MPS

可以满足共享GPU,但是资源利用率比较低(小任务在一个时间片内独占整个GPU),同时无法确保QoS。假设一个用户提交一个很大的任务(占满整个GPU),其他用户将无法提交任务,并会收到“CUDA_ERROR_OUT_OF_MEMORY”的错误。但是,当GPU资源有剩余的情况时,其他用户依旧可以提交任务。考虑可以设置一个机制,用户在每次提交任务前,查看候选GPU的资源剩余量,然后手动切换满足要求的GPU,再提交任务。

结论

在pre-Volta 架构下的GPU,可以实现容器之间共享GPU,但是QoS无法保证,可以为用户提供实时切换GPU的功能。Volta架构下的GPU推测执行效率更高,如果有机会,楼主后续会继续做实验以证明。

 


[1] https://docs.docker.com/config/containers/resource_constraints/

[2] https://docs.docker.com/engine/reference/commandline/update/

[3] https://docs.nvidia.com/deploy/pdf/CUDA_Multi_Process_Service_Overview.pdf

[4] https://github.com/NVIDIA/nvidia-docker/wiki/MPS-(EXPERIMENTAL)