打印
[经验分享]

用查找表方式在MCU上实现对数运算

[复制链接]
273|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2023-9-12 15:57 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
缘起
在MCU(Micro Control Unit)编程中,因为其处理能力有限,对浮点数的支持性能也一般,但有时我们**在MCU上实现一些数**算,比如固定长度FFT,比如对数运算,等等。这种情况下,如果直接使用math数学函数库,会带来巨大的性能影响。为此,可以采用空间换时间的方式,通过使用查找表(Look-Up-Table),在满足计算精度的要求下,实现快速的运算。本文就通过查找表的方式,探讨一种针对单精度浮点数的快速对数运算的方法。

单精度浮点数的表示
在计算机上,单精度浮点数是一个32位数字,包含1个符号位,8个指数位,和23个尾数位,如下图所示:

对于对数运算来说,数字必须为正,所以这里sign必须是1。对上述浮点数进行对数(log10)运算,我们得到:

log10(num) = (E - 127) x log10(2) + log10(1.b22b21...b0)

其中,等式右边的第一部分为普通的乘法运算(E = b30b29...b23),第二部分是针对尾数部分的对数运算,是我们讨论的重点。

计算精度及查表法实现
在进一步讨论查表法实现的方法之前,先探讨计算机进行对数运算的精度问题。我们来看如下的函数公式:

y = lg(x) = ln(x) / ln(10)

其中lg表示以10为底的对数运算,ln表示以e为底的对数运算(自然对数)。那么我们得到y的微分如下:

dy = (1 / (x ln(10)) dx = dx / x / ln(10)

也就是说,数值计算的精度(dy),与x的大小成反比,x越大,计算误差dy越小。对于上一节提到的单精度浮点数计算公式来说,计算精度主要取决于第二部分对尾数部分的运算。由于尾数部分取值在[1, 2)区间内,即1 <= x < 2,计算误差最大的位置在当x == 1时。为此,若只考虑最大计算误差,我们可以简化误差计算公式为:

dy = dx / 1 / ln(10) = dx / ln(10)

对于完整的尾数部分,其数值表达精度为1 / 2^23 = 0.00000011920929 = 1.1920929 * 10e-7,因此计算误差(假设计算过程不引入新的误差)为1.7198265 * 10e-7。

但是,在实际应用中,我们可能并不需要这么高的精度。例如,如果对数计算结果是用来表示信号的功率的分贝(dB)值,那么0.01dB就是一个不错的精度了。假设我们的目标精度是0.01dB,我们看看具体是什么情况。根据dB计算的公式,假设信号功率为x,那么转换成dB的公式为:

z = 20 * log10(x) = 20 lg(x)

那么dz = 20 dy = dx * 20 / ln(10),假设dz = 0.01,那么dx = dz * ln(10) / 20 = 0.00115,也就是说,只要x的精度好于0.00115,我们就可以达到0.01dB的精度。我们来看看用几位尾数精度可以达到0.00115的精度:


从表中我们可以看到,当尾数比特数为10时,其精度达到了0.0009765625,好于0.01dB所要求的尾数精度0.00115。所以,我们可以取10比特尾数表示单精度浮点数,并构建一个1024(2^10)个表项的查找表来实现该对数运算:

/** Log Table for [1, 2), with step 0.0009765625 */
const float Log10Table[1024] = {
    0, 0.000423909, 0.000847404, 0.00127049, 0.00169316, 0.00211542, 0.00253727, 0.00295871,
    0.00337974, 0.00380036, 0.00422058, 0.00464039, 0.0050598, 0.0054788, 0.0058974, 0.00631559,
    0.00673338, 0.00715077, 0.00756776, 0.00798435, 0.00840054, 0.00881633, 0.00923173, 0.00964672,
    0.0100613, 0.0104755, 0.0108893, 0.0113028, 0.0117158, 0.0121284, 0.0125407, 0.0129525,
    0.013364, 0.013775, 0.0141857, 0.014596, 0.0150059, 0.0154154, 0.0158246, 0.0162333,
    0.0166417, 0.0170497, 0.0174572, 0.0178645, 0.0182713, 0.0186777, 0.0190838, 0.0194895,
    0.0198948, 0.0202998, 0.0207043, 0.0211085, 0.0215123, 0.0219157, 0.0223188, 0.0227215,
    0.0231238, 0.0235257, 0.0239273, 0.0243285, 0.0247293, 0.0251298, 0.0255299, 0.0259296,
    0.0263289, 0.0267279, 0.0271265, 0.0275248, 0.0279227, 0.0283202, 0.0287174, 0.0291142,
    0.0295106, 0.0299067, 0.0303024, 0.0306977, 0.0310927, 0.0314874, 0.0318816, 0.0322756,
    0.0326691, 0.0330623, 0.0334552, 0.0338477, 0.0342398, 0.0346316, 0.035023, 0.0354141,
    0.0358048, 0.0361952, 0.0365852, 0.0369749, 0.0373642, 0.0377532, 0.0381418, 0.0385301,
    0.0389181, 0.0393057, 0.0396929, 0.0400798, 0.0404664, 0.0408526, 0.0412384, 0.041624,
    0.0420091, 0.042394, 0.0427785, 0.0431626, 0.0435465, 0.04393, 0.0443131, 0.0446959,
    0.0450784, 0.0454605, 0.0458423, 0.0462238, 0.0466049, 0.0469857, 0.0473661, 0.0477463,
    0.0481261, 0.0485055, 0.0488847, 0.0492635, 0.0496419, 0.0500201, 0.0503979, 0.0507754,
    0.0511525, 0.0515294, 0.0519059, 0.052282, 0.0526579, 0.0530334, 0.0534086, 0.0537835,
    0.054158, 0.0545323, 0.0549062, 0.0552798, 0.055653, 0.056026, 0.0563986, 0.0567709,
    0.0571429, 0.0575146, 0.0578859, 0.0582569, 0.0586277, 0.0589981, 0.0593681, 0.0597379,
    0.0601074, 0.0604765, 0.0608453, 0.0612138, 0.0615821, 0.0619499, 0.0623175, 0.0626848,
    0.0630517, 0.0634184, 0.0637847, 0.0641508, 0.0645165, 0.0648819, 0.065247, 0.0656118,
    0.0659763, 0.0663405, 0.0667044, 0.067068, 0.0674312, 0.0677942, 0.0681569, 0.0685192,
    0.0688813, 0.0692431, 0.0696045, 0.0699657, 0.0703265, 0.0706871, 0.0710474, 0.0714073,
    0.071767, 0.0721263, 0.0724854, 0.0728442, 0.0732027, 0.0735608, 0.0739187, 0.0742763,
    0.0746336, 0.0749906, 0.0753473, 0.0757037, 0.0760599, 0.0764157, 0.0767713, 0.0771265,
    0.0774815, 0.0778361, 0.0781905, 0.0785446, 0.0788984, 0.0792519, 0.0796052, 0.0799581,
    0.0803108, 0.0806631, 0.0810152, 0.081367, 0.0817185, 0.0820697, 0.0824207, 0.0827714,
    0.0831217, 0.0834718, 0.0838216, 0.0841712, 0.0845204, 0.0848694, 0.0852181, 0.0855665,
    0.0859146, 0.0862625, 0.0866101, 0.0869574, 0.0873044, 0.0876511, 0.0879976, 0.0883438,
    0.0886897, 0.0890353, 0.0893807, 0.0897258, 0.0900706, 0.0904151, 0.0907594, 0.0911034,
    0.0914471, 0.0917906, 0.0921337, 0.0924767, 0.0928193, 0.0931617, 0.0935038, 0.0938456,
    0.0941872, 0.0945284, 0.0948695, 0.0952102, 0.0955507, 0.0958909, 0.0962309, 0.0965706,
    0.09691, 0.0972492, 0.0975881, 0.0979267, 0.0982651, 0.0986032, 0.098941, 0.0992786,
    0.0996159, 0.099953, 0.10029, 0.100626, 0.100963, 0.101299, 0.101634, 0.10197,
    0.102305, 0.10264, 0.102975, 0.103309, 0.103643, 0.103977, 0.104311, 0.104644,
    0.104978, 0.105311, 0.105643, 0.105976, 0.106308, 0.10664, 0.106971, 0.107303,
    0.107634, 0.107965, 0.108295, 0.108626, 0.108956, 0.109286, 0.109615, 0.109945,
    0.110274, 0.110603, 0.110932, 0.11126, 0.111588, 0.111916, 0.112244, 0.112571,
    0.112898, 0.113225, 0.113552, 0.113878, 0.114204, 0.11453, 0.114856, 0.115181,
    0.115507, 0.115831, 0.116156, 0.116481, 0.116805, 0.117129, 0.117453, 0.117776,
    0.118099, 0.118422, 0.118745, 0.119068, 0.11939, 0.119712, 0.120034, 0.120355,
    0.120677, 0.120998, 0.121319, 0.121639, 0.12196, 0.12228, 0.1226, 0.122919,
    0.123239, 0.123558, 0.123877, 0.124196, 0.124514, 0.124833, 0.125151, 0.125469,
    0.125786, 0.126103, 0.126421, 0.126738, 0.127054, 0.127371, 0.127687, 0.128003,
    0.128318, 0.128634, 0.128949, 0.129264, 0.129579, 0.129894, 0.130208, 0.130522,
    0.130836, 0.13115, 0.131463, 0.131777, 0.13209, 0.132402, 0.132715, 0.133027,
    0.133339, 0.133651, 0.133963, 0.134274, 0.134585, 0.134896, 0.135207, 0.135518,
    0.135828, 0.136138, 0.136448, 0.136758, 0.137067, 0.137376, 0.137685, 0.137994,
    0.138303, 0.138611, 0.138919, 0.139227, 0.139535, 0.139842, 0.140149, 0.140456,
    0.140763, 0.14107, 0.141376, 0.141682, 0.141988, 0.142294, 0.1426, 0.142905,
    0.14321, 0.143515, 0.14382, 0.144124, 0.144428, 0.144732, 0.145036, 0.14534,
    0.145643, 0.145946, 0.146249, 0.146552, 0.146854, 0.147157, 0.147459, 0.147761,
    0.148063, 0.148364, 0.148665, 0.148966, 0.149267, 0.149568, 0.149868, 0.150169,
    0.150469, 0.150768, 0.151068, 0.151367, 0.151667, 0.151966, 0.152264, 0.152563,
    0.152861, 0.15316, 0.153458, 0.153755, 0.154053, 0.15435, 0.154647, 0.154944,
    0.155241, 0.155538, 0.155834, 0.15613, 0.156426, 0.156722, 0.157017, 0.157313,
    0.157608, 0.157903, 0.158198, 0.158492, 0.158786, 0.159081, 0.159374, 0.159668,
    0.159962, 0.160255, 0.160548, 0.160841, 0.161134, 0.161426, 0.161719, 0.162011,
    0.162303, 0.162595, 0.162886, 0.163178, 0.163469, 0.16376, 0.164051, 0.164341,
    0.164632, 0.164922, 0.165212, 0.165502, 0.165791, 0.166081, 0.16637, 0.166659,
    0.166948, 0.167237, 0.167525, 0.167813, 0.168101, 0.168389, 0.168677, 0.168965,
    0.169252, 0.169539, 0.169826, 0.170113, 0.170399, 0.170686, 0.170972, 0.171258,
    0.171544, 0.171829, 0.172115, 0.1724, 0.172685, 0.17297, 0.173255, 0.173539,
    0.173823, 0.174108, 0.174391, 0.174675, 0.174959, 0.175242, 0.175525, 0.175808,
    0.176091, 0.176374, 0.176656, 0.176939, 0.177221, 0.177503, 0.177784, 0.178066,
    0.178347, 0.178629, 0.17891, 0.17919, 0.179471, 0.179751, 0.180032, 0.180312,
    0.180592, 0.180872, 0.181151, 0.18143, 0.18171, 0.181989, 0.182268, 0.182546,
    0.182825, 0.183103, 0.183381, 0.183659, 0.183937, 0.184214, 0.184492, 0.184769,
    0.185046, 0.185323, 0.1856, 0.185876, 0.186153, 0.186429, 0.186705, 0.186981,
    0.187256, 0.187532, 0.187807, 0.188082, 0.188357, 0.188632, 0.188907, 0.189181,
    0.189455, 0.189729, 0.190003, 0.190277, 0.190551, 0.190824, 0.191097, 0.19137,
    0.191643, 0.191916, 0.192188, 0.192461, 0.192733, 0.193005, 0.193277, 0.193549,
    0.19382, 0.194091, 0.194363, 0.194634, 0.194904, 0.195175, 0.195446, 0.195716,
    0.195986, 0.196256, 0.196526, 0.196796, 0.197065, 0.197334, 0.197604, 0.197873,
    0.198141, 0.19841, 0.198679, 0.198947, 0.199215, 0.199483, 0.199751, 0.200019,
    0.200286, 0.200553, 0.200821, 0.201088, 0.201354, 0.201621, 0.201888, 0.202154,
    0.20242, 0.202686, 0.202952, 0.203218, 0.203483, 0.203749, 0.204014, 0.204279,
    0.204544, 0.204809, 0.205073, 0.205338, 0.205602, 0.205866, 0.20613, 0.206394,
    0.206657, 0.206921, 0.207184, 0.207447, 0.20771, 0.207973, 0.208236, 0.208498,
    0.20876, 0.209023, 0.209285, 0.209546, 0.209808, 0.21007, 0.210331, 0.210592,
    0.210853, 0.211114, 0.211375, 0.211636, 0.211896, 0.212156, 0.212417, 0.212676,
    0.212936, 0.213196, 0.213455, 0.213715, 0.213974, 0.214233, 0.214492, 0.214751,
    0.215009, 0.215268, 0.215526, 0.215784, 0.216042, 0.2163, 0.216558, 0.216815,
    0.217072, 0.21733, 0.217587, 0.217844, 0.2181, 0.218357, 0.218613, 0.21887,
    0.219126, 0.219382, 0.219638, 0.219893, 0.220149, 0.220404, 0.22066, 0.220915,
    0.22117, 0.221424, 0.221679, 0.221934, 0.222188, 0.222442, 0.222696, 0.22295,
    0.223204, 0.223457, 0.223711, 0.223964, 0.224217, 0.22447, 0.224723, 0.224976,
    0.225228, 0.225481, 0.225733, 0.225985, 0.226237, 0.226489, 0.226741, 0.226992,
    0.227244, 0.227495, 0.227746, 0.227997, 0.228248, 0.228499, 0.228749, 0.229,
    0.22925, 0.2295, 0.22975, 0.23, 0.230249, 0.230499, 0.230748, 0.230997,
    0.231247, 0.231495, 0.231744, 0.231993, 0.232241, 0.23249, 0.232738, 0.232986,
    0.233234, 0.233482, 0.23373, 0.233977, 0.234225, 0.234472, 0.234719, 0.234966,
    0.235213, 0.235459, 0.235706, 0.235952, 0.236199, 0.236445, 0.236691, 0.236937,
    0.237182, 0.237428, 0.237673, 0.237919, 0.238164, 0.238409, 0.238654, 0.238898,
    0.239143, 0.239387, 0.239632, 0.239876, 0.24012, 0.240364, 0.240608, 0.240851,
    0.241095, 0.241338, 0.241581, 0.241825, 0.242068, 0.24231, 0.242553, 0.242796,
    0.243038, 0.24328, 0.243522, 0.243764, 0.244006, 0.244248, 0.24449, 0.244731,
    0.244973, 0.245214, 0.245455, 0.245696, 0.245937, 0.246177, 0.246418, 0.246658,
    0.246898, 0.247139, 0.247379, 0.247618, 0.247858, 0.248098, 0.248337, 0.248577,
    0.248816, 0.249055, 0.249294, 0.249533, 0.249771, 0.25001, 0.250248, 0.250487,
    0.250725, 0.250963, 0.251201, 0.251439, 0.251676, 0.251914, 0.252151, 0.252388,
    0.252626, 0.252863, 0.253099, 0.253336, 0.253573, 0.253809, 0.254046, 0.254282,
    0.254518, 0.254754, 0.25499, 0.255225, 0.255461, 0.255696, 0.255932, 0.256167,
    0.256402, 0.256637, 0.256872, 0.257106, 0.257341, 0.257575, 0.25781, 0.258044,
    0.258278, 0.258512, 0.258746, 0.258979, 0.259213, 0.259446, 0.25968, 0.259913,
    0.260146, 0.260379, 0.260612, 0.260844, 0.261077, 0.261309, 0.261542, 0.261774,
    0.262006, 0.262238, 0.26247, 0.262701, 0.262933, 0.263164, 0.263396, 0.263627,
    0.263858, 0.264089, 0.26432, 0.26455, 0.264781, 0.265011, 0.265242, 0.265472,
    0.265702, 0.265932, 0.266162, 0.266392, 0.266621, 0.266851, 0.26708, 0.267309,
    0.267538, 0.267767, 0.267996, 0.268225, 0.268454, 0.268682, 0.268911, 0.269139,
    0.269367, 0.269595, 0.269823, 0.270051, 0.270278, 0.270506, 0.270733, 0.270961,
    0.271188, 0.271415, 0.271642, 0.271869, 0.272096, 0.272322, 0.272549, 0.272775,
    0.273001, 0.273227, 0.273453, 0.273679, 0.273905, 0.274131, 0.274356, 0.274582,
    0.274807, 0.275032, 0.275257, 0.275482, 0.275707, 0.275932, 0.276157, 0.276381,
    0.276605, 0.27683, 0.277054, 0.277278, 0.277502, 0.277726, 0.277949, 0.278173,
    0.278396, 0.27862, 0.278843, 0.279066, 0.279289, 0.279512, 0.279735, 0.279957,
    0.28018, 0.280402, 0.280625, 0.280847, 0.281069, 0.281291, 0.281513, 0.281734,
    0.281956, 0.282178, 0.282399, 0.28262, 0.282842, 0.283063, 0.283284, 0.283504,
    0.283725, 0.283946, 0.284166, 0.284387, 0.284607, 0.284827, 0.285047, 0.285267,
    0.285487, 0.285707, 0.285926, 0.286146, 0.286365, 0.286585, 0.286804, 0.287023,
    0.287242, 0.287461, 0.287679, 0.287898, 0.288116, 0.288335, 0.288553, 0.288771,
    0.288989, 0.289207, 0.289425, 0.289643, 0.289861, 0.290078, 0.290296, 0.290513,
    0.29073, 0.290947, 0.291164, 0.291381, 0.291598, 0.291814, 0.292031, 0.292247,
    0.292464, 0.29268, 0.292896, 0.293112, 0.293328, 0.293544, 0.293759, 0.293975,
    0.294191, 0.294406, 0.294621, 0.294836, 0.295051, 0.295266, 0.295481, 0.295696,
    0.295911, 0.296125, 0.296339, 0.296554, 0.296768, 0.296982, 0.297196, 0.29741,
    0.297624, 0.297837, 0.298051, 0.298264, 0.298478, 0.298691, 0.298904, 0.299117,
    0.29933, 0.299543, 0.299756, 0.299968, 0.300181, 0.300393, 0.300606, 0.300818,
};
#define EXPO_BITS         8
#define EXPO_OFFSET       ((1 << (EXPO_BITS - 1)) - 1)   // 127
#define FRAC_BITS         23
#define FRAC_MASK         ((1 << FRAC_BITS) - 1)         // 0x7FFFFF
#define FRAC_INDEX_SHIFT  (FRAC_BITS - TABLE_ORDER)
float mylog10(float x)
{
    if (x <= 0.0f)
        return LOG10_MIN;

    void *px = &x;
    int x_int = *((int *) px);
    int exp = (x_int >> FRAC_BITS) - EXPO_OFFSET;
    int frac = x_int & FRAC_MASK;

    float dB = 0.0f;
    dB += (float) exp * LOG10_2;
    dB += Log10Table[frac >> FRAC_INDEX_SHIFT];

    return dB;
}



在此实现方法中,一共使用了1024个浮点常数,占用4096字节的ROM空间,但是避免了复杂的对数运算。实测表名,使用查找表方法,对数运算的性能提升了10倍左右。在带单精度浮点运算单元的STM32L496处理器上,普通计算方法计算一个2048个点的对数需要大约10ms时间,而使用查找表方法后,计算时间缩短到约1ms。

结语
查找表方法通过空间换时间的方法,以不大的ROM空间为代价,在满足性能要求的前提下,能大大缩短浮点运算的计算时间,是嵌入式系统中值得大力推广的方法。本文以对数运算为例进行阐发,**给读者以提示,在嵌入式开发中带来更佳的性能提升。
————————————————
版权声明:本文为CSDN博主「若谷先生」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45629282/article/details/132551064

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1530

主题

14513

帖子

9

粉丝