天天看点

x265探索与研究(八):x265中的并行处理机制函数关系分析x265探索与研究(八):x265中的并行处理机制函数关系分析

        hevc的高计算复杂度如果仅仅依赖于单核处理器计算能力的提高,其代价是非常昂贵的,为此,hevc的设计充分考虑到了并行计算的需求。x265不同于hm(hevc

test model),x265将并行计算发挥地更加淋淋尽致。在main()函数中,为了完成多线程计算,读完24帧输入帧后才开始编码的原因也基于此。

        为了理清x265中的并行处理机制,首先给出了如下图的并行处理函数关系图:

x265探索与研究(八):x265中的并行处理机制函数关系分析x265探索与研究(八):x265中的并行处理机制函数关系分析

        经过前面几篇文章的分析,我们知道main()函数主要调用了encoder_open()函数、encoder_headers()函数、encoder_encode()函数与encoder_close()函数。其中:

(1)encoder_encode()函数调用了encode()函数,而encode()函数中调用了startcompressframe()函数,在startcompressframe()函数中,采用m_enable.trigger完成了触发线程的功能;

(2)encoder_open()函数调用了encoder_create()函数,在encoder_create()函数中等待线程的初始化并进入threadmain()函数中等待线程的触发,线程一旦触发则调用compressframe函数进行进一步地编码工作。

        这两步的协调工作完美地成就了多线程的实现。为了进一步分析hevc的并行处理机制,接下来首先分析视频编码的并行处理相关技术,然后依次分析该函数关系图中较为重要的startcompressframe()函数、encoder_create()函数以及threadmain()函数。

        并行处理一般指许多指令得以同时进行的处理模式,通常分为两种:功能并行和数据并行。

(1)功能并行是指将应用程序划分成互相独立的功能模块,每个模块间可以并行地执行,这种并行方式也称为流水线型并行,它将各个独立的模块划分给不同的运算单元,各个模块之间通过流的方式来进行数据交换和通信,最终再将各个单元串接在一起。功能并行充分利用了时间上的并行性来获得加速的效果,比较适合于硬件实现。功能并行的缺点是很明显的,a、由于分配给不同运算单元的功能模块是不同的,因此很容易产生载荷失衡问题;b、功能并行还需要在不同运算单元间进行数据通信,当数据量较大时,需要花费额外的资源来进行存储;c、另外,功能并行的扩展性较差。

(2)数据并行是将数据信息划分为相互独立的部分,每一部分交给不同的运算单元来执行,从而实现并行处理。在这种方式下,不同运算单元上执行的程序是相同的,而且处理的是相互独立的数据信息,因此不需要进行运算单元间的通信;数据并行也具有较好的扩展性,易于软件实现。

        hevc/h.265提供了适用于进行数据并行处理的结构单元,如片和tile,在不同的片和tile中,数据信息是相互独立的,这样有利于将其分配给不同的运算单元来处理;对于小于片和tile的划分单元,hevc支持波前并行处理(wavefront

parallel processing, wpp),这是对于相互具有依赖关系的图像单元进行数据并行处理的方法。在hevc中,并行处理技术主要包括:基于tile的并行和波前并行两种。在进行基于tile的并行时,由于tile的相互独立性,不需要考虑它们之间的相互依赖关系,而在进行波前并行处理时,数据间的相互依赖关系是必不可少的。

        startcompressframe()函数的主要功能就是触发线程,对应的代码分析如下:

        encoder_create()函数的主要功能是检测线程池、可用的线程数目等等,若线程使用的条件符合则调用threadmain()函数,对应的代码分析如下:

        threadmain()函数相当于线程函数的main()函数,其主要功能就是在完成线程触发后等待处理,在此处,调用了compressframe()函数。

        对应的代码分析如下: