在NVIDIA A100 GPU上利用硬件JPEG解码器和NVIDIA nvJPEG库
根据调查,普通人产生的1.2万亿张图像可以通过电话或数码相机捕获。这样的图像的存储,尤其是以高分辨率的原始格式,会占用大量内存。
JPEG指的是联合图像专家组,该组织于2017年庆祝成立25周年。JPEG标准指定了编解码器,该编解码器定义了如何将图像压缩为字节的位流并解压缩回图像。
JPEG编解码器的主要目的是最小化照片图像文件的文件大小。JPEG是一种有损压缩格式,这意味着它不存储原始图像的完整像素数据。JPEG的优点之一是,它可以微调所使用的压缩量。如果正确使用,这会产生良好的图像质量,同时还会使最小的合理文件大小成为可能。
JPEG压缩的关键组件如下:
• 色彩空间转换可以分离亮度(Y)和色度(Cb,Cr)分量。Cb和Cr的下采样可以减小文件大小,而质量损失几乎没有引起注意,因为人的感知对这些图像分量不太敏感。这不是核心标准的一部分,但是定义为JFIF格式的一部分。
• 基于块的离散余弦变换(DCT)允许以较低的频率压缩数据。
• 量化允许对高频细节进行舍入系数。通常,可以丢失这些细节,因为人眼通常无法轻松地区分高频内容。
• 逐行编码在部分解码位流后预览整个图像的低质量版本。
以下照片(图1)显示了JPEG压缩导致的图像质量损失。原始的蝴蝶图像为BMP格式(512×512,24位,769 kB,无压缩),然后以JPEG格式显示同一图像,质量压缩系数为50%,二次采样为4:2:0,24位,图片大小为33 KB。

图1a. 原始蝴蝶图像(无压缩,大小512×512,24位),769 KB。

图1b. 压缩蝴蝶图像(质量压缩系数50%,二次采样4:2:0,24位),33 KB。
JPEG如何运作
图2显示了JPEG编码器的一种常见配置。

图2.使用GPU CUDA软件和CPU的并行利用的JPEG编码过程图。
首先,JPEG编码以RGB彩色图像开始。
第二步涉及将颜色转换为代表亮度(亮度)的YCbCr颜色空间Y和代表色度(红色和蓝色投影)的Cb和Cr通道。然后,将Cb和Cr通道以预定因子(通常为2或3)进行下采样。下采样提供了压缩的第一阶段。
在下一阶段,将每个通道划分为8×8的块,并计算DCT,这是一种类似于傅立叶变换的频率空间变换。DCT本身是无损且可逆的,将一个8×8空间块转换为64个通道。
然后,对DCT系数进行量化,该过程是有损的并且包括第二压缩阶段。量化由JPEG质量参数控制,较低的质量设置对应于更严格的压缩,因此文件更小。
量化阈值特定于每个空间频率,并且已经过精心设计。对低频的压缩比对高频的压缩要少,因为人眼对大范围内的细微W误差比对高频信号的大小变化更敏感。
最后阶段是使用Huffman编码无损地压缩量化的DCT系数,并将其存储在JPEG文件中,如图2所示。
图3显示了NVIDIA GPU上的JPEG解码过程。

图3. JPEG解码过程采用了GPU CUDA和软件的并行利用。用于霍夫曼解码的混合(CPU / GPU)方法克服了串行过程的停顿。
JPEG解码过程从压缩的JPEG位流开始,并提取头信息。
然后,霍夫曼解码处理串行过程,因为从比特流中一次解码一个DCT系数。
下一步将解量化和逆DCT处理为8×8块。
上采样步骤处理YCbCr转换并产生解码的RGB图像。
NVIDIA通过基于CUDA技术构建的nvJPEG库加速了JPEG编解码器。我们开发了JPEG算法的完整并行实现。JPEG编码器和解码器工作流的典型GPU加速部分如图2和3所示。
新的JPEG硬件解码器
推出了NVIDIA A100 GPU,它具有专用的硬件JPEG解码器。以前,数据中心GPU上没有这样的硬件单元,JPEG解码是同时使用CPU和GPU的纯软件CUDA解决方案。
现在,硬件解码器与其余GPU同时运行,后者可以执行各种计算任务,例如图像分类,目标检测和图像分割。与NVIDIA Tesla V100相比,它以不止一种方式提供了显着的吞吐量提高,JPEG解码速度提高了4-8倍。
它通过CUDA工具包的一部分nvJPEG库公开。
nvJPEG库概述
nvJPEG是用于JPEG编解码器的GPU加速库。结合数据扩展和图像加载库NVIDIA DALI,它可以通过加速数据的解码和扩展来加速对图像分类模型的深度学习训练。A100包含5核硬件JPEG解码引擎。nvJPEG利用硬件后端来批量处理JPEG图像。

