优化SuperH汇编:为何用对数表而非倒数表加速除法?
针对你在SuperH汇编优化中遇到的疑问,对数+指数表方案相比单纯的倒数表,主要有这些实用优势:
覆盖更大的数值范围
倒数表的大小和除数的位数直接挂钩,比如要支持16位除数就得做65536项的表,32位除数的话表的体积直接到4GB,完全不现实。而log+exp可以通过数值归一化——比如把数拆成「基数×2^指数」的形式,只对基数部分做log/exp查表,指数部分用加减运算处理,用很小的表就能覆盖从极小到极大的数值范围,不管是整数还是浮点数都适用。复用性强,适配多运算场景
如果你的应用里不止有除法,还涉及乘法、平方根、幂运算,log+exp表能一套搞定:- 乘法:
log(a) + log(b) → exp - 除法:
log(a) - log(b) → exp - 平方根:
log(a)/2 → exp
不用为每种运算单独维护专用表,反而能减少整体内存占用和代码复杂度,对资源有限的SuperH嵌入式平台来说很实用。
- 乘法:
精度调整更灵活
倒数表要提升精度,只能靠增大表的规模,这会直接拉高内存开销。而log+exp方案可以通过插值算法(比如线性插值、二次插值)在表大小不变的情况下提升计算精度,甚至可以针对业务中常用的数值区间做局部加密的表,在精度和内存之间找到更优的平衡,比单纯堆表项更高效。适配浮点数的天然优势
要是你处理的是浮点数除法,log+exp的逻辑和浮点数的「符号位+指数位+尾数位」结构完全契合:提取指数位做加减,只对尾数部分做log/exp查表,表的大小只需要覆盖尾数的范围(比如IEEE754单精度浮点数的尾数是23位,不用做2^23的大表,靠插值就能满足精度要求)。而倒数表处理浮点数要么得拆分整数、小数部分分别处理,要么表的体积会爆炸。缓存命中率的隐性优势
虽然看起来要存两张表,但如果你的应用复用这套表处理多种运算,反而能减少缓存中加载的表数量,避免频繁的缓存换入换出。再加上你提到的交错存储,把log和exp的对应项放在同一缓存行里,一次内存访问就能拿到需要的两个值,实际内存开销并没有翻倍那么夸张,对缓存不大的SuperH CPU来说,这种复用带来的缓存友好性可能比单纯的倒数表更好。
内容的提问来源于stack exchange,提问作者gfdjjrtiejo

