整数之间的铸造是否昂贵?

时间:2017-06-21 20:23:44

标签: rust

我正在开展一项项目,我正在进行大量基于索引的计算。我有几行如下:

let mut current_x: usize = (start.x as isize + i as isize * delta_x) as usize;

start.xiusizedelta_x属于isize。我的大多数数据都是无符号的,因此将其签名存储没有多大意义。另一方面,当我操作一个数组时,我正在访问很多,我必须将所有内容转换回usize,如上所示。

整数之间的铸造是否昂贵?它对运行时性能有影响吗?

还有其他方法可以更轻松/更有效地处理索引算术吗?

1 个答案:

答案 0 :(得分:12)

取决于

基本上不可能孤立地回答你的问题。这些类型的低级事物可以积极地与必须发生的操作相结合,因此任何数量的内联都可以改变行为。此外,它很大程度上取决于您的处理器;在8位微控制器上更改为64位数字可能相当昂贵!

我的一般建议是不要担心。保持您的类型一致,获得正确的答案,然后分析您的代码并解决您找到的问题。

务实,你打算做什么

那就是说,这是x86-64和Rust 1.18.0的一些具体内容。

相同尺寸,更改标志

基本上没有影响。如果这些是内联的,那么你可能永远不会看到任何组装。

#[inline(never)]
pub fn signed_to_unsigned(i: isize) -> usize {
    i as usize
}

#[inline(never)]
pub fn unsigned_to_signed(i: usize) -> isize {
    i as isize
}

每个都会生成程序集

movq    %rdi, %rax
retq

扩展值

这些必须对值进行符号或零扩展,因此必须进行某种最小化操作以填充这些额外的位:

#[inline(never)]
pub fn u8_to_u64(i: u8) -> u64 {
    i as u64
}

#[inline(never)]
pub fn i8_to_i64(i: i8) -> i64 {
    i as i64
}

生成程序集

movzbl  %dil, %eax
retq

movsbq  %dil, %rax
retq

截断值

截断只是另一个举动,基本上没有影响。

#[inline(never)]
pub fn u64_to_u8(i: u64) -> u8 {
    i as u8
}

#[inline(never)]
pub fn i64_to_i8(i: i64) -> i8 {
    i as i8
}

生成程序集

movl    %edi, %eax
retq

movl    %edi, %eax
retq

所有这些操作归结为x86-64上的单个指令。然后你会遇到并发症#34;手术需要多长时间"甚至更难