您现在的位置是:首页 > 正文

x265笔记_3_并行处理机制

2024-04-01 01:27:27阅读 6

HEVC中的并行处理技术

功能并行和数据并行

此处只讨论多处理器的并行技术,可分为功能并行和数据并行:

  1. 功能并行,指将不同的功能模块划分给不同的运算单元,因此又叫”流水线级并行“,这种方法充分利用了功能模块的时间并行性,适合硬件实现,缺点是容易产生载荷失衡的问题,而且拓展性较差;
  2. 数据并行,把信息划分为相互独立的部分,每一部分交给不同的运算单元完成,该种方法具备较好的拓展性,而且如果保证数据单元数大于运算单元数,比较容易达到负载均衡,但是有时候难以保证数据之间的独立性,不得不要进行核间通信来消除数据单元间的依赖性。

在这里插入图片描述

HEVC解码端的并行处理框架

因为熵解码在Slice、Tile和CTB行的起始处都有可能进行概率模型初始化,而且不同模型的初始化位置不一定相同,正是因为熵解码之间的依赖关系和后续解码模块的依赖关系不一致,所以需要两个功能并行模块,即熵编码和其余模块解码。

在每个功能模块中使用数据并行分为更多并行模块,每个运算单元负责其中一个模块:

在这里插入图片描述

HEVC中编码单元数据之间的依赖关系

HEVC中编码单元数据的依赖关系来源于帧内预测、帧间预测、去方块滤波和样点自适应补偿(SAO)等过程,因为编码/解码当前块必须知道其参考块的编码/解码信息。

四种方式的参考信息如下所示:

在这里插入图片描述

HEVC编解码的并行策略

这里其实是很灵活的,可以分为GOP级别、图像级别、Slice级别、Tile级别 和 CTB级别的并行,主要介绍Tile级别的并行策略和CTB级别的并行策略。

Tile级别的并行策略

Tile是H265新增加的数据单元,将原来的图像分为一个个独立的矩形区域,各区域独立进行编码,不会相互参考,很适合于并行化处理。(补充:Tile与之前的Slice划分相互独立,但是要保证一个Tile不会跨过两个Slice,或一个Slice不会跨过两个Tile。而且当多个Tile共用一个Slice的时候,可以公用同一个Slice头,从而可以节省码率。)

Tile中的CTB是按照光栅扫描的顺序进行扫描的,而Tile之间的排序也是按照光栅扫面的顺序排列的,如下图所示:
在这里插入图片描述

可见与Slice的条状相比,Tile的矩形表达提高了内部像素的相关性,而且减少了由于运动预测所需要的缓冲数量(即要缓存的运动搜索范围相比Slice的实现要更小了),但是过多的Tile势必降低率失真性能,因为Tile边界附近的信息被破坏了,下面的波前并行处理算法很好的解决了这个问题。

值得说明的是,虽然Tile之间是相互独立的,而且某些熵编码会在Tile的结尾进行上下文模型的更新,但是去方块滤波和样点自适应补偿仍然可能会跨过Tile边界,此时还是需要额外的核间通信

CTB级别的并行策略/波前并行处理算法(WPP)

波前并行处理算法,可以允许多个CTB同时处理,而且后一行的处理要比前一行滞后两个CTB,这样可以在不破坏边界相关性的前提下进行并行编码。该算法的处理过程如下图所示:

在这里插入图片描述

人们还提出了 依赖片 的数据单元,即将一个完整的Slice划分为不同的区域,分别封装到不同的独立NAL中,这些区域可能是相互关联的,因此被称为依赖片。

对应到该算法,可以将一段用波前并行处理的 CTB行 数据或者Tile 数据打包到一个单独的NAL中,这个单元就被称为依赖片。如下图所示

在这里插入图片描述

这样的好处是,各个NAL虽然是相互依赖的,但是NAL2不用等待NAL1解码完成再解码,而是可以在NAL1解码的同时进行解码,只需要保证落后两个CTB即可,这样可以大大减少解码时延。

坏处就是,码率会十分不平衡,尤其是当上方的运算单元已经结束,但是下方仍然没有结束,此时码率会逐渐降低,这是我们不希望看到的。于是人们提出"重叠波前并行算法",当上方部分运算单元结束之后,会自动编码下一张图片,而不会继续等待,如下图所示,T1~T4会继续编码之后的帧:

在这里插入图片描述

造成的问题是未编码的像素块的运动矢量要尽可能小,在上面的例子中,运动矢量不能大于4。

x265多线程实现原理

