当前位置:蜗牛素材网>综合资讯>图文>正文

cuda指定使用的gpu:基于GPU的图像处理加速库CV-CUDA全面解读

人气:169 ℃/2024-04-11 12:27:32

随着短视频APP、视频会议平台以及VR/AR等技术的发展,视频与图像已逐渐成为全球互联网流量的主要组成部分。我们平时接触到的这些视频图像,也有很多是被AI和计算机视觉(CV)算法处理并增强过的。然而,随着社交媒体和视频分享服务的快速增长,作为AI图像算法基础的视频图像处理部分,也早已成为计算流程中不可忽视的成本和瓶颈。

CV-CUDA应用场景

我们先带大家简单回顾一下图像处理的常见的例子,以更好地理解CV-CUDA(Computer Vision - Compute Unified Device Architecture)应用场景。

(1)AI算法图像背景模糊化

AI背景模糊(CPU 前后处理方案)

图像背景模糊化通常会被应用于视频会议、美图修图等场景。在这些场景中,我们通常希望AI算法可以将主体之外的背景部分模糊化,这样可以保护用户隐私、实现美化图像等。图像背景模糊化的流程大体可以分为3个过程:前处理、DNN网络以及后处理过程。前处理过程,通常包含了对图像做Resize、Padding、Image2Tensor等操作;DNN网络可以是一些常见segmentation network,比如UNet等;后处理过程,通常包括Tensor2Mask、Crop、Resize、Denoise等操作。

在传统的图像处理流程中,前处理和后处理部分通常都是使用CPU进行操作,这导致整个图像背景模糊化流程中,有90%的工作时间消耗在前后处理部分,这部分工作也成为了整个算法流水线的瓶颈。若能把前后处理妥善利用GPU加速,则能够大幅提升整体的计算性能。

AI背景模糊(GPU 前后处理方案)

当我们把前后处理部分都放到GPU上后,就可以对整个pipeline进行端到端的GPU加速。经过测试,在单个GPU上,相比于传统图像处理方式,将整个pipeline移植到GPU后,可获得20倍以上的吞吐率提升。这无疑会大大节省计算成本。

(2)AI算法图像分类

AI 图像分类

图像分类是最常见的AI图像算法之一,通常用于物体识别、以图搜图等场景,几乎是所有AI图像算法的基础。图像分类的pipeline大体可以分为2个部分:前处理部分和DNN部分。其中前处理部分,在training和Inference过程中最常见的4种操作包括:图片解码、Resize、Padding、Normalize。DNN部分已经有了GPU的加速,而前处理部分通常都会使用CPU上的库函数进行处理。如果能够将前处理部分也移植到GPU上,那么一方面可以释放CPU资源,另一方面也可以进一步提升GPU利用率,从而对整个pipeline进行加速。

当前图像处理主流方案

针对前后处理部分,我们将对目前已有的一些主流应用方案进行总结。

(1)目前应用最广泛的图像处理库是OpenCV

前后处理中的操作,往往依赖于任务类型,这导致前后处理相关的操作种类繁多且数量庞杂。利用OpenCV确实可以实现大部分的图像处理操作,不过,这些操作大部分是用CPU实现的,缺少对应的GPU加速版本。而部分CPU操作虽然存在对应的GPU版本,但这些GPU版本在实现过程中可能存在一些问题,包括:

  • a. 部分算子的CPU和GPU结果无法对齐。在某些场景下,我们的算法团队使用CPU的算子进行training,而在inference阶段负责部署的同学考虑到性能问题,决定使用GPU算子。然而在测试过程中,发现CPU和GPU算子结果无法对齐,这可能会导致端到端的处理结果出现精度异常;
  • b. 部分算子GPU性能弱于CPU性能。除某些算法本身就不太适合GPU化之外,我们还发现部分GPU实现无法达到高效。比如,有些算子会在运行过程中,临时申请显存空间,导致增加了额外的耗时;
  • c. 在真实的部署pipeline中,可能有些算子只有CPU版本,而有些算子既有CPU版本又有GPU版本。如果pipeline里既有CPU算子又有GPU算子,那么会存在GPU和CPU同步,以及H2D、D2H内存拷贝问题,从而引入额外的耗时。

