gpt4 book ai didi

rust - 在 Rust 中链接检查算术运算

转载 作者:行者123 更新时间:2023-11-29 07:54:35 25 4
gpt4 key购买 nike

在进行带有溢出检查的整数运算时,计算通常需要组合多个算术运算。在 Rust 中链接检查算法的一种直接方法是使用 checked_* 方法和 Option 链接:

fn calculate_size(elem_size: usize,
length: usize,
offset: usize)
-> Option<usize> {
elem_size.checked_mul(length)
.and_then(|acc| acc.checked_add(offset))
}

然而,这告诉编译器为每个基本操作生成一个分支。我遇到了一种使用 overflowing_* 方法的更展开的方法:

fn calculate_size(elem_size: usize,
length: usize,
offset: usize)
-> Option<usize> {
let (acc, oflo1) = elem_size.overflowing_mul(length);
let (acc, oflo2) = acc.overflowing_add(offset);
if oflo1 | oflo2 {
None
} else {
Some(acc)
}
}

无论溢出如何继续计算并使用按位或聚合溢出标志确保在整个评估中最多执行一个分支(前提是 overflowing_* 的实现生成无分支代码)。这种优化友好的方法比较麻烦,在处理中间值时需要谨慎。

有没有人知道 Rust 编译器如何在各种 CPU 架构上优化上述任一模式,以判断显式展开是否值得,尤其是对于更复杂的表达式?

最佳答案

Does anyone have experience with how the Rust compiler optimizes either of the patterns above on various CPU architectures, to tell whether the explicit unrolling is worthwhile, especially for more complex expressions?

您可以使用 playground检查 LLVM 如何优化事物:只需单击“LLVM IR”或“ASM”而不是“运行”。在要检查的函数上贴上#[inline(never)],注意传递运行时参数,避免常量折叠。如 here :

use std::env;

#[inline(never)]
fn calculate_size(elem_size: usize,
length: usize,
offset: usize)
-> Option<usize> {
let (acc, oflo1) = elem_size.overflowing_mul(length);
let (acc, oflo2) = acc.overflowing_add(offset);
if oflo1 | oflo2 {
None
} else {
Some(acc)
}
}

fn main() {
let vec: Vec<usize> = env::args().map(|s| s.parse().unwrap()).collect();
let result = calculate_size(vec[0], vec[1], vec[2]);
println!("{:?}",result);
}

然而,您将得到的答案是,不幸的是,Rust 和 LLVM 中的溢出内在函数是为了方便而不是为了性能而编码的。这意味着虽然显式展开可以很好地优化,但目前指望 LLVM 来优化已检查的代码是不现实的。

通常这不是问题;但对于性能热点,您可能需要手动展开。

注意:这种性能不足也是在 Release 模式下默认禁用溢出检查的原因。

关于rust - 在 Rust 中链接检查算术运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36112911/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com