我发现手动计算%
运算符__int128
比内置编译器运算符快得多。我将向您展示如何计算模 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;
}
测量超过 100,000,000 个随机数会得出以下结果:
mod9_v1 | 3.986052 secs
mod9_v2 | 1.814339 secs
GCC 9.3.0-march=native -O3
用于 AMD Ryzen Threadripper 2990WX。
这是godbolt的链接。
我想问一下它在你这边的行为是否相同?(在向 GCC Bugzilla 报告错误之前)。
更新: 根据要求,我提供了一个生成的程序集:
mod9_v1:
sub rsp, 8
mov edx, 9
xor ecx, ecx
call __umodti3
add rsp, 8
ret
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