作者:nuabolalalala4_135 | 来源:互联网 | 2022-12-08 17:18
主
#![feature(core_intrinsics)]
fn print_type_of(_: &T) {
println!("{}", unsafe { std::intrinsics::type_name::() });
}
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机器。浮点变量默认情况下是双精度的,这很好。为什么整数只有4个字节?我应该使用哪个?如果不需要i64,应该使用i32吗?i32的性能更好吗?
1> harold..:
i32的性能更好吗?
这实际上是一种微妙的事情。如果我们查看一些最新的指令级基准(例如SkylakeX),则在大多数情况下,显然在64位和32位指令之间没有明显的区别。例外是除法,即使对相同的值进行除法,64位除法也比32位除法慢(除法是少数几个依赖于其输入值的可变时间指令之一)。
对数据使用i64也会使自动矢量化的效率降低-这也是小于32位的数据除了数据大小优化之外还具有其他用途的罕见地方之一。当然,数据大小对于i32 vs i64问题也很重要,使用较大的i64阵列可能会很慢,因为它更大,因此会占用更多的缓存空间(如果适用)和更多的带宽。因此,如果问题是[i32]
vs [i64]
,那么这很重要。
更微妙的事实是,使用64位操作意味着代码平均将包含更多的REX前缀,从而使代码的密度略低,这意味着较少的代码将立即放入L1代码缓存中。但是,这是一个很小的效果。在代码中只包含一些64位变量不是问题。
尽管如此,绝对不要过度使用 i32,尤其是在您确实应该使用 i32的地方usize
。例如,不要这样做:
// don't do this
for i in 0i32 .. data.len() as i32 {
sum += data[i as usize];
}
这会导致较大的性能下降。现在,循环中不仅没有无意义的符号扩展,而且还克服了边界检查消除和自动矢量化的问题。但是当然,首先没有理由编写这样的代码,这比正确地编写代码不自然且更难。