为了更好地理解 Rust 的恐慌/异常机制,我编写了以下代码:
#![feature(libc)]
extern crate libc;
fn main() {
let mut x: i32;
unsafe {
x = libc::getchar();
}
let y = x - 65;
println!("{}", x);
let z = 1 / y;
println!("{}", z);
}
我想检查 Rust 如何处理被零除的情况。最初我认为它要么接受了一个未处理的 SIGFPE 并死亡,要么它实现了一个处理程序并将其重新路由到一个恐慌(现在可以处理吗?)。
该代码很冗长,因为我想确保 Rust 在编译时知道某些内容为零(因此用户输入为零)时不会执行任何“智能”操作。只需给它一个“A”,它就可以解决问题。
我发现 Rust 实际上生成的代码每次在除法发生之前都会检查零除法。我什至看了一次大会。 :-)
长话短说:我可以禁用此行为吗?我想对于更大的数据集,这可能会对性能产生相当大的影响。为什么不利用我们的 CPU 能力来为我们检测这些东西呢?我可以设置自己的信号处理程序并处理 SIGFPE 吗?
根据Github 上的一个问题 https://github.com/rust-lang/rust/issues/944不久前情况一定有所不同。
我认为事前检查每个部门离“零成本”还很远。你怎么认为?我错过了一些明显的东西吗?
我认为事前检查每个部门离“零成本”还很远。你怎么认为?
你测量了什么?
执行的指令数量是性能的一个非常差的指标;矢量化代码通常更详细,但速度更快。
所以真正的问题是:这个分支机构的成本是多少?
由于故意除以 0 的可能性相当小,并且偶然除以 0 的可能性稍大一些,因此分支总是会被正确预测except当除数为 0 时。但是,考虑到恐慌的代价,错误预测的分支是你最不用担心的。
因此,成本为:
The exact impact is hard to qualify, and for math-heavy code it might have an impact. Though I would remind you that an integer division is ~100 cycles1 to start with, so math-heavy code will shy away from it as much as possible (it's maybe THE single most time consuming instruction in your CPU).
1 See Agner Fog's Instruction Table http://www.agner.org/optimize/instruction_tables.pdf: for example on Intel Nehalem DIV and IDIV on 64-bits integrals have a latency of 28 to 90 cycles and 37 to 100 cycles respectively.
除此之外,rustc 是在 LLVM 之上实现的,它将实际的代码生成委托给 LLVM。因此,rustc 在许多情况下都受到 LLVM 的支配,这就是其中之一。
LLVM 有两个整数除法指令:udiv 和 sdiv http://llvm.org/docs/LangRef.html#udiv-instruction.
两者都具有除数为 0 的未定义行为。
Rust 的目标是消除未定义的行为,所以has防止被 0 除的情况发生,以免优化器破坏发出的代码而无法修复。
它使用 LLVM 手册中建议的检查。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)