(2)使用Pytorch框架进行模型训练引入的torchvision图像处理库

在算法开发阶段,出于训练考虑,算法工程师可能会优先使用torchvision来完成图像处理操作。然而在模型部署阶段,负责模型部署的工程师通常会使用c 作为开发语言,没有办法使用torchvision完成图像处理操作,那么可能会使用其他的c 图像处理库,比如OpenCV。然而这就涉及到,torchvision和OpenCV结果对齐的问题。此外,与使用OpenCV的情况类似,torchvision中的算子也有不支持GPU加速,或者GPU加速效果不佳的情况。

CV-CUDA特点

如上所述,传统的图像预处理操作一般在CPU上进行,一方面会占用大量的CPU资源,使得CPU和GPU的负载不均衡;另一方面由于基于CPU的图像加速库不支持batch操作,导致预处理的效率低下。为了解决当前主流的图像处理库所存在的一些问题,NVIDIA和字节跳动的机器学习团队联合开发了基于GPU的图像处理加速库CV-CUDA,并拥有以下特点:

(1)Batch

支持batch操作,可充分利用GPU高并发、高吞吐的并行加速特性,提升计算效率和吞吐率。

(2)Variable Shape

支持同一batch中图片尺寸各不相同,保证了使用上的灵活性。此外,在对图片进行处理时,可以对每张图片指定不同的参数。例如调用RotateVarShape算子时,可以对batch中每张图片指定不同的旋转角度。

(3)C/C /Python接口

在部署机器学习算法时需要对齐训练和推理流程。一般来说,训练时利用python进行快速验证,推理时利用C 进行高性能部署,然而一些图像处理库仅支持python,这给部署带来了极大的不便。如果在训练和推理期间,采用不同的图像处理库,则又需要在推理端重新实现一遍逻辑,过程会非常繁琐。

CV-CUDA提供了C,C 和Python接口,可以同时服务于训练和推理场景。从训练迁移到推理场景时,也可免去繁琐的对齐流程,提高部署效率。

(4)独立算子设计

CV-CUDA作为基础图像处理库,采用了独立算子设计,不需要预先定义流水线。独立算子的设计具有更高的灵活性,使得调试变得更加容易,而且可以与其他的图像处理交互,或者集成在用户自己的图像处理上层框架中。

(5)结果对齐OpenCV

不同的图像处理库,对于一些算子的实现方式不一致,往往会导致计算结果难以对齐。例如常见的Resize操作,OpenCV、OpenCV-gpu以及torchvision的实现方式都不一样,计算结果存在差异。因此,如果在训练时用OpenCV CPU版本而推理时若要采用GPU版本或其他图像处理库,就会面临结果存在误差的问题。

在设计之初,我们考虑到当前图像处理库中,很多用户习惯使用OpenCV的CPU版本,因此在设计算子时,不管是在函数参数还是图像处理结果上,尽可能对齐OpenCV CPU版本的算子。当用户从OpenCV迁移到CV-CUDA时,只需做少许改动便可使用,且图片处理结果和OpenCV一致,不需要重新训练模型。

(6)易用性

CV-CUDA提供了Image,ImageBatchVarShape等结构体,方便用户的使用。同时还提供了Allocator类,用户可以自定义显存分配策略(例如用户可以设计显存池分配策略来提高显存分配速度),方便上层框架集成和管理资源。目前CV-CUDA提供了PyTorch、OpenCV和Pillow的数据转化接口,方便用户进行算子替换和进行不同图像库之间的混用。

(7)针对不同GPU架构的性能高度优化

CV-CUDA可以支持Volta、Turing、Ampere等GPU架构,并针对不同架构GPU的特点,在CUDA kernel层面进行了性能上的高度优化,可在云服务场景中规模化部署。

算子数量及其性能

(1)CV-CUDA目前提供了50多种算子

包括常用的CvtColor、Resize、Crop、PadStack、Normalize等。当前算子能够覆盖大部分应用场景,后续将会支持更多算子。

算子清单:

CV-CUDA 支持算子清单

(2) 性能对比

