Nvidia DeepStream和Triton Server学习经验分享

  • Post author:
  • Post category:其他




一、前言


“If I have seen further it is by standing on the shoulders of giants.”


-Issac Newton.

Nvidia出品的人工智能工具太多了,每次GTC大会上都让人惊艳一把,感觉用都用不过来,好用的工具对于工作效率的提升不言而喻,但也要警惕不要让自己变成调包侠,最近在的工作内容涉及到一些云边协同的需求,就去研究了一下Nvidia的两个明星工具,DeepStream和Triton Server,结合工作讲讲自己的认识分享给大家。



二、DeepStream

DeepStream是Nvidia基于Gstreamer做的音视频处理SDK,基于模块化的设计和封装方法,将音视频处理的整个流程按照功能划分成不同的模块,然后通过构建pipeline的方法实现整个音视频文件的处理。

学习DeepSteam之前还是要先了解一下Gstreamer的,看看Gstreamer的官方文档有一个基础的认识还是很重要的,

Gstreamer官方文档地址

,Gstreamer的学习成本偏高,建议先看看Basic Tutorials,掌握几个重要概念和方法,我学习过程中觉得比较重要的代码在github仓库记录下来了,感兴趣可以看看,

这些

是我比较关注的一些基础内容,在代码里写了一些Reminder提醒自己需要关注的点:



1.组件(element):

element几个主要的元素有source,filter,sink,pad,bin,bus,pipeline

Gstreamer的功能实现像是搭输油管道(pipeline),每一截管道就是一个Gstreamer的element,管道直接通过pad相互连接焊在一起,所有的管道连接(link)在一起后,形成一个bin,为了查看管道的实时状态,反馈给用户,在bin里加入了消息机制bus,这样就形成了一个基础的pipeline,音视频流就像油一样经由source流入,在pipeline里流淌,每一截管道可能会对流做不同的处理,使最终流出的流达到用户想要的模样。



2. Gstreamer工具:

个人觉得Gstreamer的核心工具使gst-inspect,通过整个工具可以详细的查看每个组件的使用方法,更重要的使了解组件之间的pad通过什么方式连接,这个涉及到pipeline的构建方式,为了满足不同的构建方式,element的pad有不同的状态(Sometimes,Requeset,Always),pipeline的构建方式决定了pad状态的区别,用的时候直接查element需要怎么连,给他提供对应的连接方式就可以了。



3. pipeline构建方法:

以下是我在视频处理种觉得常用和比较重要的两个pipeline构建方法,DeepStream的构建方法也不太会跳出这两个方法



(1)动态构建方法

动态构建是指有了视频流输入之后再link整个pipeline,形成完成的功能,这个功能的实现涉及一个核心:回调函数和信号机制的使用,Gstreamer提供了对应的API函数,当有数据源接入的时候触发回调函数进行pipeline连接。



(2)多线程构建方法

音视频处理的多线程处理比较常见,Gstreamer提供了queue组件作为多线程的构建方法,重点了解以下queue怎么用就可以实现基本的功能



4.DeepStream

DeepStream继承了Gstreamer的思想,实现了很多自定义的插件或者element去完成自己的功能,目前支持的功能有目标检测、实例分割和分类检测。

了解DeepStream的第一步是先跑跑demo,DeepStream提供了很多test文件,基本涵盖了视频处理的主要应用场景:多视频处理、模型级联推理、不同格式源视频处理、检测结果上传至云。设置以下config文件基本就能实现给定的功能。而后就是要深入了解DeepStream实现的几个比较常用的插件。装好DeepStream后,这些element都可以通过gst-inspect查看具体的内容。

知乎用户

JuLec

做了很多Nvidia组件翻译、介绍的工作,推荐大家看看。



(1) Metadata

DeepStream设计的数据结构,如下所示,

以下图片引自知乎用户向南的蜗牛.


这个数据结构基本就是按照目标检测的需求设计的,一层层包裹形成Metadata,有一个frame_user_meta_list供用户定制自己的数据结构。

Metadata数据结构



(2)Gst-nvstreammux

Gst-nvstreammux 插件从多个输入源形成一批帧进行batch推理。



(3)Nvinfer

这个模块其实包含了图像的前处理和推理的功能,DeepStream提供的Gst-nvdspreprocess 主要是做了ROI选择的工作。



(4)Gst-nvdosd

在屏幕上显示实时的检测结果,画框和写文本。



5.Deepstream使用感悟

基于YOLO系列的目标检测社区已经做的相当完备了,如果自己的应用需求局限于多路视频目标检测的话,我觉得DeepStream是一个不错的选择,配置一下config文件,基本实现无脑运行。但如果是有自己的定制化开发想法,我倒是觉得不一定要用DeepStream,我个人初衷是想基于DeepStream实现一个多路的无监督算法推理过程,就目前的认知来看,用DeepStream去做,Nvinfer和Medata需要自己重新设计,基于probe的数据获取也不是那么友好,流复用的操作自己可以封装实现,和直接基于Gstreamer去做其实没差多少了。