图4. JPEG硬件解码过程采用了硬件解码器和GPU CUDA软件的并行利用。硬件解码器独立于CUDA SM,因此可以同时使用软件GPU解码器。
通过选择具有nvjpegCreateExinit功能的硬件解码器,nvJPEG可提供基线JPEG解码和各种颜色转换格式(例如YUV 420、422、444)的加速。如图4所示,与纯CPU处理相比,这将使图像解码速度提高20倍。DALI的用户可以直接受益于这种硬件加速,因为nvJPEG是抽象的。
nvJPEG库支持以下操作:
• nvJPEG编码
• nvJPEG转码
• nvJPEG解码(包括硬件(A100)支持)
该库支持以下JPEG选项:
• 基线和渐进JPEG编码和解码,仅适用于A100的基线解码
• 每像素8位
• 霍夫曼比特流解码
• 多达四个通道的JPEG位流
• 8位和16位量化表
• 以下三个色度通道Y,Cb,Cr(Y,U,V)的色度子采样:
o 4:4:4
o 4:2:2
o 4:2:0
o 4:4:0
o 4:1:1
o 4:1:0
该库具有以下功能:
• 同时使用CPU和GPU的混合解码。
• 库的输入在主机内存中,输出在GPU内存中。
• 单张图像和批量图像解码。
• 用户为设备提供的内存管理器和固定的主机内存分配。
绩效数字
对于本节中的性能图,使用了以下测试设置和GPU / CPU硬件:
• NVIDIA V100 GPU:CPU – E5-2698 v4 @ 2GHz 3.6GHz Turbo(Broadwell)HT on GPU – Tesla V100-SXM2-16GB(GV100)1 16160 MiB 1 80 SM GPU视频时钟1312 Batch 128和单线程
• NVIDIA A100 GPU CPU –铂金8168 @ 2GHz 3.7GHz Turbo(Skylake)HT on GPU – A100-SXM4-40GB(GA100)1 40557 MiB 1108 SM GPU视频时钟1095 Batch 128和单线程
• CPU:CPU –铂金8168 @ 2GHz 3.7GHz Turbo(Skylake)HT在TurboJPEG解码上进行CPU测试
• 图像数据集:2K FHD = 1920 x 1080 4K UHD = 3840 x 2160 CUDA Toolkit 11.0 CUDA驱动程序r450.24
接下来的两个图表显示了硬件JPEG解码器的解码速度。

图5.该图显示了A100上的硬件解码比V100上的CUDA混合解码所提高的速度。

图6. V100上的混合解码器所需的CPU线程数,以跟上A100上的硬件解码器吞吐量。
通过将解码工作转移到硬件上,可以释放宝贵的CPU周期,以便更好地利用它们。
图7显示了编码加速。

图7a. 对于1920×1080(2K FHD),3840×2160(4K UHD)图像尺寸的CPU,CUDA(V100,A100)之间的JPEG基线编码吞吐量比较。

图7b. 对于1920×1080(2K FHD),3840×2160(4K UHD)图像尺寸的CPU,CUDA(V100,A100)之间的JPEG渐进编码吞吐量比较。
图像解码示例
这是使用nvJPEG库的图像解码示例。此示例显示了A100 GPU上硬件解码器的使用以及其他NVIDIA GPU的后端回退。
//
// The following code example shows how to use the nvJPEG library for JPEG image decoding.
//
// Libraries used
// nvJPEG decoding

