深度学习技术的发展仰赖硬件的支持,检验新提出的网络模型结构、机器学习算法,人工智能应用生产级别的训练和推理,对高效处理数据、快速响应的图形处理器的需求很大。图形处理器(GPU)针对不同领域的应用场景进行优化和细分:游戏领域叫显卡,建模绘图、剪辑渲染和影视后期等设计领域叫图形卡,AI智能运算、地球天气模拟等计算场景叫计算卡,挖掘网络货币叫矿卡,GPU在所属的专业领域表现出的性能和效果更为突出。Nvidia、AMD、华为、寒武纪等厂商提供在计算场景下的GPU硬件支持,Nvidia发布基于Turing、Ampere和Volta架构的GPU,AMD发布RADEON显卡,华为有晟腾计算卡,寒武纪有思元边缘AI加速卡,布局AI计算的产品赛道和营销策略。面对市场上出现的不同显卡,使用统一的基准测试方法,衡量GPU的算力和性能表现,比较出孰优孰劣,分析发现每个显卡的特点、优势和缺陷,指导市场中的GPU选购。
我们对英伟达的四张显卡,RTX2080、T4、A100、V100进行基准测试,测量MLPerf基准测试中使用的神经网络模型在各个板卡和TensorRT、Tensorflow、Pytorch三种框架下完成推理的性能指标。
我们的测试对象——RTX2080借助Turing架构,在游戏领域大显身手。T4、A100和V100都是计算卡。T4基于Turing架构,采用节能高效的小尺寸PCIe封装,配备多精度Tensor Core和新的RT Core。A100由Ampere架构提供支持,我们测试的产品是适用于PCIe的40GB显存的版本。V100推出的时间比A100早,采用Volta架构,我们测试的产品是32GB显存的PCIe版本。
MLPerf基准测试中使用的模型有resnet50、mobilenet、ssd-mobilenet、ssd-resnet34、bert和3d-unet,在这项推理测试任务中,我们额外采集yolov3模型在各显卡的性能数据。resnet50可用于目标分类领域,“50”指有50个层。Mobilenet发挥其高精度低延迟的优点,高效准确完成大量图像分类任务,模型计算复杂度和模型大小都较低。Yolov3面向图像检测领域,使用一个单独的神经网络应用在图像上,将图像划分为多个区域并预测边界框和每个区域的概率。ssd-mobilenet以mobilenet为主干网络进行特征提取,使用SSD目标检测。ssd-resnet34以resnet34为主干网络进行特征提取,使用SSD目标检测。BERT使用双向结构的transformer,将传统大量在下游具体NLP任务中做的操作转移到预训练词向量中,在获得使用BERT词向量后,只需在词向量上加简单的MLP或线性分类器即可。3d-unet是一种从稀疏注释的立体数据中学习三维分割的网络,用2D标注数据训练,完成3D数据分割。
对于测试的AI框架:TensorRT是可以在Nvidia各GPU硬件平台下运行的C++推理框架。如图1所示,TensorRT转换Pytorch、TF或其他框架训练好的模型为TensorRT格式,利用TensorRT推理引擎去运行模型,显著提升模型在Nvidia GPU上运行的速度。TensorRT的加速效果不仅取决于模型的类型和大小,也取决于所使用的显卡类型。GPU更适合并行计算和密集型计算,TensorRT基于GPU优化,对于通道数比较多的卷积层和反卷积层,优化效果强;对于比较繁多复杂的各种细小op操作(如reshape、gather、split等),优化力度没有那么夸张。TensorRT生成针对单个Nvidia显卡、单个网络模型、单种精度、单种batch大小的推理二进制文件,TensorRT的trtexec程序执行优化后的推理文件。Tensorflow和Pytorch是研究机器学习算法和开发AI应用的开源框架。
对于测试的精度:FP32(Full Precise Float 32,单精度)占用4字节,其中1位为符号位,8位指数位,23位尾数位。FP16(半精度)占用2个字节,其中1位符号位,5位指数位,10位有效数字位。INT8占用一个字节,代表整数运算,一般由浮点运算量化而来。从FP32到FP16再到INT8,精度承载的数据量减小,能耗降低,计算速度更快,更符合端侧运算的特点。训练阶段,梯度的更新往往微小,需要较高的精度,一般用到FP32以上,推理阶段,精度要求不高,可以使用FP16和INT8,同时低精度的模型占用空间更小,有利于部署在嵌入式模型里面。
对于推理测试时数据的batch大小:batch越大,一次推理流程中喂入神经网络中的数据越多,得到所有结果的延迟越长。GPU对2的幂次的batch大小发挥更佳的性能,我们在测试中设置batch大小为1,2,8,32,128等。
测量的指标包含:
1. GPU延迟和端到端延迟。GPU延迟包含Host to Device延迟、Device to Host延迟、端到端延迟和数据传输延迟,端到端延迟指数据从喂入神经网络到计算出结果花费的时间,GPU延迟一定比对应的端到端延迟长,TRT(TensorRT)框架内嵌有计算一次batch数据的GPU延迟和端到端延迟的接口,而TF(Tensorflow)和PTH(Pytorch)需要我们实现计算端到端延迟的方式,TF和PTH的代码无法衡量计算GPU延迟的开始时间和结束时间。
2. 功耗、温度和SM时钟频率。功耗反映能源消耗量,温度指显卡的温度,SM全称Stream Multiprocessor,是一种单指令多线程架构的处理器,含有指令发射单元及若干流处理器等,N卡(Nvidia生产的GPU)里的计算单元是SM,可快速完成矩阵的乘加运算。GPU工作时有最高功率和最高温度的限制,当GPU的功率或温度超过此限制时,SM时钟频率下降,GPU性能降低。GPU利用率越高,功率和温度升高越快,SM始终频率下降越快,GPU的性能越容易变低。
3. GPU利用率、显存利用率和FB Memory使用量。使用N卡的nvidia-smi命令获取GPU工作时的属性值,单位采样时长中GPU运行的时间比率是GPU利用率,单位采样时长中显存读写数据的时间比率是显存利用率,FB Memory是板上帧缓存占用的显存使用量,这些指标反映推理测试时GPU资源的使用情况。
4. CPU利用率和内存使用量。使用top命令得到指定进程的CPU和内存使用量,反映推理测试时CPU资源的使用情况。
推理测试使用的服务器有两个,每个服务器有3个插槽插显卡接口,42服务器上插有RTX2080、T4、A100,40服务器上插有V100。配置好服务器的CUDA环境,测试流程分为三步:采集数据、处理数据和分析数据。
由于不同框架使用的环境不同,不同框架的推理测试需要分开说明。除了BERT的输入数据是一短串序列,其他网络模型的输入数据均是随机数,该推理测试极大减小数据CPU端前处理的延迟,主要考察GPU处理数据的能力。
启动Nvidia的TensorRT docker容器,完成TRT框架的推理测试。
TRT推理测试脚本接收指定batch大小、模型类型、精度类型、设备名、测试时长、测试id和存放数据的主目录的参数。脚本参数的默认值在执行时可被覆写。对不同设备、网络、精度和batch大小构建推理测试命令。resnet50、mobilenet和yolov3模型从onnx文件转换为trt文件,其他模型转换出的适用于TRT测试的plan文件和插件配置在trtexec命令中。执行推理测试的trtexec命令接收的参数有加载推理引擎的文件路径、GPU id、trtexec命令执行时长、统计记录延迟数据的轮次频度、输入数据键名和路径、输入数据shape、插件路径和精度参数。执行测试命令之前,启动监测CPU和GPU参数的脚本。命令执行中输出流写入test_log中。执行后统计latency的平均值,提取test_log、存储监测到的CPU和GPU数据的文本文件的有效数据转换成相应指标的excel表。
监测GPU参数的脚本检测含有trtexec字符串的进程是否运行,没运行脚本最长等待300秒,超时退出,检测到运行的进程后,用“nvidia-smi -q -i $gpu_id”查询GPU的所有参数,写入gpu_log中,睡眠1秒,trtexec进程停止运行之后脚本退出。
监测CPU参数的脚本在300秒内检测到运行的trtexec进程,否则退出。检测到进程后每隔一秒使用top命令获取进程的CPU占用率和内存占用量写入cpu_log中,进程停止后脚本退出。
从test_log中提取出推理测试中的每10轮推理的GPU延迟和端到端延迟,切割出指标对应的字符串值,存入test_excel的对应batch的sheet中。
从cpu_log中提取出推理测试中每一秒时CPU的利用率和内存使用量,切割出指标对应的字符串值,存入cpu_excel的对应batch的sheet中。
从gpu_log中提取出推理测试中每一秒时GPU的功率、温度、SM时钟频率、GPU利用率、显存利用率和FB Memory使用量,转换nvidia-smi命令的输出为树,取出叶节点的指标值存入gpu_csv中。
resnet50、mobilenet、yolov3三个网络模型从onnx转换为trt文件的脚本,接收的参数是TRT推理测试脚本参数的子集,没有与测试和数据存储相关的参数。使用trtexec转换onnx文件为某一精度、某一batch大小、运行在某一GPU上的推理引擎,每个网络需要指定推理时数据输入的节点名和shape。
启动Nvidia的Tensorflow docker容器,完成TF框架的推理测试。
TF推理测试脚本的逻辑与TRT推理测试脚本一致,主要的区别是推理测试执行的命令。BERT模型运行bert_pb_inference_test.py,其他模型测试运行pb_inference_test.py,bert_pb_inference_test.py比pb_inference_test.py多了预处理短串序列和将处理后的数据喂入BERT中的操作。pb_inference_test.py接收的参数有pb模型的路径、输入节点名、输出节点名、迭代次数、batch大小、GPU id、测试时长和输入数据的shape,从pb模型加载网络定义图,根据输入输出节点名从图获得张量节点,生成输入shape的随机数,喂入网络,运行会话,端到端延迟是会话运行的时长,当推理时间超过测试时长或推理轮次超过迭代次数,脚本退出推理的循环。统计每一迭代的端到端延迟和测试流程中的平均吞吐量,打印到输出流中。由于推理测试命令是python构建的,CPU和GPU监测脚本随着带有python字符串的进程启动而启动,终止而终止。TF推理测试涉及到的精度只有FP32,因为测试中使用的pb模型的权重精度是FP32。TF的代码粒度导致我们不能采集GPU延迟的数据。其他部分的实现逻辑与测试TRT框架一致。
启动Nvidia的Pytorch docker容器,完成PTH框架的推理测试。
PTH的推理测试流程和TF一致。从TF框架转到PTH框架,改变的地方是两个框架之间的不同之处,TF完成推理会话的执行需要网络模型的输入和输出节点名,PTH则不需要,PTH的推理函数是加载到设备上的模型做forward。MLPerf没有提供resnet50、mobilenet的pth文件,使用onnx的后端运行onnx文件完成没有pth文件的网络的推理测试流程。pytorch加载其他网络的pth文件并推理,依赖其他库,比如bert模型依赖transformers库,如果python环境中没有transformers,bert的推理测试脚本执行报ModuleNotFound错误。
采集到的excel表中依据测试的五个维度的每种情况分为延迟数据表、CPU数据表和GPU数据表,延迟数据表由某一迭代的延迟数据行组成,CPU数据表由某一秒的CPU数据行组成,GPU数据表由某一秒的GPU参数组成。由采集到的数据绘出某一GPU某一模型某一精度某一框架下某指标各batch变化的折线图。
绘图脚本获取各精度统计数据所在目录、模型名、GPU名、生成折线图的宽度、高度和分辨率、处理的batch大小列表、处理的精度列表、是否从0画时钟频率图、框架名的参数,从采集的数据表中根据batch大小将指标值写入summary_excel对应指标的sheet表,sheet表的列名是各batch大小,配置好matplotlib的图像,传入横坐标列表和纵坐标指标列表绘图。
除了绘图,填写GPU框架模型下各精度、各batch大小的推理测试中平均延迟、平均吞吐量、平均功率、模型大小、平均能效比的数据。
查看处理好的折线图和不同测试的指标平均数据,给出不同测试的结果描述、原因分析和可能存在的问题。
使用TRT框架测试的一些结论:
1. 2080重视频率的稳定性,随着推理进行各batch延迟基本不变,时钟频率稳定在相近的值,功率差异大,batch越大功率越大且限制于最高工作功率,偶尔有抖动
2. T4重视低功率的稳定性,虽然时钟频率伴随batch增大和推理时间的增加有明显的下滑,功率维持在70W附近波动
3. T4和A100在推理进行的几十秒后,性能有所下降,因为温度的升高导致时钟频率的下降
4. 高batch的吞吐量比低batch高,延迟高,更加充分利用带宽带来数据处理量的提升,但一批次数据的处理花费的时间更长,带宽限制了数据处理的并发量。
5. 推理过程中显存和内存的使用量没有变化,TRT保证显存的空间预先分配好,若预分配失败,报错无法执行推理,推理使用的输入数据(特定shape的随机数)占用固定的内存空间
使用TensorFlow框架测试的一些结论:
1. Tensorflow框架下的模型容易在低batch时达到吞吐量瓶颈。使用高batch完成tf模型的推理没有合算的性价比。
2. 推理过程中显存和内存的使用量没有变化,TensorFlow保证显存的空间预先分配好。
3. GPU利用率和显存利用率随测试时间有明显的振荡周期,高batch的振幅更大。说明TF框架使用GPU推理和显存读写的时长粒度较大,单位采样时间中使用GPU太久或很少用。
4. 一次batch输入数据的延迟比TRT高。
没有仔细分析使用Pytorch框架推理测试的结果,作为TF框架的佼佼者,结果差不多,另外一些测试数据出现异常,需要分析问题的原因。
以上内容经过整理和修改,得到一个报告文档,供下载
本文创建于2021年7月19日14点40分,修改于2023.1.9/18.28