main()函数主要调用了encoder_open()encoder_headers()encoder_encode()encoder_close(),其中

  1. encoder_open()除了打印配置信息,还调用了encoder_create()函数(实际调用了Encoder::create()),完成了 等待线程的初始化,并进入threadMain()函数中触发等待线程m_done.wait(),该事件标志线程初始化;
  2. encoder_encode()如上个博客所说,调用了Encoder::encode()函数,在encoder中进一步调用了FrameEncoder::startCompressFrame(),在startCompressFrame中触发线程m_done.trigger,表示进入threadMain()中。
  3. 该线程接下来调用了compressSliceencodeCTUencodeCUfinishCU完成编码

多线程算法流程图

Encoder::create()

Encoder::create()主要用于检查线程池以及可用的线程数目,若符合线程使用条件则调用threadMain()函数。

调用语句为

for (int i = 0; i < m_param->frameNumThreads; i++)
{
    m_frameEncoder[i]->start();
    // wait for thread to initialize
    m_frameEncoder[i]->m_done.wait(); 
}

FrameEncoder::threadMain()

这里的FrameEncoder::threadMain()相当于线程的main函数,主要功能是线程触发后等待处理的过程,主要调用了compressFrame()函数。

如果当前线程池不为空,调用m_pool->setCurrentThreadAffinity()设置当前线程m_tld,如果线程池不为空,创建新的线程m_tld

触发两个事件:m_done.trigger(),线程已初始化完成的信号;m_enable.wait(),等待Encoder::encoder()唤醒。

总结如下:
在这里插入图片描述

Reference

  1. 万帅《新一代高效视频编码:原理、标准与实现》
  2. x265探索与研究 之 x265多线程

视频编码:原理、标准与实现》
2. x265探索与研究 之 x265多线程

  1. x265的线程模型

网站文章

  • MySQL基础(十一)——DQL之联合查询

    本篇文章主要是对MySQL学习时的一些总结,作为学习笔记记录。数据来源数据部分来自于b站尚硅谷MySQL课程联合查询当要查询的结果来自于多个表,且多个表之间没有直接的连接关系,但查询的信息一致时,可以...

    2024-04-01 01:27:20
  • 高德地图Uncaught Error: Invalid Object: LngLat(NaN, NaN)报错

    可能因为没有设置高度。

    2024-04-01 01:26:55
  • LabVIEW在OPC中使用基金会现场总线 最新发布

    LabVIEW在OPC中使用基金会现场总线 最新发布

    区域中选择项目3. 单击。

    2024-04-01 01:26:46
  • Java线程的6种状态及切换(透彻讲解)

    Java线程的6种状态及切换(透彻讲解)

    Java中线程的状态分为6种。1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。2. 运行(RUNNABLE):Java线程中将就绪(ready...

    2024-04-01 01:26:33
  • ubuntu 改屏幕分辨率命令_ubuntu下修改分辨率

    Ubuntu下修改分辨率原来以为是显卡驱动没有装好的缘故,但按照教程重试了几次,1024*768的桌面最大分辨率只有65HZ,晃的好生眼疼。ubuntu 下修改分辨率的具体步骤:第一步,打开/etc/...

    2024-04-01 01:26:09
  • 腾讯云4核8G服务器选CVM还是轻量比较好?价格对比

    腾讯云4核8G服务器选CVM还是轻量比较好?价格对比

    腾讯云4核8G云服务器可以选择轻量应用服务器或CVM云服务器标准型S5实例,轻量4核8G12M服务器446元一年,CVM S5云服务器935元一年,相对于云服务器CVM,轻量应用服务器性价比更高,轻量服务器CPU和CVM有区别吗?性能差异如何?腾讯云4核8G服务器轻量和CVM。

    2024-04-01 01:26:05
  • Windows下安装php_http

    下载以下三个dll: php_raphf.dll php_propro.dll

    2024-04-01 01:25:59
  • windows- 怎么查看本地网卡速度

    windows- 怎么查看本地网卡速度

    由于每天用电脑上网,今天尤其好奇,自己电脑的网卡是啥样的,查了一下,查完之后有了这篇blog。

    2024-04-01 01:25:52
  • java 中的方法的应用

    注意 : 对两个字符串内容比较是否相等时候,不要使用==,应该使用来自于String类中提供的equals方法,能够精确的比较两个字符串内容是否相等。(参数列表) : 方法在定义期间,是否存在不确定的...

    2024-04-01 01:25:26
  • 简单的spring 数据库编程

    简单的spring 数据库编程

    通过所学的Spring数据库编程知识,实现学生管理系统的登录及增删改查的功能。要求学生在控制台输入用户名和密码,如果用户账号与密码正确,则显示用户个人信息;如果用户账号或密码不正确,则显示登录失败。登...

    2024-04-01 01:25:18