整数之间的转换很昂贵吗? [英] Is casting between integers expensive?

查看:26
本文介绍了整数之间的转换很昂贵吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个项目,我正在做很多基于索引的计算.我有几行,如:

I am working on a project where I am doing a lot of index-based calculation. I have a few lines like:

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

start.xiusizes 和 delta_xisize.我的大部分数据都是未签名的,因此存储签名没有多大意义.另一方面,当我操作一个数组时,我访问了很多我必须将所有内容转换回 usize ,如上所示.

start.x and i are usizes and delta_x is of type isize. Most of my data is unsigned, therefore storing it signed would not make much sense. On the other hand, when I manipulate an array I am accessing a lot I have to convert everything back to usize as seen above.

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

Is casting between integers expensive? Does it have an impact on runtime performance at all?

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

Are there other ways to handle index arithmetics easier / more efficiently?

推荐答案

看情况

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

It's basically impossible to answer your question in isolation. These types of low-level things can be aggressively combined with operations that have to happen anyway, so any amount of inlining can change the behavior. Additionally, it strongly depends on your processor; changing to a 64-bit number on an 8-bit microcontroller is probably pretty expensive!

我的一般建议是不要担心.保持您的类型一致,获得正确的答案,然后分析您的代码并修复您发现的问题.

My general advice is to not worry. Keep your types consistent, get the right answers, then profile your code and fix the issues you find.

务实地说,你打算做什么?

也就是说,这里有一些适用于 x86-64 和 Rust 1.18.0 的具体内容.

That said, here's some concrete stuff for x86-64 and Rust 1.18.0.

基本没有影响.如果这些是内联的,那么您可能永远不会看到任何程序集.

Basically no impact. If these were inlined, then you probably would never even see any assembly.

#[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

扩展值

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

Extending a value

These have to sign- or zero-extend the value, so some kind of minimal operation has to occur to fill those extra bits:

#[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

截断一个值

截断又是一个动作,基本上没有影响.

Truncating a value

Truncating is again just another move, basically no impact.

#[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 上的一条指令.然后你会陷入关于手术需要多长时间"的复杂问题,而这甚至更难.

这篇关于整数之间的转换很昂贵吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