Skip to content

Instantly share code, notes, and snippets.

@hewumars
Created July 16, 2020 01:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hewumars/50a28fb6f6218fba445d94a54976246f to your computer and use it in GitHub Desktop.
Save hewumars/50a28fb6f6218fba445d94a54976246f to your computer and use it in GitHub Desktop.

解码流程

NVJPEG的解码有两种方式,分别是单Phrase解码和多Phrase解码,其主要的区别在于多Phrase解码将单Phrase的解码部分拆开成为3个Phrase以进一步提高NVJPEG软件库的灵活性,并可以通过优化解码流程以进一步提高解码性能。下图为单Phrase解码的流程图:

nvjpegCreate:负责分配和初始化句柄

nvjpegJpegStateCreate:负责分配和初始化nvjpegJpegState结构体,其包括临时JPEG信息。

nvjpegGetImageInfo:负责解码JPEG头文件并获取图片的基本信息包括:编码通道数、色度抽样方式、图片宽度、图片高度

nvjpegDecode:负责解码JPEG文件并将数据写入目标显存中

nvjpegJpegStateDestroy:销毁nvjpegJpegState结构体

nvjpegDestroy:销毁程序句柄

单Phrase的解码中nvjpegDecode负责JPEG图片的解码,而在多Phrase部分通过将这部分拆成PhraseOne、PhraseTwo和PhraseThree来实现多Phrase的解码方式,具体流程图如下所示:

nvjpegCreate:同上

nvjpegJpegStateCreate:同上

nvjpegGetImageInfo():同上

nvjpegDecodePhaseOne:CPU预处理操作,传入图片数据和所有解码相关信息

nvjpegDecodePhaseTwo:GPU操作,将解码任务传递至GPU中

nvjpegDecodePhaseThree:GPU操作,将解码的数据写入目标显存中

nvjpegJpegStateDestroy:同上

nvjpegDestroy:同上

这里需要注意的是,nvJPEGDecode和nvjpegDecodePhaseThree里面的目标显存在输入的是nvjpegImage_t *destination指针,其指向的是位于内存的结构体,而该结构体中存的是指向分配的显存的指针及该显存的Pitch。

到目前为止介绍的是单图片的单Phrase和多Phrase解码的流程,那么解码多张图片怎么操作呢?是不是GPU最擅长的Batch方式呢?答案是肯定的,NVJPEG也提供了Batch的API来实现多图片的解码,以多Phrase的Batch解码为例,以下是其流程:

nvjpegCreate:同上

nvjpegJpegStateCreate:同上

nvjpegGetImageInfo():同上

nvjpegDecodeBatchedInitialize:初始化Batch的解码状态

nvjpegDecodeBatchedPhaseOne:同上

nvjpegDecodeBatchedPhaseTwo:同上

nvjpegDecodeBatchedPhaseThree:同上

nvjpegJpegStateDestroy:同上

nvjpegDestroy:同上

在解码之前需要调用nvjpegDecodeBatchedInitialize初始化Batch的解码状态,对于多Phrase的Batch解码可以参考以上API,而单Phrase的解码是通过调用API nvjpegDecodeBatched来实现的。

前文提过关于多Phrase的一个好处是“通过优化解码流程以进一步提高解码性能”,这个优化就是通过Batch加多Phrase解码来实现的。多Phrase解码的PhraseOne部分操作是在CPU操作的,因此可以通过多线程来进行并行操作,之后PhraseTwo在CPU多线程完成后执行Batch的GPU操作。故而在函数nvjpegDecodeBatchedInitialize中有max_cpu_threads输入参数,其指定的是最多的可使用的CPU线程数,而在nvjpegDecodeBatchedPhaseOne中亦有thread_idx的输入参数。对于一个Batch的多线程操作是对于Batch内的每一个图片调用一次nvjpegDecodeBatchedPhaseOne API,其中每一个图片赋予一个图片ID,每调用一次赋予一个线程ID。从而实现了多线程的执行Batch中的每个图片的PhraseOne计算。线程ID可以复用,即一个线程ID可以对应多个图片ID。

另外还需要提到的一点是,即使在调用nvjpegDecodeBatchedInitialize初始化了一个Batch的解码状态,在当前版本中仍然可以调用非Batch API进行解码。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment