DSP

DSP算法优化之除法优化

2019-07-13 09:35发布

关于DSP除法运算,如果不需要特别高的精度,可以采用查找表的方式,优化除法运算。下面我们就研究一下如何采用查找表的方式加速除法运算。我们以32位单精度float类型除法为例来讲解。

FLOAT的内存结构格式

float一共32位,其结构定义如下: |-------- 31 -------|------------ 30-23------------ |------------ 22-0 ------------|  符号位(sign)       指数部分(exp)          小数部分(mag) sign:符号位就一位,0表示正数,1表示负数 exp: 指数部分,无符号正数 mag:小数部分,定点小数,小数点在最左边,表示范围:0 ≤ mag< 1。 float的表达式 :  pow(-1, sign) * (1 + mag) * pow(2, exp - 127)   示例程序1 #include #include #include intmain(int argc,char*argv[]) {    float f;    int i;    int sign;    int exp;    int mag;    float d_mag;    float f2;      f = 1.23;    //f = -0.12;    i = *(int*)&f;    sign = (i >> 31) & 0x01;    exp = (i >> 23) & 0xFF;    mag = i & 0x7FFFFF;    d_mag = 1.0f * mag /0x800000;    f2 = (sign == 0 ? 1 : -1) * (1 + d_mag) * pow(2.0, exp - 127);    printf("float: f = %f ",f);    printf("sign = %X, exp = %X, mag =%X ",sign, exp, mag);    printf("float: f2 = %f ",f2);    return 0; } 输出结果:  

浮点数(FLOAT)的倒数公式

倒数(reciprocal / multiplicative inverse)读(dàoshù),是指数学上设一个数x与其相乘的积为1的数,记为1/xx,过程为乘法逆,除了0以外的复数都存在倒数,倒数图将其以1除,便可得到倒数. 两个乘积是1的数互为倒数,0没有倒数。 倒数,一般在计算器中表示为1/x 所以浮点数倒数 inv = 1 / f = 1 / (pow(-1,sign) * (1 + mag) * pow(2, exp - 127)) = pow(-1, sign) * pow(2, 127 - exp) * (1 / * (1 + mag)) 示例程序2 #include #include #include intmain(int argc,char*argv[]) {    float f;    int i;    int sign;    int exp;    int mag;    float d_mag;    float inv;      f = 1.23;    //f = -0.12;    i = *(int*)&f;    sign = (i >> 31) & 0x01;    exp = (i >> 23) & 0xFF;    mag = i & 0x7FFFFF;    d_mag = 1.0f * mag /0x800000;    inv = (sign == 0 ? 1 : -1) * pow(2.0, 127 - exp) * 1.0 / (1 + d_mag);    printf("float: f = %f,  1 / f = %f ", f, 1 / f);    printf("float: inv = %f ",inv);    return 0; } 输出结果:  

采用查找表计算倒数

倒数的快速运算的关键是计算(1 / * (1 + mag)),其中 最直接的想法莫过于将[0, 1)区间n等分,建立查找表。可以根据存储空间与计算精度的要求综合考虑n的大小。比如经过权衡,我们采用n = 4096,这时就需要16kbytes的存储空间。有效精度可以达到3~4位。 实例程序3: #include #include #include floatdiv_table[4096]; voidcreate_div_table_4096() {      int i;      for(i = 0; i < 4096; i++)      {          div_table[i]= 1.0 / (1 + i / 4096.0);      } } intmain(int argc,char*argv[]) {    float f;    int i;    int sign;    int exp;    int mag;    float d_mag;    float inv;      create_div_table_4096();    f = 1.23;    //f = -0.12;    i = *(int*)&f;    sign = (i >> 31) & 0x01;    exp = (i >> 23) & 0xFF;    mag = i & 0x7FFFFF;    inv = (sign == 0 ? 1 : -1) * pow(2.0, 127 - exp) * div_table[mag>> 11];    printf("float: f = %f,  1 / f = %f ", f, 1 / f);    printf("float: inv = %f ",inv);    return 0; } 输出结果:

代码优化

待续…

参考资料

http://blog.csdn.net/adream307/article/details/7246993 http://baike.baidu.com/link?url=jtx4w2u7UBMh-jNP44zqOxsOPBrlq85o_ujklz-2Pcx92uYYgxKhzoxmqYPxvXmapeJCkpVYLjEcyDfDP_fjOygDNqTuWp6ADcjM2z6VG37