在本文开头的背景模糊算法里,采用CV-CUDA替代OpenCV和TorchVision的前后处理后,整个推理流程的吞吐率提升了20倍以上。下图展示了在同一个计算节点上(2x Intel Xeon Platinum 8168 CPUs , 1x NVIDIA A100 GPU),以30fps的帧率处理1080p视频,采用不同的CV库所能支持的最大的并行流数。测试采用了4个进程,每个进程batchSize为64。

  • 其中涉及到的前处理操作有:Resize (Downscale)、Padding、Convert Data Type、Normalize及Image to Tensor;
  • 涉及到的后处理操作有:Tensor to Mask、Convert Data Type、Crop、Resize (Upscale)、Bilateral Filter (Denoise)、Gaussian Blur 及Composite。

对于单个算子的性能,我们也做了性能测试,下图的测试场景选用的图片大小为480*360,CPU选择为Intel(R) Core(TM) i9-7900X,BatchSize大小为1,进程数为1。

CV-CUDA性能对比 (CPU: Intel(R) Core(TM) i9-7900X CPU @ 3.30GHz)

性能优化手段及示例

为了让CV-CUDA能够更加高效的运行在GPU上,我们采取了一系列的优化手段。

(1)kernel融合

采用大量的kernel融合策略,减少kernel launch和global memory的访问时间。

(2)访存优化

采用合并访存、向量化读写、shared memory等策略,提高数据读写的效率。

(3)异步处理

CV-CUDA中所有算子均采用异步处理的方式,可减少同步带来的等待耗时。

(4)高效计算

采用fast math、warp/block reduce、table lookup等优化手段,可有效提升计算效率。

(5)预分配显存

CV-CUDA采用预分配显存策略,并且提供Allocator类,帮助使用者自定义显存分配策略或者可采取默认的显存分配策略。算子所需要的buffer和图片显存会在初始化阶段分配好,而在执行阶段不会再进行耗时的显存分配操作。

框架和API

(1)CV-CUDA整体架构

整个CV-CUDA库包含以下几个组成部分:

  • a. CV-CUDA核心模块:核心模块包含了C/C 和Python API,NVCV模块,Operator算子模块以及CV-CUDA Tools;
  • b. CV-CUDA Interop模块:这个模块包含了和其他图像处理库以及推理框架的交互接口,目前支持OpenCV、Pytorch和Pillow,后续将陆续加入其他图像处理库的交互接口;
  • c. CV-CUDA Tools/Tests:包含一些单元测试模块和工具函数。

CV-CUDA整体架构

(2)CV-CUDA核心模块

CV-CUDA核心模块

核心模块包含以下几个部分:

  • a. NVCV核心支持库:包含Image抽象类,Memory workspace类,Allocator和Batch/VarShapeBatch类;
  • b. Operators CV算子:包含了各种独立算子(resize、filter等等);
  • c. CV-CUDA Tools:包含了用于开发算子所需的各种功能函数。

(3)API

ImageBatchVarShape

Resize

字节跳动机器学习团队应用案例

最初,CV-CUDA项目的启动,主要目的是为了解决内部模型训练和推理过程中预处理瓶颈问题。以模型训练为例,正如大家所熟知的,传统数据读取和预处理过程都是由CPU完成的。当CPU多核算力足够时,能为模型训练提供稳定高效的数据,但当CPU算力不足时,数据准备过程即会成为瓶颈,从而导致GPU利用率低下,造成GPU资源的浪费。一直以来,工业界有不少模型的训练推理过程,都存在因CPU资源竞争而影响着性能的问题。这个问题在图像类模型,尤其是针对图像有比较复杂的预处理的场景中尤为明显。随着GPU算力的不断提升,CPU资源竞争的问题日益凸显。为了解决这个问题,最朴素想法便是,将造成CPU算力不足的预处理逻辑搬到GPU上来进行,利用GPU庞大的算力,高效的产生模型所需的数据。

