是否存在像编译器那样优化整数除法的CPU?
运行时除法优化的CPU硬件支持验证
优化编译器通常会把非2的幂次常量除法转换为倒数乘法,以此规避耗时的div指令。有人好奇:有没有CPU能在运行时做这类优化——把常用除数对应的「魔法常数」缓存到内部表中,要是后续碰到相同除数,就用缓存的常数通过乘法来计算除法?
为了验证这点,有人分别在x64(基于C++)和M1(基于Rust)平台开展实验:对比重复除以固定除数与除数动态变化两种场景下的除法性能。结果显示二者性能相近,由此推测这些CPU并不支持该运行时优化,但目前未找到相关公开官方资料佐证。
Rust实验代码
type div32 = i32; #[inline(never)] fn div_bench_fn(dividend: div32, mut divisor: div32, mut step: div32) -> f64 { step = std::hint::black_box(step); const LOOP_COUNT: u32 = 100_000_000; let start = std::time::Instant::now(); let mut tmp = 0; for _ in 0..LOOP_COUNT { let res = dividend % divisor; divisor += step; tmp ^= res; std::hint::black_box(tmp); } let elapsed = start.elapsed().as_secs_f64(); let div_sec = (LOOP_COUNT as f64) / elapsed; div_sec / 1_000_000. } fn main() { for _ in 0..10 { println!("--"); println!(" static {:.2}m div/sec", div_bench_fn(0x12345678, 127, 0)); println!(" dynamic {:.2}m div/sec", div_bench_fn(0x12345678, 127, 1)); } }
ARMv8.5-A循环汇编代码
divbench[0x1000017e8] <+64>: cbz w9, 0x10000185c ; <+180> // panic if divisor == 0 divbench[0x1000017ec] <+68>: sdiv w13, w11, w9 divbench[0x1000017f0] <+72>: msub w13, w13, w9, w11 divbench[0x1000017f4] <+76>: add w9, w9, w19 divbench[0x1000017f8] <+80>: eor w8, w13, w8 divbench[0x1000017fc] <+84>: str w8, [sp, #0xc] divbench[0x100001800] <+88>: subs w10, w10, #0x1 divbench[0x100001804] <+92>: b.ne 0x1000017e8 ; <+64>
实验结果(数值越高性能越好)
-- static 1018.66m div/sec dynamic 1568.52m div/sec -- static 1574.76m div/sec dynamic 1574.63m div/sec -- static 1575.77m div/sec dynamic 1574.38m div/sec -- static 1577.74m div/sec dynamic 1581.09m div/sec -- static 1585.35m div/sec dynamic 1591.46m div/sec -- static 1572.47m div/sec dynamic 1585.13m div/sec -- static 1560.05m div/sec dynamic 1571.18m div/sec -- static 1575.05m div/sec dynamic 1550.98m div/sec -- static 1556.27m div/sec dynamic 1571.85m div/sec -- static 1581.93m div/sec dynamic 1579.43m div/sec
内容的提问来源于stack exchange,提问作者Iwa
相关产品推荐
相关产品推荐

