"-ftrapv"和"-fwrapv":哪个效率更好?
"-ftrapv" and "-fwrapv": Which is better for efficiency?
来自GNU的网站:
-ftrapv
该选项在加、减、乘操作时产生有符号溢出陷阱。
-fwrapv
该选项指示编译器假设加法、减法和乘法的有符号算术溢出使用双补数表示。此标志启用某些优化,禁用其他优化。
https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Code-Gen-Options.html
我有两个问题:
- 这些选项中哪一个对性能更好?
- 当
-ftrapv
定义说它产生"陷阱"时,这是什么意思?这意味着例外吗?(我猜没有,但值得一问。)
这两个选项的全部意义是给优化器比通常更少的余地。因此,除非您在优化器中遇到错误,否则最快的方法应该是两者都不使用,优化器假设您的代码没有任何溢出,并且不会发出处理溢出的代码。
当-ftrapv定义说它生成"陷阱"是什么意思?这意味着例外吗?
这并不意味着c++异常。它是目标相关的,但假设是x86,这意味着GCC运行时库会引发SIGABRT,这通常会中止您的程序。在其他平台上,它可能会使用导致硬件异常的特殊CPU指令。它主要用于调试目的,也可能在少数情况下用于安全,在这些情况下,溢出后继续的风险大于程序突然终止的风险。
-ftrapv
是最慢的,因为它需要添加额外的代码来检测和捕获几乎所有对有符号整数的操作的溢出,除非编译器有足够的关于值范围的信息来证明操作不会溢出。
-fwrapv
可能是下一个最慢的,因为它禁止某些假设值永远不换行的优化,但这种影响相当小,所以-fwrapv
的性能通常与不提供这些选项中的任何一个相似甚至相同。
如果有一种方法告诉编译器,在溢出的情况下,它可以自由地从满足应用程序需求的所有可能的行为中选择,则将实现最佳性能。只有当程序员能够确信程序永远不会接收到任何导致溢出的输入,甚至是可以想象到的最故意的反复无常的溢出行为都能满足要求时,才会将溢出视为UB,从而产生最佳行为。
在可以接受编译器从大量可能的输出中任意选择的情况下,只要总体行为仍然受到约束,与-fwrapv相比,使用overflow UB可能会产生源代码复杂性和运行时性能的最坏组合,因为程序员必须在源代码中指定编译器将为-fwrapv自动生成的所有操作。性能将不如一个不那么激进的优化器所能达到的效果,该优化器是围绕"产生任意数据,但约束行为"的思想设计的,但是gcc没有提供这样的选项。
在编译器中捕获溢出往往比让溢出计算结束(或者——如果编译器允许——让它们被视为具有任意扩展精度,可能以不确定的方式表现)要昂贵得多,但有时可能比在代码中手动捕获溢出便宜。在编译器中捕获溢出是否有用取决于应用程序是否需要它。
- C++:将控制台输出存储在宏中更好吗
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- 初始化具有非默认构造函数的std::数组项的更好方法
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 为什么新的随机库比std::rand()更好
- 寻找一种更好的方法来表示无符号字符数组
- 哪种方法更好,性能明智
- 什么更好?返回对象指针列表?或返回指向对象列表的指针?
- 什么是更好的做法?通过指针或标识符传递类成员?
- 寻求更好地理解标准::访问
- 线程消息传递或更好:在"大师班"中访问其他班级的成员
- 有没有更好的方法来处理异常? try-catch块真的很丑
- 如何更好地检查两个 char 变量是否在一组值中?
- 有没有更好的方法对C++中的三个整数进行排序?
- 什么模板用法在阶乘中更好
- 平面缓冲区可以利用向量中的 0 吗?还是其他小波比哈尔变换更好?
- 我们应该如何使用枚举类进行索引(或者我们应该更好地避免这种情况)?
- Protobuf中重复字段的问题.使用重复字段进行序列化/反序列化的更好方法是什么?
- 代码比较:就效率而言,哪种代码更好用?
- "-ftrapv"和"-fwrapv":哪个效率更好?