int main()
{

// create nvJPEG decoder and decoder state
nvjpegDevAllocator_t dev_allocator = {&dev_malloc, &dev_free};
nvjpegPinnedAllocator_t pinned_allocator ={&host_malloc, &host_free};

// Selecting A100 Hardware decoder
nvjpegStatus_t status = nvjpegCreateEx(NVJPEG_BACKEND_HARDWARE,       &dev_allocator, &pinned_allocator,NVJPEG_FLAGS_DEFAULT,         &params.nvjpeg_handle);params.hw_decode_available = true;
if( status == NVJPEG_STATUS_ARCH_MISMATCH) {std::cout<<"Hardware Decoder not supported. Falling back to default backend"<<std::endl;
// GPU SW decoder selected
nvjpegCreateEx(NVJPEG_BACKEND_DEFAULT, &dev_allocator,&pinned_allocator, NVJPEG_FLAGS_DEFAULT,&params.nvjpeg_handle);
params.hw_decode_available = false;

}

// create JPEG decoder state
nvjpegJpegStateCreate(params.nvjpeg_handle, &params.nvjpeg_state)// extract bitstream metadata to figure out whether a bitstream can be decoded
nvjpegJpegStreamParseHeader(params.nvjpeg_handle, (const unsigned char *)img_data[i].data(), img_len[i], params.jpeg_streams[0]);// decode Batch images
nvjpegDecodeBatched(params.nvjpeg_handle, params.nvjpeg_state,     batched_bitstreams.data(),                 batched_bitstreams_size.data(), batched_output.data(), params.stream)...

}

$ git clone https://github.com/NVIDIA/CUDALibrarySamples.git
$ cd nvJPEG/nvJPEG-Decoder/
$ mkdir build
$ cd build
$ cmake …
$ make

// Running nvJPEG decoder
$ ./nvjpegDecoder -i …/input_images/ -o ~/tmp

Decoding images in directory: …/input_images/, total 12, batchsize 1
Processing: …/input_images/cat_baseline.jpg
Image is 3 channels.
Channel #0 size: 64 x 64
Channel #1 size: 64 x 64
Channel #2 size: 64 x 64
YUV 4:4:4 chroma subsampling
Done writing decoded image to file:/tmp/cat_baseline.bmp
Processing: …/input_images/img8.jpg
Image is 3 channels.
Channel #0 size: 480 x 640
Channel #1 size: 240 x 320
Channel #2 size: 240 x 320
YUV 4:2:0 chroma subsampling
Done writing decoded image to file:/tmp/img8.bmp
Processing: …/input_images/img5.jpg
Image is 3 channels.
Channel #0 size: 640 x 480
Channel #1 size: 320 x 240
Channel #2 size: 320 x 240
YUV 4:2:0 chroma subsampling
Done writing decoded image to file:/tmp/img5.bmp
Processing: …/input_images/img7.jpg
Image is 3 channels.
Channel #0 size: 480 x 640
Channel #1 size: 240 x 320
Channel #2 size: 240 x 320
YUV 4:2:0 chroma subsampling
Done writing decoded image to file:/tmp/img7.bmp
Processing: …/input_images/img2.jpg
Image is 3 channels.
Channel #0 size: 480 x 640
Channel #1 size: 240 x 320
Channel #2 size: 240 x 320
YUV 4:2:0 chroma subsampling
Done writing decoded image to file: /tmp/img2.bmp
Processing: …/input_images/img4.jpg
Image is 3 channels.
Channel #0 size: 640 x 426
Channel #1 size: 320 x 213
Channel #2 size: 320 x 213
YUV 4:2:0 chroma subsampling
Done writing decoded image to file:/tmp/img4.bmp
Processing: …/input_images/cat.jpg
Image is 3 channels.
Channel #0 size: 64 x 64
Channel #1 size: 64 x 64
Channel #2 size: 64 x 64
YUV 4:4:4 chroma subsampling
Done writing decoded image to file:/tmp/cat.bmp
Processing: …/input_images/cat_grayscale.jpg
Image is 1 channels.
Channel #0 size: 64 x 64
Grayscale JPEG
Done writing decoded image to file:/tmp/cat_grayscale.bmp
Processing: …/input_images/img1.jpg
Image is 3 channels.
Channel #0 size: 480 x 640
Channel #1 size: 240 x 320
Channel #2 size: 240 x 320
YUV 4:2:0 chroma subsampling
Done writing decoded image to file: /tmp/img1.bmp
Processing: …/input_images/img3.jpg
Image is 3 channels.
Channel #0 size: 640 x 426
Channel #1 size: 320 x 213
Channel #2 size: 320 x 213
YUV 4:2:0 chroma subsampling
Done writing decoded image to file:/tmp/img3.bmp
Processing: …/input_images/img9.jpg
Image is 3 channels.
Channel #0 size: 640 x 480
Channel #1 size: 320 x 240
Channel #2 size: 320 x 240
YUV 4:2:0 chroma subsampling
Done writing decoded image to file:/tmp/img9.bmp
Processing: …/input_images/img6.jpg
Image is 3 channels.
Channel #0 size: 640 x 480
Channel #1 size: 320 x 240
Channel #2 size: 320 x 240
YUV 4:2:0 chroma subsampling
Done writing decoded image to file:/tmp/img6.bmp
Total decoding time: 14.8286
Avg decoding time per image: 1.23571
Avg images per sec: 0.809248
Avg decoding time per batch: 1.23571
图像大小调整示例
此图像调整大小和加水印示例根据客户端请求生成图像的缩放版本。
图8显示了图像调整大小和加水印的典型工作流程。

