我正在开展一项项目,我正在进行大量基于索引的计算。我有几行如下:
let mut current_x: usize = (start.x as isize + i as isize * delta_x) as usize;
start.x
和i
为usize
,delta_x
属于isize
。我的大多数数据都是无符号的,因此将其签名存储没有多大意义。另一方面,当我操作一个数组时,我正在访问很多,我必须将所有内容转换回usize
,如上所示。
整数之间的铸造是否昂贵?它对运行时性能有影响吗?
还有其他方法可以更轻松/更有效地处理索引算术吗?
答案 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;手术需要多长时间"甚至更难。