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计算机。浮点变量默认情况下是双精度的,这很好。 为什么整数只有4个字节?我应该使用哪个?如果不需要i64,应该使用i32吗? i32的性能更好吗?
答案 0 :(得分:4)
The Rust Programming Language说:
[...]整数类型默认为
i32
:即使在64位系统上,这种类型通常也是最快的。
然后(in the next section):
默认类型为
f64
,因为在现代CPU上,它的速度与f32
大致相同,但精度更高。
但是,这是相当简化的。您应该使用哪种整数类型在很大程度上取决于您的程序。最初编写程序时,请不要考虑速度,除非您已经知道速度将是一个问题。在绝大多数代码中,速度并不重要:即使在性能至关重要的应用程序中,大多数代码还是冷代码。相反,正确性总是很重要。
还要注意,只有 unconstrained 数值变量默认为i32
/ f64
。在需要特定数字类型的上下文中使用变量后,编译器将立即使用该类型。
答案 1 :(得分:4)
i32的性能更好吗?
这实际上是一种微妙的事情。如果我们以recent instruction-level benchmarks为例查看SkylakeX,那么在大多数情况下, 显然没有64位和32位指令之间的差异。例外是除法,即使对相同的值进行除法,64位除法也比32位除法慢(除法是为数不多的取决于其输入值的可变时间指令之一)。
将i64用于数据还会降低自动矢量化的效率-这也是小于32位的数据除了数据大小优化之外还具有其他用途的罕见地方之一。当然,数据大小对于i32 vs i64问题也很重要,使用较大的i64阵列可能会很慢,因为它更大,因此会占用更多的缓存空间(如果适用)和更多的带宽。因此,如果问题是[i32]
与[i64]
,那么这很重要。
更微妙的是,使用64位操作意味着代码平均将包含更多的REX前缀,这使得代码的密度略低,这意味着更少的代码将立即放入L1代码缓存中。但是,这是一个很小的效果。在代码中只包含一些64位变量不是问题。
尽管如此,i32绝对不要滥用,尤其是在您确实应该拥有usize
的地方。例如,不要这样做:
// don't do this
for i in 0i32 .. data.len() as i32 {
sum += data[i as usize];
}
这会导致较大的性能下降。现在,循环中不仅没有无意义的符号扩展,而且还克服了边界检查消除和自动矢量化的问题。但是,当然,首先没有理由编写这样的代码,这比做正确的事不自然且更难。
答案 2 :(得分:0)
首先,您应该根据自己的需求/要求设计应用程序。也就是说,如果您需要“大”整数,请使用大类型。如果不需要它们,则应使用小型字体。
如果您遇到任何性能问题(并且仅此),则应将类型调整为您可能不需要的类型。