图8.并行使用GPU软件和CUDA的图像大小调整和水印流水线。
下面的代码示例演示如何调整图像大小并在徽标图像上添加水印。
//
// The following code example shows how to resize images and watermark them with a logo image.
//
// Libraries used
// nvJPEG decoding, NPP Resize, NPP watermarking, nvJPEG encoding

int main()
{

// nvJPEG decoder
nReturnCode = nvjpegDecode(nvjpeg_handle, nvjpeg_decoder_state, dpImage, nSize, oformat, &imgDesc, NULL);
// NPP image resize
st = nppiResize_8u_C3R_Ctx(imgDesc.channel[0], imgDesc.pitch[0], srcSize,
srcRoi, imgResize.channel[0], imgResize.pitch[0], dstSize, dstRoi,
NPPI_INTER_LANCZOS, nppStreamCtx);

st = nppiResize_8u_C3R_Ctx(imgDescW.channel[0], imgDescW.pitch[0], srcSizeW, srcRoiW,imgResizeW.channel[0], imgResizeW.pitch[0], dstSize, dstRoi,   NPPI_INTER_LANCZOS, nppStreamCtx);// Alpha Blending watermarking
st = nppiAlphaCompC_8u_C3R_Ctx(imgResize.channel[0], imgResize.pitch[0], 255, imgResizeW.channel[0], imgResizeW.pitch[0], ALPHA_BLEND, imgResize.channel[0], imgResize.pitch[0], dstSize, NPPI_OP_ALPHA_PLUS,  nppStreamCtx);// nvJPEG encoding
nvjpegEncodeImage(nvjpeg_handle, nvjpeg_encoder_state, nvjpeg_encode_params,&imgResize, iformat, dstSize.width, dstSize.height,NULL));...

}

$ git clone https://github.com/NVIDIA/CUDALibrarySamples.git
$ cd nvJPEG/Image-Resize-WaterMark/
$ mkdir build
$ cd build
$ cmake …
$ make

// Running Image resizer and watermarking
$ ./imageResizeWatermark -i …/input_images/ -o resize_images -q 85 -rw 512 -rh 512