但我们对这个GPU预处理算子库显然是有要求的。首先是性能需要足够好,如果预处理部分GPU kernel的实现跑起来非常慢,可能反而得不偿失;其次预处理搬到GPU上做,对模型迭代本身的影响要小,在我们预期中,预处理kernel是可以见缝插针似的,在模型迭代过程中仅用一点点GPU闲散资源即可;最后,预处理kernel需要支持定制化,字节跳动机器学习团队内部训练的模型多,需要的预处理逻辑也多种多样,因此有许多定制的预处理逻辑需求。而CV-CUDA就很好的满足了以上要求:每个op支持batch数据输入的设计,减少频繁Kernel launch的开销,保证高效的运行性能;每个op都支持stream对象和显存指针的传入,使得我们能够更加灵活的配置相应GPU资源;每个op设计开发时,既兼顾了通用性,也能按需提供定制化接口,实现覆盖内部的图片类预处理需求。

CV-CUDA目前在抖音集团内部的多个线上线下场景中得到了应用,比如搜索多模态、图片分类等,下面我们会对分模型训练和推理分别进行一个典型应用介绍。(模型相关的细节这里就不多做介绍了,主要展示下CV-CUDA的应用场景和获得的收益。)

(1)模型训练

在字节跳动机器学习团队内部,CV-CUDA在预处理逻辑复杂的训练任务上加速效果明显。在模型训练过程中,数据准备和模型迭代是个异步的过程,数据准备只要不比模型迭代来的慢,其性能就是满足需求的。但随着新一代强力GPU投入使用,模型本身的计算时间被进一步缩短,因而对数据准备的性能要求越来越高。此时预处理逻辑一旦有些复杂,CPU竞争就会变得激烈,这个时候CV-CUDA就能发挥很大的作用。

模型训练流程示意图

字节跳动机器学习团队某个视频相关的多模态任务,CV-CUDA应用后就获得了不小的性能收益。该任务预处理部分逻辑很复杂,既有多帧视频的解码,也有很多的数据增强,导致在A100上多卡训练时CPU资源竞争非常明显,因而虽然已经充分利用了CPU(Intel Xeon Platinum 8336C)的多核性能,但数据预处理的速度仍然满足不了模型计算的需求。而使用了CV-CUDA,预处理逻辑被全部迁移到了GPU,相应的训练瓶颈也由数据预处理转移到了模型计算本身,从而在模型训练的整体性能上我们获得了近90%的收益。另一个获得收益的OCR任务也十分相似,其预处理链路有十几个算子,使用CV-CUDA后我们在V100上训练即获得了80%的加速。

CV-CUDA 训练性能收益

需要注意的是,前后处理耗时占比不同的应用在使用CV-CUDA后带来的收益提升会有所差异。例如前后处理耗时占比为50%的应用,使用CV-CUDA后,端到端吞吐率提升的理论上限为原始的2倍(理论上限是指预处理耗时为0,端到端中模型的耗时占比为100%,实际上前后处理加速后,依然会有耗时,因此理论上限仅用于分析理想情况能达到的最大加速比);而前后处理占比90%以上的应用,使用CV-CUDA后的吞吐率提升理论上限为原始的10倍以上。此外,CPU性能的差异也会影响到最终的加速效果。

(2) 模型推理

模型推理和训练略有不同:因为模型训练时数据读取和模型更新是异步的,所以基本上提升模型训练性能可以与提高GPU利用率划等号。但模型推理过程,数据读取和模型计算是一个串行的过程,加速数据准备过程本身即会对整体性能造成直接影响。再加上模型推理时只涉及到模型前向的计算,计算量一般都较小,GPU通常有足够的剩余资源来进行其他的工作。因而模型推理阶段,把预处理逻辑搬到GPU上来加速性能,既合理而又有可行性。

模型推理流程示意图

字节跳动机器学习团队的某个搜索多模态任务,在使用CV-CUDA之后,整体的上线吞吐相比于用CPU做预处理时有了2倍多的提升,值得一提的是,这里的基线本身即是经过CPU(Intel Xeon Platinum 8336C)多核等方式优化过后的结果,虽然涉及到的预处理逻辑较简单,但使用CV-CUDA之后加速效果依然非常明显。

搜索更多有关“cuda指定使用的gpu:基于GPU的图像处理加速库CV-CUDA全面解读”的信息 [百度搜索] [SoGou搜索] [头条搜索] [360搜索]
本网站部分内容、图文来自于网络,如有侵犯您的合法权益,请及时与我们联系,我们将第一时间安排核实及删除!
CopyRight © 2008-2024 蜗牛素材网 All Rights Reserved. 手机版