当前位置: 首页 > 知识库问答 >
问题:

gcc/g中各种优化级别之间的区别到底是什么?

查飞星
2023-03-14

在任何人告诉我查找旧答案或RTFM之前,请注意我已经这样做了,所以请在指示我查找其他地方之前阅读详细信息。

我已经确定,优化级别的差异并不像为更高的优化级别启用了一些不同类型的优化标志那么简单。

例如,我首先通过以下步骤发现了O0和O1的优化标志的差异:

gcc -c -Q -O1 --help=optimizers > /tmp/O1-opts
gcc -c -Q -O0 --help=optimizers > /tmp/O0-opts
diff /tmp/O0-opts /tmp/O1-opts | grep enabled

这给了我一个O1对O0启用的各种优化标志的列表。

然后,我用-O0编译了代码,但是添加了O1对O0启用的所有单独的优化标志,因为结果应该和O1一样,对吗?猜猜看,不是!

因此,这证明了优化级别之间的差异不仅仅是使用了不同类型的优化标志。我的意思是,除了gcc/g显示的优化标志外,优化中还必须有更多的差异。

如果有人已经知道这个问题的答案,请告诉我,否则我将不得不查找gcc的源代码,这对我来说不是小事。谢谢!

至于我寻找这些信息的原因,我有一些AVX-512代码,在O0或无优化标志的情况下,L1D缓存未命中率不到3%,但在O1及以上的情况下,其未命中率超过37%(尽管它加快了代码速度)。如果我能找出是哪个(隐藏)标志导致了它,我也许能进一步加快代码的速度。公共区域的旗帜太多了。gcc源代码中的opt文件,所以我遇到了麻烦。

共有1个答案

滕成双
2023-03-14

-O0是特殊的,它意味着在每个语句之间溢出/重新加载,以实现一致的调试:为什么使用-O0(对于这个简单的浮点和)时,clang会产生低效的asm?-手动添加一些优化标志时看到的情况是否与以下情况相匹配:仍然在存储/重新加载变量,有点像volatile

我猜是的,因为您确认了@bg2b关于冗余访问的猜测,并报告了L1D未命中的绝对数量在O0到O1之间没有太大变化。我现在明白了为什么这个比例似乎被夸大了。

因此,似乎没有一个单独的-f...优化选项控制-O0的特殊行为,并且您必须实际使用-O1-Og作为设置其他选项的基础。(例如-fno-...,直到您回到-O0默认的选项集。)

选项也可以在GCC带有-S-fverose-asm-o-输出的asm注释中看到。

此外,运行速度较慢(由于存储/重新加载或任何其他原因)会使硬件预取有更多的时间来保持,并在加载uop执行之前,在L2甚至L1d中准备好数据,并出现需求未命中。

 类似资料:
  • 当我编译我的项目并检查运行所使用的资源时,大CPU/内存猪有时被称为,有时被称为。两者之间有什么区别,我是否应该直接调用?

  • 发展至今(2020 年 6 月份),GCC 编译器已经更新至 10.1.0 版本,其功能也由最初仅能编译 C 语言,扩增至可以编译多种编程语言,其中就包括 C++ 。 除此之外,当下的 GCC 编译器还支持编译 Go、Objective-C,Objective-C ++,Fortran,Ada,D 和 BRIG(HSAIL)等程序,甚至于 GCC 6 以及之前的版本还支持编译 Java 程序。但本

  • 问题内容: 我从各种各样的消息来源(虽然大部分是我的一位同事)听说的,-O3以g ++的优化级别进行编译在某种程度上是“危险的”,除非被证明是必要的,否则通常应该避免编译。 这是真的吗?如果是这样,为什么?我应该坚持-O2吗? 问题答案: 在gcc的早期(2.8等)和egcs时代,redhat 2.96 -O3有时是相当多的错误。但这是十年前的事了,-O3与其他级别的优化(在儿童车中)没有太大不同

  • 我的客户问我使用 NFS 时是否有任何区别,如下所示: 方法 1:定义 PV,如下所示: apiVersion:v1 种类:PersistentVolume 元数据: 名称:mysqldb volume 规格: capacity: 存储:3Gi 访问模式: 1ReadWriteMany nfs: path:/var/export/dbvol 服务器:master.lab.example。com 方

  • 我从不同的渠道(尽管主要是从我的一个同事那里)听说,在G++中使用的优化级别进行编译是“危险的”,除非证明是必要的,否则通常应该避免。 这是真的吗?如果是,为什么?我应该坚持吗?

  • 问题内容: 我不太了解它们之间的区别,因此我对这两个软件包有一些疑问。 在Google上浏览了一下之后,似乎Oracle决定使用JDK7版本的更新和增强软件包来更新该软件包。 封装的性能与封装相比如何? 从到有什么大变化?(例如新方法,功能) 为什么必须对原始软件包进行更新? 如今是该软件包的代名词吗? 这并不是我想在代码中使用旧版包,我对此真的很好奇。请告诉我他们的区别? 问题答案: Java最