为什么优化标志 (-O3) 不能加速四倍精度计算?
Why optimization flag (-O3) doesn't speed up quadruple precision calculations?
我有一个用 C++ 编写的 high-precision ODE(常微分方程)求解器。我用 user-defined 类型 real_type
进行所有计算。在 header:
中有一个声明此类型的 typedef
typedef long double real_type;
我决定将 long double 类型更改为 __float128
以获得更高的准确性。除此之外,我还包括 quadmath.h
并将所有标准数学函数替换为 libquadmath.
如果 "long double" 版本是在没有任何优化标志的情况下构建的,一些参考 ODE 在 77 秒内求解。如果此版本是使用 -O3 标志构建的,则可以在 25 秒内解决相同的 ODE。因此-O3标志加速了三倍的计算。
但是在“__float 128”版本中构建的类似 ODE 在 190 秒内解决了类似的 ODE 标志,在 160 秒内解决了 -O3(~ 15% 差异)。为什么 -O3 优化对四倍精度计算的影响如此微弱?也许我应该使用其他编译器标志或包含其他库?
相同的优化提供了基本相同的好处。百分比下降只是因为数学本身花费了更长的时间。
要相信优化应该是相同的百分比,您必须相信让数学花费更长的时间会以某种方式使优化器找到更多的节省空间。为什么会这样想?
如果您的目标是 x86 架构,那么在 GCC 中 __float128
是一个实际的四倍精度 FP 类型,而 long double
是 x87 96 位 FP 类型(双扩展)。
具有较小精度类型的数学可以比具有较大精度类型的数学更快,这是合理的。使用本机硬件类型的数学运算比使用非本机类型的数学运算更快也是合理的。
编译器优化是这样工作的:编译器识别代码中的某些模式,并用等效但更快的版本替换它们。在不知道您的代码究竟是什么样子以及编译器执行了哪些优化的情况下,我们无法说出编译器缺少什么。
很可能编译器知道如何对本机浮点类型及其操作执行一些优化,但它不知道如何对 __float128 和操作的库实现执行。它可能无法识别这些操作的本质。也许它无法查看库实现(您应该尝试将库与您的程序一起编译并启用 link 时间优化)。
我有一个用 C++ 编写的 high-precision ODE(常微分方程)求解器。我用 user-defined 类型 real_type
进行所有计算。在 header:
typedef long double real_type;
我决定将 long double 类型更改为 __float128
以获得更高的准确性。除此之外,我还包括 quadmath.h
并将所有标准数学函数替换为 libquadmath.
如果 "long double" 版本是在没有任何优化标志的情况下构建的,一些参考 ODE 在 77 秒内求解。如果此版本是使用 -O3 标志构建的,则可以在 25 秒内解决相同的 ODE。因此-O3标志加速了三倍的计算。
但是在“__float 128”版本中构建的类似 ODE 在 190 秒内解决了类似的 ODE 标志,在 160 秒内解决了 -O3(~ 15% 差异)。为什么 -O3 优化对四倍精度计算的影响如此微弱?也许我应该使用其他编译器标志或包含其他库?
相同的优化提供了基本相同的好处。百分比下降只是因为数学本身花费了更长的时间。
要相信优化应该是相同的百分比,您必须相信让数学花费更长的时间会以某种方式使优化器找到更多的节省空间。为什么会这样想?
如果您的目标是 x86 架构,那么在 GCC 中 __float128
是一个实际的四倍精度 FP 类型,而 long double
是 x87 96 位 FP 类型(双扩展)。
具有较小精度类型的数学可以比具有较大精度类型的数学更快,这是合理的。使用本机硬件类型的数学运算比使用非本机类型的数学运算更快也是合理的。
编译器优化是这样工作的:编译器识别代码中的某些模式,并用等效但更快的版本替换它们。在不知道您的代码究竟是什么样子以及编译器执行了哪些优化的情况下,我们无法说出编译器缺少什么。
很可能编译器知道如何对本机浮点类型及其操作执行一些优化,但它不知道如何对 __float128 和操作的库实现执行。它可能无法识别这些操作的本质。也许它无法查看库实现(您应该尝试将库与您的程序一起编译并启用 link 时间优化)。