main.rs
#![feature(core_intrinsics)]
fn print_type_of<T>(_: &T) {
println!("{}", unsafe { std::intrinsics::type_name::<T>() });
}
fn main() {
let x = 93;
let y = 93.1;
print_type_of(&x);
print_type_of(&y);
}
如果我用“rustc +nightly ./main.rs”编译,我得到这个输出:
$ ./main
i32
f64
我运行的是 x86_64 Linux 机器。默认情况下,浮点变量是 double 的,这很好。 为什么整数只有 4 个字节?我应该使用哪个?如果我不需要 i64,我应该使用 i32 吗? i32 的性能更好吗?
最佳答案
Are i32 better for performance?
这实际上是一件微妙的事情。如果我们查找一些 recent instruction-level benchmarks例如 SkylakeX ,在大多数情况下 64 位和 32 位指令之间非常明显没有区别。除法是一个异常(exception),64 位除法比 32 位除法慢,即使是对相同的值进行除法也是如此(除法是为数不多的取决于其输入值的可变时间指令之一)。
对数据使用 i64 也会降低自动矢量化的效率 - 这也是小于 32 位的数据具有超出数据大小优化用途的罕见地方之一。当然,数据大小对于 i32 与 i64 的问题也很重要,使用 i64 的大数组很容易变慢,因为它更大,因此需要更多的缓存空间和(如果适用)更多的带宽。因此,如果问题是 [i32]
与 [i64]
,那么它很重要。
更微妙的是,使用 64 位操作意味着代码将平均包含更多的 REX 前缀,从而使代码的密度略微降低,这意味着更少的代码可以一次放入 L1 代码缓存中。虽然这是一个很小的影响。在代码中只包含一些 64 位变量不是问题。
尽管如此,绝对不要过度使用 i32,尤其是在您真正应该使用
的地方。例如,不要这样做:
// don't do this
for i in 0i32 .. data.len() as i32 {
sum += data[i as usize];
}
这会导致性能大幅下降。现在循环中不仅有一个毫无意义的符号扩展,它还破坏了边界检查消除和自动矢量化。但当然,一开始就没有理由编写那样的代码,这不自然,而且比正确执行更难。
关于rust - 我应该在 64 位机器上使用 i32 还是 i64?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51685509/