将 64b x 32b 除以 64b 整数
Multiply 64b x 32b divide by 64b integers
将 64b x 32b 除以 64b 整数的最快交叉 platform/compiler(GCC 和 MSVC)方法是什么:
uint64_t counter;
uint32_t resolution = NANOS_IN_SEC; // NANOS_IN_SEC = 1000000000
uint64_t freq;
uint64_t res = (counter * resolution) / freq; // but without overflow/losing precision
保证结果始终适合 64b。
我查了很多答案,但都解了64b x 64b的乘法,而且速度很慢。
当我们假设第二个操作数仅为 32b 时,是否有解决方案如何降低代码复杂性?
我最终找到了具体的解决方案,它甚至可以接受 32b 以上的频率。
static uint64_t counter_and_freq_to_nanotime(uint64_t counter, uint64_t freq)
{
uint32_t div = 1, freq32;
uint64_t q, r;
while (freq >= (1ull << 32)) {
freq /= 2;
div *= 2;
}
freq32 = freq;
q = counter / freq32;
r = counter % freq32;
return (q * NANOS_IN_SEC + (r * NANOS_IN_SEC) / freq32) * div;
}
快速基准测试(E5-2699v4,Win7 x64):
MFllMulDiv
:~50 纳秒
- 此解决方案:~1.5 ns
将 64b x 32b 除以 64b 整数的最快交叉 platform/compiler(GCC 和 MSVC)方法是什么:
uint64_t counter;
uint32_t resolution = NANOS_IN_SEC; // NANOS_IN_SEC = 1000000000
uint64_t freq;
uint64_t res = (counter * resolution) / freq; // but without overflow/losing precision
保证结果始终适合 64b。
我查了很多答案,但都解了64b x 64b的乘法,而且速度很慢。
当我们假设第二个操作数仅为 32b 时,是否有解决方案如何降低代码复杂性?
我最终找到了具体的解决方案,它甚至可以接受 32b 以上的频率。
static uint64_t counter_and_freq_to_nanotime(uint64_t counter, uint64_t freq)
{
uint32_t div = 1, freq32;
uint64_t q, r;
while (freq >= (1ull << 32)) {
freq /= 2;
div *= 2;
}
freq32 = freq;
q = counter / freq32;
r = counter % freq32;
return (q * NANOS_IN_SEC + (r * NANOS_IN_SEC) / freq32) * div;
}
快速基准测试(E5-2699v4,Win7 x64):
MFllMulDiv
:~50 纳秒- 此解决方案:~1.5 ns