是否有可能使isnan()在gfortran -O3 -ffast-math中工作?

时间:2013-04-11 08:59:27

标签: optimization fortran nan ieee-754 gfortran

我想用gfortran和-O3 -ffast-math编译一个程序,因为它提供了很好的性能提升。我很困惑,gfortran的isnan()抓住了一些NaN,但不是全部。看完之后

Checking if a double (or float) is NaN in C++
how do I make a portable isnan/isinf function
Negative NaN is not a NaN?

我的印象是,即使启用了快速数学运算,人们也可以通过比特摆弄来检查C中的NaN。然而,自从快速数学以来,这让我很困惑

  

可能导致依赖于确切实现的程序的输出不正确   数学函数的IEEE或ISO规则/规范。

根据gcc 4.7.2的手册页。那么,如果根据IEEE标准没有表示数字,您如何知道要检查哪个位?如果你知道,你将如何在Fortran 95/03/08中实现它?

不要费心发布依赖于IEEE规则的(x \= x)或类似解决方案。它们给出与isnan()相同的结果。我也知道-ffpe-trap=invalid,zero,overflow,但不想停止该计划。如果它有帮助,我的操作系统是64位LinuxMint 14.如果在Fortran中不可能,防水C解决方案也会很好。

2 个答案:

答案 0 :(得分:3)

首先我要指出gfortran 4.9支持IEEE_arithmetic模块。但是,我不能依赖gfortran 4.9,它太新鲜了。

我在实践中实际使用的是将检查x/=x移动到没有-ffast-math编译且没有链接时优化的过程:

module ieee_arithmetic
  !poor man's replacement for the intrinsic module
  !do not use if the compiler supports the F2003 version
  !make sure not to use fast math optimizations
  use iso_fortran_env

  !common extension isnan may actually fail with optimizations above
!   intrinsic isnan

  interface ieee_is_nan
    module procedure ieee_is_nan_real32
    module procedure ieee_is_nan_real64
  end interface

contains
  logical function ieee_is_nan_real32(x) result(res)
    real(real32), intent(in) :: x

    res = x /= x
  end function

  logical elemental function ieee_is_nan_real64(x) result(res)
    real(real64), intent(in) :: x

    res = x /= x
  end function

end module

它位于一个单独的文件中,然后在没有-Ofast--ffast-math-flto的情况下进行编译。当心缺乏内联可能导致严重的性能下降。

答案 1 :(得分:1)

我在gfortran-4.7中遇到了同样的问题,并开始尝试一些表达式。对于我的测试用例,如果x是NaN,则返回true:

check = ((x*2d0==x).AND.(
         (x<-epsilon(1.d0)).OR.
         (x>+epsilon(1.d0))))

我只检查了双精度值和-O2 -ffast-math,-O3 -ffast-math选项。请注意,这会返回.false。如果不使用优化标志,则必须将其与

组合
isnan(x) .OR. check