【嵌入式底层知识修炼】整数乘除法与位运算的效率对比

您所在的位置:网站首页 汇编语言16位乘法运算 【嵌入式底层知识修炼】整数乘除法与位运算的效率对比

【嵌入式底层知识修炼】整数乘除法与位运算的效率对比

2024-07-10 11:54| 来源: 网络整理| 查看: 265

文章目录 01 - 为什么整数位移比乘除法高效02 - 位移和乘除法对比2.1 - 汇编代码对比2.2 - 编写复杂度对比2.3 - 速度对比 03 - 实际应用3.1 - 单片机时钟重载值 04 - 总结

1us的误差,足矣改变这个世界

————CSDN根号3

01 - 为什么整数位移比乘除法高效

  首先,整数位运算要比乘除法要高效。如果学过计算机组成原理的,相信在初次接触二进制乘除法运算的时候,对补码一位乘法、原码恢复余数法、补码不恢复余数法等都一脸茫然,因为过程实在是太复杂,如果你想不起来,看一看当时老师(可能是你的)课件PPT: Alt

  应当问一句:为什么这么复杂?答:因为CPU只会加法!应当说,这个世界只有加法,那些乘除法、开根号、微积分等等,都是加法的深度组合,而CPU现实加法的底层硬件之一就是位移器!相关内容在数字逻辑学中,再看一张课件PPT: Alt

  所以,程序中使用位移比使用乘除法要高效,但不是任何时候,因为程序中存在一个2-8定律,对程序性能效率起作用的只有那20%的代码,因此如果去优化那其余的80%代码是徒劳的。这里所说的高效,是在优化那20%代码的基础上

02 - 位移和乘除法对比

  现在很多嵌入式编译器很强大,当识别到除数或者乘法因子(一般是常量)是2n倍,会自动编译成位移运算,比如大多数的ARM编辑器,就ARM Gcc 6.4而言,C语言和对应的汇编如下: Alt   重点看asr r3, r3, #3,意思是把r3寄存器右移3位再把值存入r3,右移3位相当于除以23=8,所以编译器内部也会对乘除法进行优化,尽量用位移代替。当除数或者乘法因子是变量或者不是2n倍的时候,就会调用乘除法子程序,或者乘除法指令

2.1 - 汇编代码对比

  这里依然使用ARM gcc 6.4编译器,如果是整数变量进行乘除法运算,一般会调用乘除法子程序

int ret = 128; int value = 8; /* C语言 */ /* 核心汇编 */ ret /= value; ------------ bl __aeabi_idiv ret = ret >> 3; ---------- asr r3, r3, #3 2.2 - 编写复杂度对比

  有若干种情况:   ① 当除数或者乘法因子是2n倍时,乘除法很容易转变为位移运算:二进制左移1位 == 十进制乘以2,二进制右移一位 == 十进制除以2   ②当除数或者乘法因子不是2n倍时:     1. 乘法运算也可以转变为位移运算,就是拆分成一个2t + K的数:     10 * 9 = 10 * (8+1) = (10 * 8) + (10 * 1) = 103 */ /* c = a/8 */ run_time:25.659256us run_time:31.724171us

  ARM Gcc 6.4编译器代码(裸机编程,与实际硬件有关)

#define RTY_MAX 10000 extern uint32_t timer_count; void cal(void) { uint8_t a = 128; uint8_t b = 8; uint8_t c,i; timer_start(); for(i = 0; i>3; timer_stop(); xprintf("%lu tick\r\n",timer_count); }

  ARM Gcc 6.4编译器运行结果

/* c = a>>3 */ /* c = a/8 */ 1254876 tick 3865468 tick

  可以看到,乘除法的时间要比位移运算长,并且随着运算次数越多,他们时间差越大,在影响系统的20%代码内,1us的差距都将发生不可逆转的灾害

03 - 实际应用 3.1 - 单片机时钟重载值

  大家都写过:   TH0 = (65536 - 1000) / 256; TL0 = (65536 - 1000) % 256   一般而言,单片机时钟会发生ms级中断,如果编译器比较强大,那么上述公式会自动转变为位移运算,如果编译器不支持,那么每次计算重载值都会花费一点时间,随着不断的积累,时间差就会很明显,如果这段代码存在那20%代码之内,为了那若干us的误差补偿,正确的写法应当是:   TH0 = (max_65536 - value_1000) >> 8 ; TL0 = (max_65536 - value_1000) & 0x00FF ;   当然,更好的方法是先计算好,得出一个常量,直接赋值,但是这样难以维护,要适当取舍。在其余代码中也经常看见位移运算代替乘除法,如果仔细阅读过STM32的HAL库函数源代码,你会发现位移运算随处可见

04 - 总结 整数位移运算比乘除法高效优化代码要优化2-8定律中的2整数乘法任何时候都可以转换成位移运算整数除法、求余运算的除数如果是2n倍时,就可以转换成位移运算


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3