"-ftrapv"和"-fwrapv":哪个效率更好?

"-ftrapv" and "-fwrapv": Which is better for efficiency?

本文关键字:效率 更好 -ftrapv -fwrapv      更新时间:2023-10-16

来自GNU的网站:

  • -ftrapv

    该选项在加、减、乘操作时产生有符号溢出陷阱。

  • -fwrapv

该选项指示编译器假设加法、减法和乘法的有符号算术溢出使用双补数表示。此标志启用某些优化,禁用其他优化。

https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Code-Gen-Options.html

我有两个问题:

  1. 这些选项中哪一个对性能更好?
  2. -ftrapv定义说它产生"陷阱"时,这是什么意思?这意味着例外吗?(我猜没有,但值得一问。)

这两个选项的全部意义是给优化器比通常更少的余地。因此,除非您在优化器中遇到错误,否则最快的方法应该是两者都不使用,优化器假设您的代码没有任何溢出,并且不会发出处理溢出的代码。

当-ftrapv定义说它生成"陷阱"是什么意思?这意味着例外吗?

这并不意味着c++异常。它是目标相关的,但假设是x86,这意味着GCC运行时库会引发SIGABRT,这通常会中止您的程序。在其他平台上,它可能会使用导致硬件异常的特殊CPU指令。它主要用于调试目的,也可能在少数情况下用于安全,在这些情况下,溢出后继续的风险大于程序突然终止的风险。

-ftrapv是最慢的,因为它需要添加额外的代码来检测和捕获几乎所有对有符号整数的操作的溢出,除非编译器有足够的关于值范围的信息来证明操作不会溢出。

-fwrapv可能是下一个最慢的,因为它禁止某些假设值永远不换行的优化,但这种影响相当小,所以-fwrapv的性能通常与不提供这些选项中的任何一个相似甚至相同。

如果有一种方法告诉编译器,在溢出的情况下,它可以自由地从满足应用程序需求的所有可能的行为中选择,则将实现最佳性能。只有当程序员能够确信程序永远不会接收到任何导致溢出的输入,甚至是可以想象到的最故意的反复无常的溢出行为都能满足要求时,才会将溢出视为UB,从而产生最佳行为。

在可以接受编译器从大量可能的输出中任意选择的情况下,只要总体行为仍然受到约束,与-fwrapv相比,使用overflow UB可能会产生源代码复杂性和运行时性能的最坏组合,因为程序员必须在源代码中指定编译器将为-fwrapv自动生成的所有操作。性能将不如一个不那么激进的优化器所能达到的效果,该优化器是围绕"产生任意数据,但约束行为"的思想设计的,但是gcc没有提供这样的选项。

在编译器中捕获溢出往往比让溢出计算结束(或者——如果编译器允许——让它们被视为具有任意扩展精度,可能以不确定的方式表现)要昂贵得多,但有时可能比在代码中手动捕获溢出便宜。在编译器中捕获溢出是否有用取决于应用程序是否需要它。