“-ftrapv”和“-fwrapv”:哪个更有效率?
"-ftrapv" and "-fwrapv": Which is better for efficiency?
来自 GNU 的网站:
-ftrapv
This option generates traps for signed overflow on addition, subtraction, multiplication operations.
-fwrapv
This option instructs the compiler to assume that signed arithmetic overflow of addition, subtraction and multiplication wraps around using twos-complement representation. This flag enables some optimizations and disables others.
https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Code-Gen-Options.html
我有两个问题:
- 这些选项中哪个更适合性能?
-ftrapv
定义说它生成“陷阱”是什么意思?这是否意味着例外? (我猜不是,但值得一问。)
这两个选项的 重点 是给优化器 比通常情况下少 的回旋余地。因此,除非您在优化器中遇到错误,否则最快的方法应该是两者都不使用,优化器假定您的代码没有任何溢出并且不会发出代码来处理溢出。
What what does it mean when the -ftrapv definition says it generates "traps?" Does this mean exceptions?
这并不意味着 C++ 异常。它依赖于目标,但假设是 x86,这意味着 GCC 运行时库会引发 SIGABRT,这通常会中止您的程序。在其他平台上,它可能会使用导致硬件异常的特殊 CPU 指令。它主要用于调试目的,也许在少数情况下用于安全,溢出后继续运行的风险大于程序突然终止的风险。
如果有一种方法可以告诉编译器在溢出的情况下它可以自由地select从满足应用程序要求的所有可能行为中选择。将溢出视为 UB 只会产生最佳行为,前提是程序员可以非常确定程序永远不会收到任何导致溢出的输入,即使是可以想象到的最故意反复无常的溢出行为也能满足要求。
在允许编译器从大量可能的输出中任意选择的情况下,前提是整体行为仍然受到约束,溢出 UB 可能会产生最糟糕的组合与 -fwrapv 相比,源代码复杂性和 运行 时间性能,因为程序员必须在源代码中指定编译器会为 -fwrapv 自动生成的所有操作。性能将不如围绕 "yield arbitrary data, but constrained behavior" 思想设计的不太激进的优化器所能达到的性能,但 gcc 不提供此类选项。
在编译器中捕获溢出比让溢出的计算回绕(或者——如果编译器允许——让它们被视为具有可能以非确定性方式运行的任意扩展精度)要昂贵得多。 ,但有时可能比在代码中手动捕获溢出更便宜。在编译器中捕获溢出是否有用将取决于应用程序要求是否需要它。
-ftrapv
是最慢的,因为它需要添加额外的代码来检测和捕获几乎所有对有符号整数的操作的溢出,除非编译器有足够的值范围信息来证明操作没有t溢出。
-fwrapv
可能是下一个最慢的,因为它禁止某些假设值永不回绕的优化,但这种影响相当小,因此 -fwrapv
的性能通常相似甚至相同不提供这些选项中的任何一个。
来自 GNU 的网站:
-ftrapv
This option generates traps for signed overflow on addition, subtraction, multiplication operations.
-fwrapv
This option instructs the compiler to assume that signed arithmetic overflow of addition, subtraction and multiplication wraps around using twos-complement representation. This flag enables some optimizations and disables others.
https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Code-Gen-Options.html
我有两个问题:
- 这些选项中哪个更适合性能?
-ftrapv
定义说它生成“陷阱”是什么意思?这是否意味着例外? (我猜不是,但值得一问。)
这两个选项的 重点 是给优化器 比通常情况下少 的回旋余地。因此,除非您在优化器中遇到错误,否则最快的方法应该是两者都不使用,优化器假定您的代码没有任何溢出并且不会发出代码来处理溢出。
What what does it mean when the -ftrapv definition says it generates "traps?" Does this mean exceptions?
这并不意味着 C++ 异常。它依赖于目标,但假设是 x86,这意味着 GCC 运行时库会引发 SIGABRT,这通常会中止您的程序。在其他平台上,它可能会使用导致硬件异常的特殊 CPU 指令。它主要用于调试目的,也许在少数情况下用于安全,溢出后继续运行的风险大于程序突然终止的风险。
如果有一种方法可以告诉编译器在溢出的情况下它可以自由地select从满足应用程序要求的所有可能行为中选择。将溢出视为 UB 只会产生最佳行为,前提是程序员可以非常确定程序永远不会收到任何导致溢出的输入,即使是可以想象到的最故意反复无常的溢出行为也能满足要求。
在允许编译器从大量可能的输出中任意选择的情况下,前提是整体行为仍然受到约束,溢出 UB 可能会产生最糟糕的组合与 -fwrapv 相比,源代码复杂性和 运行 时间性能,因为程序员必须在源代码中指定编译器会为 -fwrapv 自动生成的所有操作。性能将不如围绕 "yield arbitrary data, but constrained behavior" 思想设计的不太激进的优化器所能达到的性能,但 gcc 不提供此类选项。
在编译器中捕获溢出比让溢出的计算回绕(或者——如果编译器允许——让它们被视为具有可能以非确定性方式运行的任意扩展精度)要昂贵得多。 ,但有时可能比在代码中手动捕获溢出更便宜。在编译器中捕获溢出是否有用将取决于应用程序要求是否需要它。
-ftrapv
是最慢的,因为它需要添加额外的代码来检测和捕获几乎所有对有符号整数的操作的溢出,除非编译器有足够的值范围信息来证明操作没有t溢出。
-fwrapv
可能是下一个最慢的,因为它禁止某些假设值永不回绕的优化,但这种影响相当小,因此 -fwrapv
的性能通常相似甚至相同不提供这些选项中的任何一个。