我可以让我的编译器在每个函数的基础上使用快速数学吗?

Can I make my compiler use fast-math on a per-function basis?

假设我有

template <bool UsesFastMath> void foo(float* data, size_t length);

我想编译一个带有 -ffast-math 的实例(--use-fast-math 用于 nvcc),另一个没有它的实例。

这可以通过在单独的翻译单元中实例化每个变体,并使用不同的命令行编译每个变体来实现 - 使用和不使用开关。

我的问题是是否可以向流行的编译器 (*) 指示应用或不应用 -ffast-math 单个函数 - 这样我就可以在同一个翻译单元中进行实例化。

备注:


(*) 流行的编译器我指的是以下任何一个:gcc、clang、msvc icc、nvcc(用于 GPU 内核代码),您有相关信息。

在 GCC 中,您可以声明如下函数:

__attribute__((optimize("-ffast-math")))
double
myfunc(double val)
{
    return val / 2;
}

这是 GCC 独有的功能。

在此处查看工作示例 -> https://gcc.gnu.org/ml/gcc/2009-10/msg00385.html

GCC 似乎没有验证 optimize() 参数。所以像“-ffast-match”这样的拼写错误将被默默地忽略。

从 CUDA 7.5(我熟悉的最新版本,虽然 CUDA 8.0 目前正在发货)开始,nvcc 支持允许程序员的函数属性在每个函数的基础上应用特定的编译器优化。

由于通过命令行开关设置的优化配置适用于整个编译单元,一种可能的方法是使用尽可能多的不同编译单元,因为有不同的优化配置,正如问题中已经指出的那样;可以共享源代码,并从一个公共文件 #include-ed。

对于 nvcc,命令行开关 --use_fast_math 基本上控制三个功能区域:

  • 清零模式已启用(即禁用非正规支持)
  • 单精度倒数、除法和平方根切换为近似版本
  • 某些标准数学函数被等效的低精度内在函数所取代

您可以通过使用适当的内在函数以每个操作的粒度应用这些更改中的一些,通过使用 PTX 内联汇编来应用其他更改。