Gstreamer的C代码风格我个人是挺难接受的,可能是自己太菜了,阅读代码过程比较痛苦,这么开发难度也比较大。如果大家是新手,也没有强制使用DeepStream的需求,不建议投入太多时间搞Gstreamer,我个人觉得学习成本还是挺高的。

从程序设计模式的角度,我们自己也可以实现打batch的接口,和nvinfer、nvosd对象一起,再搞个责任链模式,一起把pipeline构建起来,感兴趣的可以看这个

SNPE

仓库的实现。



三、TritionServer

Triton-inference-server是Nvidia开源的一个基于云端服务器推理的项目,支持各种主流的推理框架,支持面向对象的C++、Python、Java编程语言,仓库在

这里

,各个模块独立为仓库去维护。



1.前置知识

了解TritionServer需要一些前置知识,从Triton架构设计的角度分成主要分为两块:



(1)模型部署推理

在server端,需要实现模型repo的构建,需要了解推理部署的一些基本内容,具体的内容可以参加该

文章

,我们可以不需要了解的太深入,但推理前后处理,不同的推理框架要有一个基础的认识。



(2)网络编程基础知识

在client端,需要用户发起推理请求,通过http/grpc的方式将请求传输至监听请求的server端口,这样才能在server端进行推理并返回结果。首先,我们需要了解网络协议,明白http或者grpc是出于应用层,基于TCP建立起来的;了解什么是http,什么是grpc,他们之间有什么关联和区别;TCP通信的基本建立流程,什么是套接字,三次握手、四次挥手都干了些啥;更进一步IO多路复用和多线程实现并发服务的实现方法是什么(可以先不掌握),有了这些基础的认识之后再去接触Triton官方的

client仓库

,这样看代码会容易些。Triton的功能实现和封装屏蔽了一些上面提到的知识,但都是基于这些去实现的。



2.架构设计

整个Triton的架构设计如下图所示,包括Client端和Server端,在服务端主要是搭建推理流程,设置推理时的模型参数、调度参数,实现云端的模型推理;在客户端主要实现用户的请求处理,回收响应后的结果。推理肯定是在Server端完成的,前后处理在client端还是server就看用户的需求了。

架构设计图



3. 核心功能

Server端的核心功能就是模型仓库的建立和服务模式的实现,主要涉及两个仓库:



(1)

server仓库

该仓库介绍了如何构建TritonServer实现一个推理服务,官方推荐基于docker构建,直接从nvcr.io拉取镜像启动即可,考虑到driver支持版的限制,请大家选择适合自己系统的tritonserver版本。模型仓库构建好之后,很快就能启动一个docker服务,大家可以自己试试。



(2)backend仓库

该系列仓库是Triton模型推理的后端支持,torch/tensorflow/tensorrt/onnx这些主流的模型推理都是支持的,backend仓库里包含了这些后端的具体实现,我个人比较感兴趣的是

python_backend

,用户可以基于python_backend方便的实现模型的前后处理、这样通过Triton提供的ensemble模型调度机制,在server能够快速地实现前处理、模型推理、后处理的集成,用户端就发送请求就可以了,这样可以屏蔽用户端处理带来的不确定性错误,只开放给用户发送请求的接口即可。



(3)

client仓库

该仓库是用户请求的实现仓库,主要基于http/grpc提供了大量的实例,Triton将请求的实现封装成了tritonclient对象,python端可以直接通过pip安装,通过pydoc去查看tritonclient方法的功能介绍,或者通过对应的library查看功能的设计理念,我觉得基于Python实现推理请求比较快捷,而且如果前处理、推理、后处理都在server端实现,C++带来的速度收益没那么明显,反而增加了开发难度。



4. Triton使用感悟

虽然和DeepStream不是一个维度的工具,但Triton的开放性、扩展性明显更好,面向对象的代码设计也更容易阅读和理解,代码的封装屏蔽了很多细节,让用户能够更聚焦于业务,不去关注太多细枝末节的东西,当然个人觉得这些细枝末节全是满满的技术干货,值得去深入阅读。

近几年各大厂都在发力云计算,大模型的涌现更是对基于云端的推理服务提出了更加广阔的需求,作为一个入行就从事边缘计算的工程师,我现在觉得云端的推理服务调度及优化也是一个值得深入研究和探索的领域,云端部署能够很好地弥补边缘端小模型精度差的问题,对于网络环境良好、对实时性要求不高的场景,云端推理部署大有可为。



四、总结

个人觉得DeepStream和Triton Server都是基于面向对象程序设计模式对深度学习算法的高度封装,为用户提供了快速开发的接口,因此除了享受这种便捷带来的效率提升外,也要关注Nvidia在软件开发种倾注的精力,学习优秀的设计模式和设计风格,不让自己的代码编程屎山!



版权声明:本文为u011268946原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。