前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NVIDIA VPI初探(1):用NVIDIA VPI高阶封装接口,快速开发GPU视觉应用

NVIDIA VPI初探(1):用NVIDIA VPI高阶封装接口,快速开发GPU视觉应用

原创
作者头像
GPUS Lady
修改2021-09-22 11:12:37
1.1K0
修改2021-09-22 11:12:37
举报
文章被收录于专栏:GPUS开发者GPUS开发者

NVIDIA在2021年初发布的VPI(视觉编程接口-Vision Programming Interface)到现在也有半年多的时间 (从NVIDIA发布VPI看NVIDIA的大局观),但似乎关注的眼球并不是那么密集,原因何在呢?说穿了就是大家的理解不够,还没感受到这个开发接口的好处。

有很多在NVIDIA设备开发视觉应用的工程师,大概都很清楚开发过程有很多痛苦的地方,特别是在处理图像格式/尺寸/颜色空间转换时,想要发挥GPU并行计算优势时,总得透过Numpy库与OpenCV或PIL的交互运作,在CPU与GPU之间不断地进行数据传输,然后调用底层CUDA库进行计算。

期间最麻烦的就是记忆体管理的部分,在一个计算中需要预先分配多大的显存空间,与设备所配置的显存大小息息相关,但是GPU种类这么多、配置的显存数量不一致,更深入的问题是,在支持统一内存(Unified Memory)的设备上(例如Jetson系列),可以使用更有效率的数据传输方式,这时候在代码上该如何处理,才能提高这个应用的通用性?

从NVIDIA发布VPI看NVIDIA的大局观文章里有提到NVIDIA对这些问题的概略描述,以及推出VPI编程接口的用意,大家可以回头先去看看文章里面所说的内容,这里就不多解释。

真正了解NVIDIA的开发者,都能感受到近年来他们在开发工具上,一直秉承着“高效、易用、兼容”三大原则去提供高阶封装的开发接口。

什么是“高阶封装接口”?并非只是使用C++或Python这些开发语言就算,关键点在于这些接口的“封装(encapsulation)”形式。一个高阶封装的开发接口至少得具备以下条件:

1.      能非常直观地从接口名称去识别其功能;

2.      单一指令就能执行许多的功能;

3.      资源之间的独立性,这里包括:

1)      硬件相关的接口:抽象出高阶API接口

2)      软件相关的接口:与其他功能库之间的调用与结果回传

3)      执行目标相关的接口:在生产环境中的资源优化

4.      自动处理底层计算资源(线程数、显存、CUDA流)的合理分配与最终释放的步骤

5.      接口的所有参数都提供(优化策略)预设值

高阶封装的指令让开发者可以忽略很多容易出错的细节之处,特别是数据类型以及大小的问题,在函数里面都做好对应的处理机制,这样会大大减少开发人员消耗在底层问题的纠错时间,会让开发者感受到设计者的细心与贴心,减少不必要的时间浪费以及挫折感。

下面提供一段对图像执行blur模糊除了的代码,让大家看一下VPI高阶封装指令的的易用性:

代码语言:javascript
复制
 ​import vpi
import numpy as np
from PIL import Image
from argparse import ArgumentParser

# 解析命令行的参数
parser = ArgumentParser()
parser.add_argument('input', help='Image to be used as input')
args = parser.parse_args();

# 加载输入并将其包装到VPI图像
input = vpi.asimage(np.asarray(Image.open(args.input)))

# 将其转换为灰度,并使用带有零边界条件的11x11过滤器对其进行模糊
# 在python上下文中启用CUDA后端,使得VPI算法在默认情况下使用CUDA执行
with vpi.Backend.CUDA:
    output = input.convert(vpi.Format.U8).box_filter(11, border=vpi.Border.ZERO)

# 将结果存到磁盘上
with output.rlock():
    Image.fromarray(output.cpu()).save('tutorial_blurred_python.png')

现在执行一下看看效果如何?

左边是原始图,右边则是模糊处的结果,如何,是不是非常简单?这个代码如果扣除汇入(import)库与命令行参数解析的部分,实际的Python代码也就5行而已,事实上真正关键的代码也就是下面这两行,这就是“高阶封装接口”的厉害之处。

代码语言:javascript
复制
with vpi.Backend.CUDA:​output = input.convert(vpi.Format.U8).box_filter(5, border=vpi.Border.ZERO)

