什么时候我可以放心地用-O3编译程序?

2023-12-03

我见过很多人抱怨-O3 option:

  • GCC:程序无法使用编译选项-O3
  • 浮点问题由 David Hammen 提供

我查看了 GCC 的手册:

   -O3    Optimize yet more.  -O3 turns on all optimizations
          specified   by   -O2   and   also   turns  on  the
          -finline-functions and -frename-registers options.

我还确认了代码,以确保两个选项是其中包含的唯一两个优化-O3 on:

if (optimize >= 3){
    flag_inline_functions = 1;
    flag_rename_registers = 1;
}

对于这两个优化:

  • -finline-functions在某些情况下(主要是 C++)很有用,因为它允许我们使用 -finline-limit 定义内联函数的大小(默认为 600)。设置高内联限制时,编译器可能会报告内存不足的错误。
  • -frename-registers尝试通过使用寄存器分配后剩余的寄存器来避免调度代码中的错误依赖关系。这种优化最有利于具有大量寄存器的处理器。

对于内联函数来说,虽然可以减少函数调用次数,但是可能会导致二进制文件很大,所以-finline-functions可能会引入严重的缓存惩罚并且变得比 -O2 更慢。我认为缓存惩罚不仅取决于程序本身。

对于重命名寄存器,我认为它不会对 x86 这样的 cisc 架构产生任何积极影响。

我的问题有 2.5 个部分:

  1. 我是否可以声称使用 -O3 选项程序是否可以运行得更快取决于底层平台/架构? [已回答]

    EDIT:

    第 1 部分已被确认为真实的。 David Hammen 还声称,我们应该非常小心优化和浮点运算如何在具有扩展精度浮点寄存器(如 Intel 和 AMD)的机器上交互。

  2. 什么时候才能放心使用-O3 option?我认为这两个优化尤其是重命名寄存器可能会导致与 -O0/O2 不同的行为。我看到一些程序编译为-O3在执行过程中崩溃了,它是确定性的吗?如果我运行一个可执行文件一次而没有任何崩溃,这是否意味着它可以安全使用-O3?

    编辑:确定性与优化无关,它是一个多线程问题。但是对于多线程程序来说,使用起来并不安全-O3当我们运行一次可执行文件而没有错误时。大卫·哈曼表明-O3浮点运算的优化可能违反比较的严格弱排序标准。我们在使用的时候还有什么需要注意的地方吗?-O3 option?

  3. 如果第一个问题的答案是“是”,那么当我更改目标平台或在具有不同机器的分布式系统中时,我可能需要在-O3 and -O2。有没有通用的方法来决定我是否可以获得性能改进-O3?比如更多的寄存器、短的内联函数等。【已解答】

    编辑:第三部分已被 Louen 回答为“平台的多样性使得对这个问题的一般推理变得不可能”在评估性能增益时-O3,我们必须同时尝试两者并对我们的代码进行基准测试,看看哪个更快。


  1. 我看到一些程序在使用 -O3 编译时崩溃了,它是确定性的吗?

如果程序是单线程的,则程序使用的所有算法都是确定性的,并且如果运行之间的输入相同,则可以。如果其中任何一个条件不成立,答案是“不一定”。

如果您在不使用 -O3 的情况下进行编译,则同样适用。

如果我运行一次可执行文件而没有任何崩溃,是否意味着使用 -O3 是安全的?

当然不是。同样,如果您在不使用 -O3 的情况下进行编译,则同样适用。仅仅因为您的应用程序运行一次并不意味着它在所有情况下都会成功运行。这就是测试成为难题的部分原因。


在浮点寄存器比双精度精度更高的机器上,浮点运算可能会导致奇怪的行为。例如,

void add (double a, double b, double & result) {
   double temp = a + b;
   result = temp;
   if (result != temp) {
      throw FunkyAdditionError (temp);
   }
}

编译一个使用它的程序add功能未优化,您可能永远不会看到任何FunkyAdditionError例外情况。编译优化和某些输入将突然开始导致这些异常。问题是,通过优化,编译器将使temp注册同时result,作为参考,不会被编译到寄存器中。添加一个inline限定符和当你的编译器编译时这些异常可能会消失-O3因为现在result也可以是一个寄存器。浮点运算的优化可能是一个棘手的话题。

最后,让我们看一下其中一个案例,当使用 -O3 编译程序时,晚上事情确实发生了碰撞,GCC:程序无法使用编译选项 -O3。该问题仅出现在 -O3 中,因为编译器可能内联了distance函数,但将其中一个(但不是两个)结果保留在扩展精度浮点寄存器中。通过此优化,某些点p1 and p2可以导致两者p1<p2 and p2<p1评价为true。这违反了比较函数的严格弱排序标准。

您需要非常小心优化和浮点操作如何在具有扩展精度浮点寄存器的机器(例如 Intel 和 AMD)上交互。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么时候我可以放心地用-O3编译程序? 的相关文章

  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • c# Asp.NET MVC 使用FileStreamResult下载excel文件

    我需要构建一个方法 它将接收模型 从中构建excel 构建和接收部分完成没有问题 然后使用内存流导出 让用户下载它 不将其保存在服务器上 我是 ASP NET 和 MVC 的新手 所以我找到了指南并将其构建为教程项目 public File
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 使用 LINQ 查找列表中特定类型的第一个元素

    使用 LINQ 和 C 在元素列表中查找特定类型的第一个项目的最短表示法是什么 var first yourCollection OfType
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr

随机推荐