我有以下功能:
template <typename Float, std::enable_if_t<std::is_floating_point_v<Float>, int> = 0>
constexpr Float inf2nan(Float x)
{
static_assert(std::numeric_limits<Float>::is_iec559);
return x * 0 + x;
}
如果输入为无穷大,则此函数将返回NaN
,否则仅返回输入。不幸的是,在GCC中使用-ffast-math
标志可以将其优化为一个ret
语句。我希望我的函数在启用这些标志的情况下也这样做。
我也试着把它替换为:
return std::isinf(x) ? std::numeric_limits<Float>::quit_NaN() : x;
但是GCC和clang并没有将其优化为与我的原始函数相同的输出。
有没有一种方法(通过注解或宏)可以为单个变量或类似于Java的strictfp
关键字的函数使用GCC和clang启用严格的浮点运算?或者,我可以检测到我的代码中启用了快速数学,并有条件地编译后一个版本吗?
2条答案
按热度按时间bkhjykvo1#
一种方法是将所有函数定义放置到编译单元(.cpp文件)中,并使用自己的设置编译该编译单元。这样你就不需要依赖编译器相关的源设置。
如何做到这一点取决于你的工具链。在CMake中,您可以创建一个
OBJECT
库,并将该OBJECT
库与您的可执行文件链接。在一个make文件中,它也应该是直接的。对于源代码中的gcc特定解决方案,有:
9rnv2umw2#
现在大多数编译器都知道,在快速数学下,你不能用fma()做疯狂的事情,因为它破坏了算法。所以它会让那些人独处。也就是说,使用fma的人这样做是有原因的,在这种情况下,这是为了精确,而不是你可能听说过的速度。所以,你可以给予这个尝试:
请注意,fma在英特尔处理器上会很慢,除非您已打开Haswell和启用Haswell新指令功能集/AVX 2的后续优化。它在GPU,powerpc,arm 64上会很快,而且可能是一个比将函数移到另一个编译单元并关闭必要的链接优化更快的解决方案。
此外,作为一个内部棒球,-fast-math的起源是您可以为SPEC打开的单个编译器标志。它包括12种讨厌的,如-funsafe-优化。因此,除非你真的认为你的应用程序,你的生计是基于应该船舶与胸部重击作弊优化打算为SPEC身体部位测量比赛,它可能是最好的离开。最好看看-ffast-math在哪里有帮助,看看你是否能找出原因并解决这个问题,这样就不再需要这个标志了。
也就是说,如果你在GPU上工作,那里的文化是不同的。英夫?南?谁在乎?都是像素!而且,摆在你面前的硬件不一定是你将要运行的硬件、驱动程序或公司,所以为什么要测试呢?FUnsafe对大家来说显然是“好玩”+“安全”!个/秒