浮点代码的 g++ 优化开关

Posted

技术标签:

【中文标题】浮点代码的 g++ 优化开关【英文标题】:g++ optimization switches for floating point code 【发布时间】:2017-12-27 22:24:04 【问题描述】:

我正在尝试让一些代码运行得更快。它是浮点密集型代码——作为输入:

参数(常量、双精度、整数) 输入值数组(常量、双精度)

输出是

值数组(双精度) 雅可比矩阵

目前我正在使用

g++-7 (Ubuntu 7.2.0-1ubuntu1~16.04) 7.2.0

和下面的命令行:

g++-7 -S -fPIC -O3 -DNDEBUG -funroll-loops -march=native -ffast-math \
-I $BOOST_DIR tmp.cpp -std=c++17 \
-D__forceinline='__attribute__((always_inline))' \
-frecord-gcc-switches -Wno-attributes

根据我的记忆,G++ 编译器在过去生成了更好的代码——而且对这些代码的咀嚼时间也更长。我尝试过使用各种选项,但只有

--param max-gcse-memory=1

似乎有任何效果——在使用或不使用这个参数之间。忽略参数值的变化。

我对更好代码的标准是与 vmul[sp]d 指令相比,代码中 vmov/mov 指令的数量。更好的代码应该包含更少的 [v]mov 指令。

使用时

--param max-gcse-memory=1

与没有此参数的 11325 相比,我得到 10766 [v]mov 指令。 这与 1000 vmulpd 和 1900 vmulsd 相比——两次尝试之间的数字或多或少是恒定的。

再次——我不介意编译时间。我想获得更好的代码,并且根据我在过去(2010 年)的记忆,我得到了更好的代码,包括更长的编译时间。

【问题讨论】:

您不能尝试安装旧版本并进行比较吗?还有,原生架构不变吗? 在这个级别,计算 mov 与 mul 是一种非常粗略的启发式方法,您需要比较代表性数据的运行时间。 【参考方案1】:

SIMD 指令通常需要对齐的数据。听起来 GCC 正在生成大量代码来防止数据对齐不足。

如果您可以修改代码,听起来您将受益于 aligned 属性的一些使用,或者更好的是 OpenMP SIMD pragma。

根据您的程序的结构,LTO (-flto) 可能会产生很大的影响,限制函数可见性(即 -fvisibility=hidden)也可以。

基本上,您希望为优化器提供尽可能多的工作空间,以便它可以删除大量额外的代码,以便为 SIMD 指令正确对齐。

您可能还想考虑启用更多 ISA 扩展... AVX 支持 256 位向量,这意味着您可以使用一条指令完成两倍的工作,而且您的 CPU 很有可能支持它。如果您要交付可执行文件以在其他计算机上运行,​​请考虑使用 target_clones 属性,以便轻松生成针对多个 ISA 扩展进行优化的代码。

【讨论】:

OP 正在使用-march=native,它启用了您的 CPU 支持的所有功能,如果您在天空湖上,则设置 -mtune=skylake 或其他。不过,LTO 是一个很好的建议,如果没有它,您无法让 gcc 自动矢量化一些重要的循环,OpenMP 会很有帮助(例如,__restrict 的使用不足,或者如果使用 OpenMP 做得更好. 啊,你说得对;我错过了 -march=native。 OpenMP 还允许您指定对齐方式,这就是我在这里讨论的上下文。根据他所说的说明,听起来 GCC 正在对代码进行矢量化,它也做了很多准备工作;在这种情况下,让编译器知道东西是对齐的并让它更积极地优化(LTO + 可见性)应该有很长的路要走。 是的,gcc 的 vanilla 自动矢量化策略是完全展开的标量 intros/outros 以到达内部循环中的一个指针的对齐边界(但内部循环根本没有展开) .对于宽向量(尤其是窄整数类型),这是很多代码膨胀。有关查看编译器输出的提示,请参阅 ***.com/questions/38552116/…,TL:DR:将其放在 gcc.godbolt.org。

以上是关于浮点代码的 g++ 优化开关的主要内容,如果未能解决你的问题,请参考以下文章

当我在 Linux 上运行使用硬浮点选项构建的 Neon 代码时出现分段错误

允许这种浮点优化吗?

是否允许编译器优化浮点常量乘法

哪些优化编译器开关使调试变得非常困难?

在编译时比较类型的大小

浮点数据有损压缩算法 附完整C代码