视频编码的GPU加速

前言

随着视频编解码技术的不断发展,视频逐步向着高清晰、高动态、高数据量的方向演进。这对视频编解码终端的计算能力提出了越来越高的要求。同时,在GPU领域,随着CUDA等通用计算平台的不断发展,GPU逐渐成为了通用计算领域中不可或缺的硬件。利用GPU对视频编码进行加速成为了学术界和工业界的热点。

1. GPU概述

早期,GPU只能承担图形计算和渲染方面的任务,而且硬件架构较为封闭。OpenGL和DirectX接口是与GPU交互的唯一方式。如果工程师想利用GPU进行通用计算,不仅先要学习OpenGL和DirectX,还要想办法把运算数据“伪装”成图形数据给GPU处理。这种负担对研究人员来说过于沉重,因此GPU计算在早期没有被广泛接受。

在2006年11月,NVIDIA发布了第一块基于CUDA架构构建的GPU,GeForce 8800GTX。CUDA架构允许程序对芯片上的每个数学逻辑单元(ALU)进行排列,且可以任意读写内存和缓存。此外,CUDA架构采用C语言作为开发语言,并只增加了一小部分关键字来支持CUDA架构的特殊功能。目前,基于CUDA的GPU加速已经在深度学习、图像处理、科学计算等领域有着广泛应用。

2. 编码加速

目前,最新的视频编码标准是HEVC,基于GPU的HEVC编码加速研究已经有很多。主要集中在运动估计方面。HEVC的运动估计包含以下步骤

  • AMVP确定搜索起点
  • 整像素搜索
  • 亚像素差值
  • 亚像素搜索

这其中,搜索当中最频繁的运算是SAD(或HAD),而插值部分可以看成图像滤波。这两部分运算有着数值运算量大、逻辑运算量少、每个像素的运算相互独立的特点,因此非常适合在GPU上进行运算。

GPU运算的流程为输入、运算、输出三个部分。一般来说,运算部分可以为程序带来很高的提速。但是输入输出部分所耗的时间是无法消除的。这就要求加速算法必须提高吞吐量。

在HEVC中,整像素搜索部分是以PU块为单位进行。然而,HEVC的PU块可选大小分布广泛,最大可取64x64,最小时边长仅为4。若对很小的PU块进行运算,其运算吞吐量非常小,算上输入输出时间很可能比原程序还要慢。为此,多数论文以整个CTU为单位进行运动估计。常见的套路是,通过某种策略给当前CTU确定一个搜索起点,然后对整个CTU进行整像素搜索。CTU内部的CU划分和PU块运动矢量的确定可以以SAD(HAD)作为因素。由于CTU中各个PU块都是按照相同方向进行搜索的,所以小的PU块可以像拼图一样拼出整个CTU,这样每个内部单元的SAD(HAD)都可求,如图1所示。

图1 一个自下而上的PU计算策略

至于插值部分,最常见的套路是先把每个参考帧提前插好,程序需要时直接读取。整个图像作为运算单元已经可以满足吞吐量的要求。

3. 常见GPU优化方法

在CUDA架构中,CPU称为主机(Host),GPU称为设备(Device)。在进行GPU运算时,首先要把数据从主机内存中传输到GPU显存中,合理地进行I/O设计是GPU效率的关键。主要策略有以下几点:

  • 尽可能减小主机复制到设备的数据量
  • 使用“页锁定内存”可以提高传输带宽
  • 将多个小的数据进行合并,一次传输,这样可以省去每次传输时的前置工作
  • 将GPU运算和I/O同步进行(较新的显卡)

本篇主要对页锁定内存进行说明。

主机CPU所管理的内存分为页锁定内存(Pinned Memory)和可分页内存(Pageable Memory)。若不加任何限定,默认分配的内存都是可分页内存。然而GPU无法直接获取主机的可分页内存。当从主机到设备进行一次数据传递时,首先CUDA驱动程序要先申请一个临时的页锁定内存,然后再将原内存数据复制到页锁定内存上,最后才能将页锁定内存的数据传输到设备上,如图2所示。

图2 可分页内存和页锁定内存

为了避免申请临时页锁定内存,我们可以直接在主机上申请页锁定内存。但是页锁定内存的申请有可能失败,所以每次申请时都要检查返回值是否报错。因为页锁定内存长期驻留在内存里,不会被操作系统内存优化影响(比如内存压缩、移入虚拟内存等),所以页锁定内存可以提高传输带宽。但是,过多的页锁定内存可能会很快消耗掉主机内存,使得主机性能下降。

4. 总结

本文主要介绍了常见的HEVC的GPU加速方法和GPU程序设计时要注意的问题。主机和设备之间的I/O是GPU优化的重点问题,需要精心设计。下一篇GPU的文章我们将介绍如何将GPU运算和I/O同步进行。

原文发布于微信公众号 - 媒矿工厂(media_tech)

原文发表时间:2017-08-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一个会写诗的程序员的博客

Spring Reactor 项目核心库Reactor Core

Non-Blocking Reactive Streams Foundation for the JVM both implementing a Reactiv...

2192
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

4878
来自专栏hbbliyong

WPF Trigger for IsSelected in a DataTemplate for ListBox items

<DataTemplate DataType="{x:Type vm:HeaderSlugViewModel}"> <vw:HeaderSlug...

4064
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.2K7
来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

6948
来自专栏魂祭心

原 canvas绘制clock

4164
来自专栏ASP.NETCore

ASP.NET Core 整合Autofac和Castle实现自动AOP拦截

除了ASP.NETCore自带的IOC容器外,我们还可以使用其他成熟的DI框架,如Autofac,StructureMap等(笔者只用过Unity,Ninjec...

674
来自专栏张善友的专栏

Mix 10 上的asp.net mvc 2的相关Session

Beyond File | New Company: From Cheesy Sample to Social Platform Scott Hansel...

2597
来自专栏杨龙飞前端

scrollto 到指定位置

2534
来自专栏Ceph对象存储方案

Luminous版本PG 分布调优

Luminous版本开始新增的balancer模块在PG分布优化方面效果非常明显,操作也非常简便,强烈推荐各位在集群上线之前进行这一操作,能够极大的提升整个集群...

3195

扫码关注云+社区