哪个整数操作在Rust中具有更高性能的替代方法?

时间:2016-12-12 13:25:18

标签: rust micro-optimization

在Rust中编写将运行数百万次的整数函数(想想像素处理)时,使用性能最高的操作很有用 - 类似于C / C ++。

虽然参考手册解释了行为的变化,但并不总是清楚哪种方法的性能高于标准(参见注释1。)整数算术运算。我假设wrapping_add编译成等同于C的补充。

在标准操作中(加/减/乘/模/除/移位/位操作...),哪些操作具有更高性能的替代方法,默认情况下不使用?

注意:

  1. 通过标准我的意思是使用符号a + bi / kc % e等等的整数算术。
    写作时你会用什么数学表达式 - 除非您特别需要使用包装或返回溢出的方法之一。
  2. 我意识到回答这个问题可能需要一些研究。因此,我很高兴通过查看生成的程序集来查看哪些操作正在使用未经检查/原始操作。
  3. 可能是已检查/未检查操作之间的速度差异不大,如果是这样的情况我仍然仍然喜欢能够将“快速”版本的函数写入与“安全”版本进行比较,得出自己的结论是否是给定函数的合理选择。
  4. 提到像素处理后,SIMD已成为可能的解决方案。尽管这是一个很好的建议。这仍然留给我们使用SIMD优化不能的情况,因此快速整数算法的一般情况仍有待考虑。

3 个答案:

答案 0 :(得分:6)

  

在标准操作(加/减/乘/模/除/移位/位操作...)中,哪些操作具有更高性能的替代方法,默认情况下不使用?

请注意,Rust是为性能而设计的;因此,在 Debug 中检查整数操作时,它们被定义为发布中的 wrap ,除非您特别指示编译器。

因此,在使用默认选项的发布模式下,严格之间没有性能差异:

  • +wrapping_add
  • -wrapping_sub
  • *wrapping_mul
  • /wrapping_div
  • TODO:检查模数,移位,否定和绝对

对于无符号整数,性能严格地类似于C或C ++;但是,对于有符号整数,优化器可能会产生不同的结果,因为有符号整数的下溢/溢出是C和C ++中的未定义行为(gcc和Clang接受-fwrapv标志,即使对于有符号整数也要求包装,但它&#39 ; s不是默认值。)

我希望使用checked_*overflow_*saturating_*方法一般会慢一点。

然后,有趣的切线是了解当您翻转开关并明确要求检查算术时会发生什么。

目前,Rust实现 1 是下溢/溢出检查的精确实现。每个加法,减法,乘法,...都是独立检查的,优化器不擅长融合这些分支。

具体来说,精确实现会排除临时溢出:5 + x - 5无法优化为x,因为5 + x可能会溢出。它也排除了一般的自动矢量化。

只有当优化器能够证明没有溢出时(通常它不能),您可能希望重新获得更易于优化的无分支路径。

应该注意的是,在通用软件上,影响几乎不可察觉,因为算术指令只代表总成本的一小部分。然而,当这个比例上升时,它可能非常明显,实际上它出现在与Clang的SPEC2006基准测试的一部分中。

此开销足以被视为不适合默认激活支票。

1 这是由于LLVM方面的技术限制; Rust实现只委托给LLVM。

将来,希望检查的模糊实现可用。模糊实现背后的想法是,不是检查每个操作,而是执行它们并且设置标志或者在下溢/溢出的情况下中断值。然后,在使用结果之前,执行检查(分支)。

根据Joe Duffy的说法,他们在Midori中有这样的实现,性能影响几乎不可察觉,所以它似乎是可行的。但是,我还没有意识到在LLVM中有任何类似的东西。

答案 1 :(得分:5)

Rust不保证其运营速度。如果您需要保证,则需要调用汇编程序。

也就是说,当前Rust转发到LLVM,所以你可以调用内在函数,它将1:1映射到LLVM内在函数并使用这些保证。但是,无论你做什么都不是asm,请注意优化器可能对你认为最优的东西有不同的看法,因此不优化你对LLVM内在函数的手动调用。

也就是说,Rust努力尽可能快,所以你可以假设(或者只是看标准库的实现)所有具有相同LLVM内在函数的操作都将映射到该LLVM内在函数,因此和LLVM一样快。

对于给定的基本算术运算,哪个操作最快是没有一般规则的,因为它完全取决于您的用例。

答案 2 :(得分:3)

  

想像素处理

那么你根本不应该考虑单值操作;您想要使用SIMD指令。这些目前在稳定的Rust中不可用,但有些可通过功能门控功能访问,并且所有功能都可通过汇编获得。

  

LLVM是否有可能将代码优化为SIMD,就像它对clang一样?

作为aochagavia already replied,是的,LLVM将自动向量化某些类型的代码。但是,当您要求最高性能时,您通常不希望自己处于优化器的一时兴起。我倾向于希望在我的普通普通代码中进行自动向量化,然后为我的重数学内核编写直线代码,然后编写SIMD代码并测试速度的正确性和基准。