__int128手动取模实现是否比编译器内置%运算符性能更优?
手动实现__int128取模运算比GCC内置运算符更快的现象验证请求
最近我发现一个有趣的性能现象:手动计算__int128的取模运算符速度明显快于GCC的内置运算符,下面以取模9为例演示这个方法,该思路还能推广到任意数值的取模计算。
两种实现方式
内置运算符实现
uint64_t mod9_v1(unsigned __int128 n) { return n % 9; }
手动优化实现
uint64_t mod9_v2(unsigned __int128 n) { uint64_t r = 0; r += (uint32_t)(n); r += (uint32_t)(n >> 32) * (uint64_t)4; r += (uint32_t)(n >> 64) * (uint64_t)7; r += (uint32_t)(n >> 96); return r % 9; }
性能测试结果
我用1亿个随机数做了性能测试,结果如下:
mod9_v1(内置实现):3.986052秒mod9_v2(手动实现):1.814339秒
测试环境信息:
- 编译器:GCC 9.3.0
- 编译选项:
-march=native -O3 - 硬件:AMD Ryzen Threadripper 2990WX
生成的汇编代码
为了更直观对比,我提取了两种实现编译后的汇编代码:
mod9_v1的汇编输出
mod9_v1: sub rsp, 8 mov edx, 9 xor ecx, ecx call __umodti3 add rsp, 8 ret
mod9_v2的汇编输出
mod9_v2: mov rax, rdi shrd rax, rsi, 32 mov rdx, rsi mov r8d, eax shr rdx, 32 mov eax, edi add rax, rdx lea rax, [rax+r8*4] mov esi, esi lea rcx, [rax+rsi*8] sub rcx, rsi mov rax, rcx movabs rdx, -2049638230412172401 mul rdx mov rax, rdx shr rax, 3 and rdx, -8 add rdx, rax mov rax, rcx sub rax, rdx ret
在准备向GCC Bugzilla提交这个性能问题之前,我想确认一下:这个现象是否能在你的环境中复现?
内容的提问来源于stack exchange,提问作者DaBler
相关产品推荐
相关产品推荐

