容器是如何调用GPU的

容器使用GPU的主要需求有两个:

  • 容器中可以查看GPU设备
  • 容器应用可以操作GPU显卡

Nvidia GPU对容器的支持具体可见:Enabling GPUs in the Container Runtime Ecosystem

Nvidia-docker

Nvidia推出Nvidia-docker套件以支持容器对GPU的操作。安装完Nvidia-docker后,在/etc/docker/daemon.jsonrumtimes中注册nvidia runtime,使用nvidia runtime运行的容器就可通过容器中的Nvidia驱动操作GPU显卡。

Nvidia-docker项目只是建立在容器层的设计,真正调用GPU的核心支持放在libnvidia-container。该库基于Linux内核原语,与更高的容器运行时层无关。这样就可以将GPU支持扩展到不同的容器环境中,例如Docker、LXC和CRI-O。该库包含一个cli工具并提供API以便继承到其他运行时环境中。Nvidia将容器使用GPU需要的运行时中的库、工具和层集成到Nvidia-container-runtime中。这个就是GPU容器在启动时指定的那个runtime。

Nvidia-container-runtime

是Nvidia维护的一个容器runtime,它对runc进行了二次修改(runc是一个根据OCI标准来创建和运行容器的轻量级工具),对所有指定nvidia runtime的容器注入一个自定义的pre-start hook,使容器支持GPU操作。

Nvidia-container-runtime的构建关系如图:

NVIDIA Container Runtime Docker GPU

Nvidia-container-runtime-hook是一个二进制包,作用是将当前容器中的信息收集并处理,转换为参数调用libnvidia-container的nvidia-container-cli工具。比如对环境变量NVIDIA_VISIBLE_DEVICES的处理,如果未指定或是void,则认为是非GPU容器,不做任何处理;否则调用nvidia-container-cli配置容器对GPU硬件的使用支持,将Nvidia 驱动库的so文件 和 GPU设备信息, 通过文件挂载的方式映射到容器中。环境变量中指定了哪几个GPU就挂载哪几个GPU。Nvidia-container-runtime-hook还负责传入容器GPU应用进程的Pid。

nvidia-container-cli的configure组件中负责挂载GPU的部分代码:

        /* Mount the driver, visible devices, mig-configs and mig-monitors. */
        if (perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_MOUNT], ecaps_size(NVC_MOUNT)) < 0) {
                warnx("permission error: %s", err.msg);
                goto fail;
        }
        if (nvc_driver_mount(nvc, cnt, drv) < 0) {
                warnx("mount error: %s", nvc_error(nvc));
                goto fail;
        }
        for (size_t i = 0; i < devices.ngpus; ++i) {
                if (nvc_device_mount(nvc, cnt, devices.gpus[i]) < 0) {
                        warnx("mount error: %s", nvc_error(nvc));
                        goto fail;
                }
        }

在容器中使用mount命令可以看到挂载的GPU

image-20201012210204065.png

使用nvidia-smi命令查看被映射的GPU卡


image-20201012210340046.png

你可能感兴趣的:(容器是如何调用GPU的)