首先VPI是一个软件库,在NVIDIA嵌入式和离散设备中,提供的多个计算硬件平台上实现计算机视觉(CV)和图像处理(IP)算法,相同的算法在不同的后端(backend)实现,如CPU、GPU、PVA1和VIC2。

在“with vpi.Backend.CUDA:”时就指定后端为通用GPU设备,VPI就会根据特定的内存特性,在所支持的设备后端之间提供无缝的零拷贝内存映射,如果设备支持统一内存功能(例如Jetson系列),就会启动零拷贝(zero-copy)内存映射功能,可以显著提高吞吐量。

另外一行“output=input.converrt()”指令,就是标准的模糊处理与格式转换的算法,整个过程全部都在GPU上执行,却不存在半分与CUDA相关的迹象,这就是VPI希望达到的目的,让工程师将精力集中在应用开发上,至于硬件计算资源的问题,都交由VPI在后台默默处理。

下面是VPI的基本架构图,提供给大家参考。

整个VPI的执行概念,就是提供适合实时图像处理应用的异步计算管道,由一个或多个异步计算流(streams)组成,这些流在可用计算后端(backends)的缓冲区(buffers)上运行算法(algorithms),流之间使用事件(events)进行同步。

这句话将VPI的元素几乎都涵盖进去了,下面就为大家简单说明一下这些元素的用途:

1. 流(Streams):

VPIStream是一个异步队列,在给定的后端设备上按顺序执行算法。为了实现后端之间的高度并行性,可以在给定的处理管道中配置几个并行运行的处理阶段,每个阶段都在其VPI流中,然后在VPI提供的同步原语的帮助下通过交换数据结构相互协作。

2. 后端(Backends):

后端由最终运行算法的计算硬件组成,VPI支持后端CPU、GPU(使用CUDA)、PVA(可编程视觉加速器)、VIC(视频和图像合成器)和NVENC(视频编码器引擎),详细的设备信息,请参阅以下部分:

3. 算法(Algorithms):

VPI支持用于多种目的计算机视觉算法,例如计算立体图像之间的视差Harris关键点检测以及前面范例的图像模糊处等等。

目前支持的算法主要有三大类:

(1)    图像处理:包括Gaussian Pyramid Generato等十六个算法

(2)    视差估算:目前已经支持Stereo Disparity

(3)    特征检测与跟踪:目前已经提供KLT Bounding Box Tracker、Harris Corners Detector、ColorNames Features Detector、Histogram of Oriented Gradients四种

有些算法会使用VPIPayload临时缓冲区来执行处理,有效负载可以创建一次,然后在每次将算法提交到流的时时候重用。

4. 数据缓冲区(Data Buffers):

VPI将数据封装到需要使用的每个算法的缓冲区中,提供Images(二维图像)、Arrays(一维数组)和Pyramids(二维图像金字塔)的三种抽象,以及用户分配内存包装,由VPI直接分配和管理。

对于Images与Arrays这两种类型,VPI可以包装外部分配的内存以便算法直接使用,并试图通过零拷贝(共享)内存映射到目标后端来实现高吞吐量。

5. 同步原语(Synchronization Primitives):

VPI提供了几种方法来协调不同流之间的工作,并确保任务以正确的顺序执行:

(1)     可以将给定流同步到调用线程,使调用线程等待到目前为止提交到流的所有工作完成,应用程序可以检查或将最终结果转发到另一个阶段。

(2)     为了在流之间进行更细粒度的协调,可以使用VPIEvent使一个流或调用线程在一个或多个流上等待特定任务完成,从而有效地实现屏障同步机制。

6. VPI应用(Applications):这部分包括三个主要阶段:

(1)     初始化:在其中分配内存,创建streams、images、arrays和context这些VPI对象,并执行其他一次性初始化任务,例如设置。

(2)     处理循环:将外部数据进行封装以供VPI使用,应用程序大部分时间都花在这一阶段,处理循环将初始化期间创建的有效负载提交给流,从中读取结果并将其传递到其他阶段以进行进一步处理或可视化。

(3)     清除:其中销毁初始化期间分配的所有对象。。

以上就是VPI架构的基本元素的功能,透过这些元件架构起来的开发接口,开发者只要专注在“应用”本身所需要的功能,将底层与计算资源相关的调度与管理问题,全部交给VPI去处理就行。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档