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

时间:2022-07-23 09:11:23

I would like to compile a program with gfortran and -O3 -ffast-math enabled, since it gives a nice performance boost. I was rather confused, that gfortran's isnan() catched some NaN's but not all of them. After reading

我想用gfortran和-O3 - ffastmath来编译一个程序,因为它可以提高性能。我很困惑,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?

检查双(或浮点)是否为NaN在c++中如何使便携式isnan/isinf函数为负NaN不是NaN?

I am under the impression that people are able to check for NaN's in C via bit-fiddling even with fast-math enabled. However, this puzzles me since fast-math

我的印象是,即使是在快速数学的帮助下,人们也可以通过bit-fiddling来检查NaN的C语言。然而,这让我困惑,因为快速数学。

can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions.

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

According to the man page of gcc 4.7.2. So how do you know which bit to check, if the numbers are not represented according to IEEE standard? And if you know it, how would you implement it in Fortran 95/03/08?

根据gcc 4.7.2的手册页。那么,如果这些数字没有按照IEEE标准来表示,你怎么知道要检查哪位呢?如果你知道,你怎么用Fortran 95/03/08来实现它呢?

Don't bother to post (x \= x) or simlar solutions which depend on IEEE rules. They give the same result as isnan(). I am also aware of -ffpe-trap=invalid,zero,overflow, but don't want to stop the program. If it helps, my OS is 64-bit LinuxMint 14. If it is not possible in Fortran, a waterproof C solution would also be nice.

不必费心去发布(x \= x)或依赖于IEEE规则的simlar解决方案。它们给出的结果与isnan()相同。我也知道- ffpetrap =无效,零,溢出,但不想停止程序。如果有帮助的话,我的操作系统是64位的LinuxMint 14。如果用Fortran语言是不可能的,那么防水C的解决方案也不错。

2 个解决方案

#1


3  

First I would point out that gfortran 4.9 supports the IEEE_arithmetic module. However, I cannot depend on gfortran 4.9, it is too fresh.

首先,我要指出gfortran 4.9支持ieee_算术模块。然而,我不能指望gfortran 4.9,它太新鲜了。

What I actually use in practice is to move the check x/=x to a procedure which is compiled without -ffast-math and without link time optimizations:

实际上,我在实践中使用的是将检查x/=x移动到一个没有- ffastmath计算的过程中,并且没有链接时间优化:

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

It is in a separate file, which is then compiled without -Ofast, --ffast-math and without -flto. Beware the lack of inlining can case serious performance decrease.

它是在一个单独的文件中,然后在没有-Ofast的情况下编译,—ffast-math和没有-flto。要注意的是,缺少内衬可能会导致严重的性能下降。

#2


1  

I was facing the same problem in gfortran-4.7 and started to experiment with some expressions. For my Test Cases this one returned true if x is a NaN:

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

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

I've checked only double precision values and -O2 -ffast-math, -O3 -ffast-math options. Note that this returns .false. if using no optimization flags, thus you would have to combine it with

我只检查了双精度值和-O2 -ffast-math, -O3 -ffast-math选项。注意,这个返回。false。如果没有使用优化标志,那么您将不得不将其与。

isnan(x) .OR. check

#1


3  

First I would point out that gfortran 4.9 supports the IEEE_arithmetic module. However, I cannot depend on gfortran 4.9, it is too fresh.

首先,我要指出gfortran 4.9支持ieee_算术模块。然而,我不能指望gfortran 4.9,它太新鲜了。

What I actually use in practice is to move the check x/=x to a procedure which is compiled without -ffast-math and without link time optimizations:

实际上,我在实践中使用的是将检查x/=x移动到一个没有- ffastmath计算的过程中,并且没有链接时间优化:

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

It is in a separate file, which is then compiled without -Ofast, --ffast-math and without -flto. Beware the lack of inlining can case serious performance decrease.

它是在一个单独的文件中,然后在没有-Ofast的情况下编译,—ffast-math和没有-flto。要注意的是,缺少内衬可能会导致严重的性能下降。

#2


1  

I was facing the same problem in gfortran-4.7 and started to experiment with some expressions. For my Test Cases this one returned true if x is a NaN:

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

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

I've checked only double precision values and -O2 -ffast-math, -O3 -ffast-math options. Note that this returns .false. if using no optimization flags, thus you would have to combine it with

我只检查了双精度值和-O2 -ffast-math, -O3 -ffast-math选项。注意,这个返回。false。如果没有使用优化标志,那么您将不得不将其与。

isnan(x) .OR. check