DSP

AVS具体代码优化_熵解码

2019-07-13 19:07发布

之前讲了很多的理论,之后会结合一些代码讲解一些优化的方法,今天刚对AVS熵解码的一部分内存访问进行优化 在熵编码和熵解码这样的底层函数因为调用次数是非常多的,有时候只要减少一个clock都会优化很多的内容 做DSP优化,和C语言优化有一些不同,除了一些常规的注意嵌套循环,减少判断语句之类的操作外, 对dsp优化必须非常注意减少内存的访问和程序运行的并行化处理 同时对于所采用的硬件也应该注意其自带的一些内联指令,这些内联指令对于一些运算是十分有用的,这个在我做DCT和IDCT优化的时候有明显的感觉,优化达到了80%以上,之后会慢慢介绍一些内联指令 我所提及的指令大部分都是针对TI 6678,对于别的型号可以作为参考用: 言归正传: 在AVS熵解码的一个函数 if (--Dbits_to_go < 0) { //<如果当前缓冲区没有数据 get_byte();//<从码流中获得一个字节的数据存入缓冲区 } // Shift in next bit and add to value value_t = (value_t << 1) | ((Dbuffer >> Dbits_to_go) & 0x01);//<将value_t和当前缓冲区数据中拿出来一个bit进行运算 value_t = 256 + value_t - t2;这里没有循环,只有一次操作
while (t_rlps < 256) {//t_rlps不为0,这是一个循环操作 t_rlps = t_rlps << 1; if (--Dbits_to_go < 0) { get_byte(); } // Shift in next bit and add to value value_t = (value_t << 1) | ((Dbuffer >> Dbits_to_go) & 0x01);//<和上面类似 }
while (value_t < 256) {//> Dbits_to_go) & 0x01); //<和上面类似 value_s++; }


在这个函数中主要对这三部分进行优化,因为他们在大量的访问内存,并且做循环操作 1 get_byte()函数使用得可以更加充分,我们不取一个字节,在保证边界条件的情况下我们一次先取出来4个字节 #define get_byte(){ Dbuffer = Dcodestrm[(*Dcodestrm_len)++]; Dbits_to_go = 7; }
修改为: void Get_Byte2(DecodingEnvironmentPtr dep) { Dbuffer = _mem4(Dcodestrm + *Dcodestrm_len); Dbuffer = _packlh2(Dbuffer,Dbuffer); Dbuffer = _swap4(Dbuffer); Dbits_to_go = 31; *Dcodestrm_len +=4; }这里用到了一些内联函数,具体可以参考6678的操作手册 上面的代码不仅取出来了4个字节的数据,还让码流顺序进行了交换,这个是代码中所需要的 (Dbuffer >> Dbits_to_go)表示每次都是从高位中读出的,因此当Dbits_to_go从7变为31的时候也需要将码流适当做顺序处理 通过一次访问4个字节就会减少对内存的访问次数 2 计算一个循环的最大循环次数,为其准备充分的数据,减少循环内部判断 第一部分的代码最多循环1次 第二部分的代码最多循环8次 第三部分的代码循环次数不一定,但是根据分析我们可以知道value_t如果不为0,那么他的循环次数最多8次,如果为0,那么就需要根据缓冲区中的数据进行判断了,因此为了投机运算,我们开分支进行处理 if (Dbits_to_go < 16) { Get_Byte2_(dep); }
在函数一开始将数据准备好,之后就不再有判断了,对应三部分的代码 dep->value_t = (dep->value_t << 1) | ((Dbuffer >>(--Dbits_to_go)) & 0x01); dep->value_t = 256 + dep->value_t - t2;
tempi = _lmbd(1,t_rlps)-23;//<_lmbd is searching for the number of 0 befor 1 //< tempi refers to the cyclenum of while (t_rlps < 256),because the max number is 8 dep->value_t <<= tempi; if (tempi != 0) { dep->value_t = dep->value_t | _extu(Dbuffer,32-Dbits_to_go,32-tempi);//<_extu get the bit of Dbuffer between 32-Dbits_to_go and 32-tempi } Dbits_to_go-=tempi; t_rlps<<=tempi;
if (dep->value_t) { tempi = _lmbd(1,dep->value_t)-23; dep->value_t <<= tempi; if (tempi != 0) { dep->value_t = dep->value_t | _extu(Dbuffer,32-Dbits_to_go,32-tempi); } Dbits_to_go-=tempi; dep->value_s +=tempi; } else { while (dep->value_t < QUARTER) { if (--Dbits_to_go < 0) { Get_Byte2(dep); } dep->value_t = (dep->value_t << 1) | ((Dbuffer >> Dbits_to_go) & 0x01); dep->value_s++; } }
还有需要注意的就是使用恰当的DSP对应的内联函数