范围编码器:如何摆脱分裂?

时间:2012-08-02 22:57:16

标签: optimization arm integer-division raspberry-pi range-encoding

我正在尝试优化QTC视频编解码器,以便在Raspberry Pi上运行,并获得不错的性能。一个重要的瓶颈是在范围解码器中完成的32位整数除法,其考虑了解码时间的18%。由于设备的ARM处理器显然缺少整数除法指令,我认为可以轻松优化它。分工必须准确。

每个调用中特定除法中的被除数和除数都是不同的,但已知除数总是小于65536.我考虑建立一个逆除数值的查找表。使用该表我可以使用乘法而不是除法。查找表的大小为256千字节。

问题

  1. 执行优化是一个好主意吗?
  2. 有没有更好的方法摆脱软件部门?
  3. 有没有不同的方法来实现算法,以便没有划分?
  4. 其他想法?

2 个答案:

答案 0 :(得分:5)

还可以利用Raspberry Pi包含FP单元的事实,该FP单元能够执行双精度FP分割,这比整数分割的软件仿真更快。用a = b / c替换所有整数除法a = (double)b / (double)c对我有用。

答案 1 :(得分:2)

如果你想使用魔术乘法+ LUT,这里有一些代码。

简单的测试器测试随机除数i。没有详尽地测试所有我的,但我已经在短期内工作了。对于我测试过的i,似乎可以处理被除数的所有32位状态(j = 0..2 ^ 32-1)。

实际上,你会预先计算i = 2..64k-1或某些范围的查找表(i = 0不会起作用,因为值/ 0是未定义的,i = 1不会起作用,因为它的魔力乘数超出了32位数的范围)。然后使用方程式使用i作为查找索引来获得魔术乘数'm'。根据需要改变&不要讨厌我的风格。 :P

#include <stdio.h>

int main() {
  unsigned int i,j,k,m,c;

  // compute j/i,
  // compute k = 2^32/i
  // instead of j/i, use m = ~(j*k)>>32
  srand(time(0));
  for(c=0;c<64;c++) {
    // generate random divisor i's for testing, then fully test every j
    i = rand()&0x7fff;      
    // precompute these and put into a lookup table, index on [i]
    k = (((__int64)1)<<32)/i;  
    for(j=0;j!=-1;j++) {
      // status updater so we know it's working...
      if(!(j&0xfffff)) { printf("%d : %d     \r", i, j); fflush(0); }    
      // multiply instead of divide!
      m = (((__int64)j*k)+k/2)>>32; 
      // rare fixup
      if(j - m*i >= i) m++;                          
      if(m != j/i) {
        // as long as this line doesn't print, we're ok
        printf("wrong : %d %d %d   got: %d  should be: %d\n", 
            i, j, k, m, j/i);    
      }
    }
  }
}