一、cpu与gpu的区别
cpu:擅长逻辑控制,串行的运算,cpu就好像是一个厉害的老博士,任何复杂的数学题都会
gpu:擅长大规模并发计算,gpu就好像是一群只会简单加减法的小学生,每个小学生都只能算简单的题目,但是gpu是组织了一大群小学生一起来算
现实场景,比如人工智能领域的图像识别,需要的不是大量复杂的逻辑判断与运算,而是大量的简单运算,此时cpu就不好用了,gpu最合适
GPU的工作大部分就是这样,计算量大,但没什么技术含量,而且要重复很多很多次。就像你有个工作需要算几亿次一百以内加减乘除一样,最好的办法就是雇上几十个小学生一起算,一人算一部分,反正这些计算也没什么技术含量,纯粹体力活而已。而CPU就像老教授,积分微分都会算,就是工资高,一个老教授资顶二十个小学生,你要是富士康你雇哪个?GPU就是这样,用很多简单的计算单元去完成大量的计算任务,纯粹的人海战术。这种策略基于一个前提,就是小学生A和小学生B的工作没有什么依赖性,是互相独立的。很多涉及到大量计算的问题基本都有这种特性,比如你说的破解密码,挖矿和很多图形学的计算。这些计算可以分解为多个相同的简单小任务,每个任务就可以分给一个小学生去做。但还有一些任务涉及到“流”的问题。比如你去相亲,双方看着顺眼才能继续发展。总不能你这边还没见面呢,那边找人把证都给领了。这种比较复杂的问题都是CPU来做的。 总而言之,CPU和GPU因为最初用来处理的任务就不同,所以设计上有不小的区别。而某些任务和GPU最初用来解决的问题比较相似,所以用GPU来算了。GPU的运算速度取决于雇了多少小学生,CPU的运算速度取决于请了多么厉害的教授。教授处理复杂任务的能力是碾压小学生的,但是对于没那么复杂的任务,还是顶不住人多。
当然现在的GPU也能做一些稍微复杂的工作了,相当于升级成初中生高中生的水平。但还需要CPU来把数据喂到嘴边才能开始干活,究竟还是靠CPU来管的。
cpu与gpu的设计区别:https://egonlin.com/?p=7543
拓展阅读
Nvidia中文名英伟达,1999年,NVIDIA定义了GPU,这极大地推动了PC游戏市场的发展,重新定义了现代计算机图形技术,并彻底改变了并行计算
NVIDIA Tesla GPU系列P4、T4、P40以及V100是Tesla GPU系列的明星产品
当下计算行业正在从只使用CPU的“中央处理”向CPU与GPU并用的“协同处理”发展。
CPU负责数据的逻辑处理,然后将处理好的数据交给GPU进行大规模的运算。
为此,NVIDIA™(英伟达™)发明了CUDA这一编程模型,它提供了可以直接调用GPU硬件接口,可用于在应用程序中充分利用CPU和GPU各自的优点
二、在容器中使用gpu
2.1 nvidia-docker1.0
NVIDIA于2016年开始设计NVIDIA-Docker已便于容器使用NVIDIA GPUs。
第一代nvidia-docker1.0实现了对docker client的封装,并在容器启动时,将必要的GPU device和libraries挂载到容器中。但是这种设计的方式高度的与docker运行时耦合,缺乏灵活性。存在的缺陷具体如下:
- 设计高度与docker耦合,不支持其它的容器运行时。如: LXC, CRI-O及未来可能会增加的容器运行时。
- 不能更好的利用docker生态的其它工具。如: docker compose。
- 不能将GPU作为调度系统的一种资源来进行灵活的调度。
- 完善容器运行时对GPU的支持。如: 自动的获取用户层面的NVIDIA Driver libraries, NVIDIA kernel modules, device ordering等。
基于上面描述的这些弊端,NVIDIA开始了对下一代容器运行时的设计: nvidia-docker2.0。
2.2 nvidia-docker2.0
先简单介绍下nvidia-docker 2.0与ontainerd、vidia-container-runtime、ibnvidia-container以及runc之间的关系
它们之间的关系可以通过下面这张图关联起来:
- 1、nvidia-docker 2.0
nvidia-docker2.0 是一个简单的包,它主要通过修改docker的配置文件/etc/docker/daemon.json来让docker使用NVIDIA Container runtime。 - 2、nvidia-container-runtime
nvidia-container-runtime 才是真正的核心部分,它在原有的docker容器运行时runc的基础上增加一个prestart hook,用于调用libnvidia-container库。 - 3、libnvidia-container
libnvidia-container 提供一个库和一个简单的CLI工具,使用这个库可以使NVIDIA GPU被Linux容器使用。 - 4、Containerd
Containerd主要负责的工作是:- 管理容器的生命周期(从容器的创建到销毁)
- 拉取/推送容器镜像
- 存储管理(管理镜像及容器数据的存储)
- 调用runc 运行容器
- 管理容器的网络接口及网络
containerd接收到请求之后,做好相关的准备工作,可以选择自己调用runc也可以通过创建containerd-shim再去调用runc,而runc基于OCI文件对容器进行创建。
- 5、RunC
RunC 是一个轻量级的工具,它是用来运行容器的,只用来做这一件事,并且这一件事要做好。我们可以认为它就是个命令行小工具,可以不用通过 docker 引擎,直接Runc运行容器。事实上,runC 是标准化的产物,它根据 OCI 标准来创建和运行容器。而 OCI(Open Container Initiative)组织,旨在围绕容器格式和运行时制定一个开放的工业化标准。直接使用RunC的命令行即可以完成创建一个容器,并提供了简单的交互能力。
上面已经介绍个各个组件的作用以及它们之间的关系,接下来详细的描述下这张图:
-
1、正常创建一个容器的流程是这样的:
docker –> dockerd –> containerd–> containerd-shim –>runc –> container-process
docker客户端将创建容器的请求发送给dockerd, 当dockerd收到请求任务之后将请求发送给containerd, containerd经过查看校验启动containerd-shim或者自己来启动容器进程。
创建一个使用GPU的容器 -
2、创建GPU容器的流程如下:
docker–> dockerd –> containerd –> containerd-shim–> nvidia-container-runtime –> nvidia-container-runtime-hook –> libnvidia-container –> runc — > container-process
基本流程和不使用GPU的容器差不多,只是把docker默认的运行时替换成了NVIDIA自家的nvidia-container-runtime。
这样当nvidia-container-runtime创建容器时,先执行nvidia-container-runtime-hook这个hook去检查容器是否需要使用GPU(通过环境变NVIDIA_VISIBLE_DEVICES来判断)。如果需要则调用libnvidia-container来暴露GPU给容器使用。否则走默认的runc逻辑。
说到这里nvidia-docker2.0的大体机制基本就通了。但是涉及到的nvidia-container-runtime, libnvidia-container, containerd,runc这些项目, 这本篇文章里面就不一一介绍了。如果感兴趣可以自行去探索学习。这些项目的地址在文章中都已经做个相关的链接。
参考
NVidia Containter Runtime
NVidia Dev Blogs
OpenContainers Runtime Spec Config
OpenContainers Runtime Spec
NVidia Container Runtime
RunC
libnvidia container
2.3 docker19使用GPU
随着docker的不断升级,对GPU的支持也越来越友好,尤其是docker19.03之后,不再需要安装nvidia-docker了。只安装NVIDIA-CONTAINER-RUNTIME就可以使用了,并且支持docker-compose。
本文记录和梳理一下想要在docker中使用GPU,都需要做些什么。
(1)下载GPU的驱动
在NVIDIA驱动程序页面下载对应的驱动。
(2)安装NVIDIA-CONTAINER-RUNTIME
在https://nvidia.github.io/nvidia-container-runtime/查看支持的操作系统和版本,并根据对应选项,添加源,因为我是centos7.6,所以添加方式为:
在参考https://github.com/NVIDIA/nvidia-container-runtime后,得知直接安装即可
(3) 直接使用
此时就准备好了GPU环境,在docker19下就能通过–gpus参数直接使用了,安装docker19略
查看–gpus 参数是否安装成功:
从Docker 19.03开始,安装好docker之后,只需要使用 –gpus 即可指定容器使用显卡。
以上就完成了GPU的准备,可以使用了。(如果指定某一张卡可以使用选项:–gpus "device=0")
强调:容器内可以使用gpu的必备条件
1、物理机主机插有gpu卡
2、物理机操作系统安装了gpu驱动程序
3、安装了docker19.0.3版本
4、启动容器时采用临时参数–gpus指定启用gpu,或者修改配置文件永久修改
5、容器镜像必须包含cuda环境才能使用
当你发现容器内部发现CUDA Version: N/A,就是因为容器内没有cuda的driver接口,需要在镜像里定制好 ,如下制作一个带有cuda环境的java镜像(注意cuda版本)。
使用docker build -t nvidia-java:1.0.0 .打包镜像。
之后再使用的话在此基础上进行封装就可以了,比如:
更多操作
2.4 修改容器的runtime为nvdia-runtime
如果我们嫌弃每次启动容器是都指定–gpus参数很麻烦,那么我们可以直接把默认的Runc替换为nvidia-runtime,这样每次你启动容器是,就不用加–gpus参数了,默认容器内就可以用gpu,当然容器镜像里有cuda环境
为docker环境安装Nvidia-container-runtime
1、对于已经安装好docker的CentOS系统
2、对于已经安装好docker的Ubuntu系统
(1). 首先配置nvidia源
(2)、参考https://gitee.com/wuxler/nvidia-container-runtime?_from=gitee_search 安装nvidia-container-runtime
(3)、验证
2.5 关于gpu信息的说明
显示所有GPU的当前信息状态:
nvidia-smi
查询所有GPU的当前详细信息:
nvidia-smi -q
设备监控命令,以滚动条形式显示GPU设备统计信息:
nvidia-smi dmon
进程监控命令,以滚动条形式显示GPU进程状态信息:
nvidia-smi pmon
实时监测并高亮显示状态:
watch -n 1 -d nvidia-smi,1代表间隔1s刷新。