在NVIDIA A100 GPU上利用硬件JPEG解码器和NVIDIA nvJPEG库相关推荐

  1. NVIDIA A100 GPUs上硬件JPEG解码器和NVIDIA nvJPEG库

    NVIDIA A100 GPUs上硬件JPEG解码器和NVIDIA nvJPEG库 Leveraging the Hardware JPEG Decoder and NVIDIA nvJPEG Lib ...

  2. 在NVIDIA A100 GPU中使用DALI和新的硬件JPEG解码器快速加载数据

    在NVIDIA A100 GPU中使用DALI和新的硬件JPEG解码器快速加载数据 如今,最流行的拍照设备智能手机可以捕获高达4K UHD的图像(3840×2160图像),原始数据超过25 MB.即使 ...

  3. FFmpeg在Intel GPU上的硬件加速与优化

    英特尔提供了一套基于VA-API/Media SDK的硬件加速方案,通过在FFmpeg中集成Intel GPU的媒体硬件加速能力,为用户提供更多的收益.本文来自英特尔资深软件开发工程师赵军在LiveV ...

  4. 【FFmpeg在Intel GPU上的硬件编解码实现】

    用于记录Intel CPU开发qsv硬件解码过程中遇到的一些问题及解决方案 以下文章是在开发过程中参考的比较有意义的文章,供大家学习和参考~~ https://zhuanlan.zhihu.com/p ...

  5. 超级计算机的等级,Azure超级计算机等级的Nvidia A100 GPU云计算服务正式上线

    微软周三宣布Azure ND A100 v4 Cloud GPU的云计算服务,正式在Azure公有云平台上线,号称是速度最快的超级计算机. 去年11月以预览版问世的ND A100 v4搭载Nvidia ...

  6. 在Ubuntu 16.04.5 LTS上利用python 2.7版本的pillow库拼接近千张图片实录

    缘由 这两年网上出现了使用python中的PIL或是pillow库拼接图片和朋友圈图像的例子,让我非常感兴趣,比较典型的是这几个例子: <朋友圈的朋友们,你们终于可以互相看到了> < ...

  7. 安卓上利用百度输入法提供的导入词库与个性短语,批量造词方便输入

    最近有做个小APP,里面管理了很多的商品,商品名称不是常见的词,用户在会需要经常输入这些商品名称(软件外部,无法做自动补全),每次都要选词,正确的候选项往往不会出现在很前面,容易误选,输入效率较低.按 ...

  8. NVIDIA A100 深度解密(一):GPU 峰值计算那些事

    这是我的推广信息,以激励自己更好的分享自己的知识和经验!也希望看到的你能够多多支持,谢谢! 1. 滴滴云AI大师: 目前滴滴云正在大力推广自己的云计算服务,需要购买的朋友们用我的AI大师码 「2049 ...

  9. NVIDIA GPU上的直接线性求解器

    NVIDIA GPU上的直接线性求解器 NVIDIA cuSOLVER库提供了密集且稀疏的直接线性求解器和本征求解器的集合,它们为计算机视觉,CFD,计算化学和线性优化应用程序提供了显着的加速.cuS ...

最新文章

  1. C++_泛型编程与标准库(三)
  2. matlab norm 范式
  3. 我所理解的原型原型链
  4. python在中国的发展-Python未来的发展前景到底如何?
  5. 简单谈谈linux的文件权限问题
  6. 如何做一名优秀的电子工程师[zz]
  7. 构造函数和实例化原理
  8. 促销惊喜活动优惠海报设计,可临摹PSD分层格式
  9. android之读取相册照片并显示
  10. Blog访问量提升秘笈
  11. 信息课为什么不叫计算机课,你理解的互联网是这样的吗?为什么叫加入互联网?...
  12. java i586什么意思_linux里面i386 i686 i486 i586代表什么?是什么意思
  13. vs2003常见问题
  14. 谈谈银联 js 支付
  15. android 动漫头像,动漫卡通头像制作
  16. The error occurred while setting parameters
  17. nginx的安装升级、常用配置(二)
  18. python 正则表达式 ,看这篇就够了
  19. 深度学习之鸡兔同笼问题
  20. 操作系统之文件管理系统

热门文章

  1. 2017 年已读书单总结
  2. 路由器远程登陆配置:01一个人登陆多台设备
  3. 获取当前脚本目录路径问题汇总
  4. Java中如何实现Date与String之间的数据类型转换
  5. LeetCode简单题之增量元素之间的最大差值
  6. 实用的Linux 安装 zip unzip
  7. Java map 知识
  8. ubantu中的mysql命令
  9. 024_Word知识汇总
  10. 初级版python登录验证,上传下载文件加MD5文件校验