十六 提高专业技能之 “Codec定点化”
Write by Liupin 2010-4-1
- 基本理论
1) 为什么要定点化
Since the Core is an integer process,all floating point operations must be simulated using integer arithmetic. 现在大多数嵌入式CPU都是定点的,当然在这些CPU platform上是能跑浮点数的程序,但效果很低,原因是内部是调用floating 处理的库或专用的硬件处理单元。另一点,由于浮点数的处理单元功耗更高,这就限制在移动devices上的应用。
结论:定点化处理在移动应用上开发往往是必不可少的一步。现在很多算法实现,往往开始是在相关的平台上进行算法仿真,然后就C语言浮点实现,里面有很多float, double型的数据,然后就是定点化的,提高算法的效率。
2) 定点化的方法
首先要选择Q的数值,如short型的,往往用Q15, int型的,往往用Q31.这也是有前提的,要保证在所有运算过程中,最大值不会大于1。 如出现了,应该调整Q值,如用Q14或Q30.
其次就是一些基本运算时,注意一定要保持Q值的统一,如不统一那得要通过左移或右移来实现。
In signal processing the data oftenconsists of fractional values, in the range -1 to +1. This example uses exponentq and 32-bit integer mantissas (so that each value can be held in a single ARMregister). In order to be able to multiply two numbers without overflow, youneed , or . In practice q=14 is often chosen as this allows multiplication withseveral accumulates without risk of overflow。
Fig16.1 Q=14 Basic operations
从Fig16.1中可以看,在计算前要统一各参与运算变量的Q值。 如 X + a, X是Q14, 而且a是一整数,所以在运算时要统一到Q14, so a<<14. 运算有时会改变Q的值,所以在运算后往往要对结果进行Q值的调整。如 xy
X: Q14, Y :Q14, So XY: Q28, in order tonormal the Q value to 14, so the result have to right shift 14: (X*Y) >>14.
Example1:
To calculate the distance from theorigin, d = sqrt(x^2 + y^2 + z^2), in q=8 form. If you apply the above formulaedirectly and keep all intermediate answers in q=8 form, you arrive at thefollowing code:
x = (x*x)>>8 square x
y = (y*y)>>8 square y
z = (z*z)>>8 square z
s = x+y+z sum of squares
d = sqrt(s<<8)the distance in q=8 form
Alternatively, if you keep theintermediate answers in q=16 form, the number of shifts is reduced and theaccuracy increased:
x = x*x square of x in q=16 form
y = y*y square of y in q=16 form
z = z*z square of z in q=16 form
s = x+y+x sum of squares in q=16 form
d = sqrt(s) distance d in q=8 form
Conclusion:
(1) If you add two numbers in Q-form, the stay in Q-form
(2) If you multiply two numbers in Q-form, the answer is 2Q-from
(3) If you take the square root of a number in q form the answer isin q/2-form.
(4) To convert from q-formto r-form you shift left by (r-q) or right by (q-r),depending on which of q andr is greater
(5) To get the bestprecision results, choose q to be the largest number such that the intermediatecalculations cannot overflow.
- 深入探究
定点化过程中,最难把握的是数度问题,如Q值太小,往往达不到技术要求的精度。但Q值定得太大,如Q31,这样又比较容易出现溢出,同时也会增加一些常量表的size. 在实际运行中,往往也会影响代码的效率,因为会导致register不够用。如都是Q15,那样一个数就是2bytes,这样一个32bits register就能load二个数值。
一个方法往往是先估计一下,在运算中,最大的数值是多少,这个往往好估计的,然后根据这个值来尽量取大的Q值。原则是先满足精度要求下进行定点化,当定点化完成后,再考虑用小点的Q值来定点化。尽量提高时间性能参数。
- 工程实战
以AC3decoder project 定点化来说明,代码定点化过程。
往往大家,拿到一工程代码,由于文件很多,且各个文件有相关参数的传递,这样搞得大家不知道怎么下手来做定点化的工作。
其实我们可以采用化整为零的方法,通过做法是以每个function为单位进行定点化。
例如:
AC3 Decoder---idctsc() function
做法是,在进行idctsc后,对输入的数据进行定点化,然后参与定点化的运算,定点化的运算无非就是上面列举的basic operations, 然后在function结束前,做与开始相反的运算,恢复输出buffer里的数据成floating data.
void idctsc(DEC_PARAM *p_decparam, BUFF_PARAM *p_buff)
{
//DSPfract*fftrptr, *fftiptr, *fftrptr2, *fftiptr2;
//DSPfract*tcrptr, *tciptr, *cosptr, *sinptr;
//DSPfractar, ai, cr, ci;
int *fftrptr, *fftiptr, *fftrptr2, *fftiptr2;
int *tcrptr,*tciptr;
int ar, ai, i;
int fftbuf_fx[N], tcbuf_fx[N];
short *cosptr, *sinptr;
short cr, ci;
//对输入buffer里的数据进行Q31的定点化处理
for(i=0;i<N; i++)
{
fftbuf_fx[i]= (int)(p_buff->fftbuf[i] * 2147483647);
tcbuf_fx[i] = (int)(p_aublk->tcbuf[i] * 2147483647);
fprintf(fdebug,"idctsc1: 0x%08x\n", fftbuf_fx[i]);
fprintf(fdebug,"idctsc2: 0x%08x\n", tcbuf_fx[i]);
}
……
进行相关运算
……
//恢复outputbuffer floating data, in order to the next function run.
for(i=0;i<N; i++)
{
p_buff->fftbuf[i]= (double)(fftbuf_fx[i]/2147483647.0);
}
}
用这个方法,fixed AC3 project codec function by function.当然了,有时并不是整个project用统一的Q值,可能这个function 是Q30,另一个function 由于一些值的累加,用Q30时会产生溢出,这时可能会用Q28. 有不同Q值时,特别要注意利用左右移位,保证最后数据的正确性。
- 参考文献
[1]. ARM Document, ApplicationNote 33 --- Fixed point Arithmetic on the ARM