-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[kernel]增加一种新的查找字节最低非0位的算法 #5063
Conversation
增加一种新的查找字节最低非0位的算法 |
运行效率上有没有啥差距 |
首先该方式能够省下很多空间,原来的算法需要256个字节,而现在只需要37个字节的空间。 我觉得更重要的是,当该系统使用64位的MPU或者CPU的时候,这种方法绝对效果显著,无论时间还是空间效率,都将大大提高。 |
写个循环调用的函数试试吧。两个函数都运行个多少万次之后,看看执行时间。 我是感觉之前的方式,只有移位和位运算对于计算机处理会方便不少。新加的算法有指数运算和取模运算,感觉时间上可能会慢一点。 |
首先,新加的算法没有指数运算,那是异或操作。 127: int __rt_ffs(int value)
128: {
0x0800122C 4601 MOV r1,r0 ;将r0的值(函数参数值)放入r1中
130: return __lowest_bit_bitmap_new[(uint32_t)( value & (value - 1) ^ value ) % 37];
0x0800122E 1E48 SUBS r0,r1,#1 ; (value-1)结果放入r0
0x08001230 4008 ANDS r0,r0,r1 ;(value & (value-1) 结果放入r0
0x08001232 4048 EORS r0,r0,r1 ; (value & (value-1) ^ value))实现异或的结果放入r0
0x08001234 2225 MOVS r2,#0x25 ; 将37放入r2
0x08001236 FBB0F3F2 UDIV r3,r0,r2 ;r3为商
0x0800123A FB020013 MLS r0,r2,r3,r0; 乘加,r0 = r0 - r2*r3
0x0800123E 4A01 LDR r2,[pc,#4] ; @0x08001244 ;找到查找表的位置
0x08001240 5C10 LDRB r0,[r2,r0] ;得到查找表中的值
131: }
0x08001242 4770 BX lr ;函数返回 而原先的代码则需要比较多的代码实现,由于代码较多,请看这篇文章:https://blog.csdn.net/m0_37697335/article/details/121026018 |
执行效率
理论上精简版本性能会差一点 资源占用
优化 267 字节 CM3 指令周期[CM3 指令时钟周期] https://developer.arm.com/documentation/ddi0337/h/programmers-model/instruction-set-summary/cortex-m3-instructions |
我使用 STM32F103 来实际测试,就是对所有可能的输入测试(0x00 - 0xFFFFFFFF),测得运行时间为
写了一篇验证文章,如有错误或者不严谨的地方,麻烦指教。 |
写了一篇验证文章,主要是验证的一些过程、数据和方法。 |
跳转指令确实不能在一个机器周期内完成,当有多次跳转时,耗时可能比除法还要久。从目前的分析情况来看,这种算法,确实很优秀。 |
如果感觉没问题的话,请+1 |
欢迎提供更优秀的算法、代码 👍 |
在微信文章上看到了,很棒!留了言似乎还能改进,不用额外空间来折半查找计算最低位bit,我这两天来试试看。 |
#9729 我写的查找32bit最低非0bit位置的算法如下: int __rt_ffs(uint32_t value) {
if (value == 0)
return 0; // 0 means no bit 1
int position = 1; // position start from 1
// search half range
if ((value & 0xFFFF) == 0) { // is lower 16bit 0
position += 16;
value >>= 16;
}
if ((value & 0xFF) == 0) { // is lower 8bit 0
position += 8;
value >>= 8;
}
if ((value & 0xF) == 0) { // is lower 4bit 0
position += 4;
value >>= 4;
}
if ((value & 0x3) == 0) { // is lower 2bit 0
position += 2;
value >>= 2;
}
if ((value & 0x1) == 0) { // is lower 1bit 0
position += 1;
}
return position;
} |
拉取/合并请求描述:(PR description)
[
这份PR的目的是增加一种新的查找字节最低非0位的算法,该算法比一般的位图算法更省空间,同时对于 32bit以及更长的字节,该算法查找字节最低非0位的实现路径也更加高效。
该算法的原理为:假设 X 为 uint32_t 类型的变量, 则 X & (X - 1) ^ X 的算式可以得到仅含字节最低非0位的结果,也就是将所有的可能转变为仅有的32种可能,也就是32个 “1在不同bit位” 的数,接着将这32个数对 37 取余,能够得到互不相同的结果,利用这些结果建立一个位图表,就能实现在O(1)的时间复杂度上查找到目标结果。
该算法已经经过测试程序对比,输入所有可能的输入,得到的结果与之前的位图算法相同。
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
#if 0
代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up