gpt4 book ai didi

rust - 128bit由64bit原生划分

转载 作者:行者123 更新时间:2023-12-05 01:22:34 24 4
gpt4 key购买 nike

我需要在 Rust 中执行 128 位 x 64 位除法。 x86-64 ISA 包含用于此目的的 native DIV 指令。但是,我编译的测试代码没有使用这条指令。

测试代码:

pub fn div(hi: u64, lo: u64, divisor: u64) -> u64 {
assert!(hi < divisor);

let dividend = ((hi as u128) << 64) + lo as u128;
(dividend / divisor as u128) as u64
}

编译器资源管理器输出:

example::div:
push rax
cmp rdi, rdx
jae .LBB0_1
mov rax, rdi
mov rdi, rsi
mov rsi, rax
xor ecx, ecx
call qword ptr [rip + __udivti3@GOTPCREL]
pop rcx
ret
.LBB0_1:
...

相反,通过 __udivti3 执行低效的 128 位乘以 128 位除法。这可能是因为如果商不适合 64 位,则 DIV 指令会导致 CPU 异常。然而,就我而言,这是不可能的:hi < divisor, lo < 2^64 -> dividend = hi * 2^64 + lo <= (divisor - 1) * 2^64 + 2^64 - 1 = divisor * 2^64 - 1-> 股息/除数 <= 2^64 - 1/除数 < 2^64

如何强制编译器使用 native 指令?

最佳答案

您唯一的选择是使用内联汇编。可能有编译器标志的模糊组合可以强制 llvm 执行优化本身,但我认为试图找到它不值得付出努力。使用汇编,它看起来像这样:

use std::arch::asm;
pub fn div(hi: u64, lo: u64, divisor: u64) -> u64 {

assert!(hi < divisor);

#[cfg(target_arch = "x86_64")]
unsafe {
let mut quot = lo;
let mut _rem = hi;
asm!(
"div {divisor}",
divisor = in(reg) divisor,
inout("rax") quot,
inout("rdx") _rem,
options(pure, nomem, nostack)
);
quot
}
#[cfg(not(target_arch = "x86_64"))]
{
let dividend = ((hi as u128) << 64) + lo as u128;
(dividend / divisor as u128) as u64
}
}

Godbolt

在 x86_64 上,这只是将除法编译为一个小的寄存器改组,然后是 div,并在其他系统上执行对 __udivti3 的调用。它也不应该过多地妨碍优化器,因为它是纯粹的。

绝对值得对您的应用程序进行实际基准测试,看看这是否真的有帮助。与内联汇编相比,llvm 更容易推理整数除法,并且错过其他地方的优化很容易导致此版本运行速度比使用默认版本慢。

关于rust - 128bit由64bit原生划分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73667228/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com