Detecting NaN inside CUDA Fortran Kernel

  • the subject basically says everything. How can I detect NaN in a kernel? CUDA appears to have a library function[1], but I can’t figure out how to access it.
(my_value .NE. my_value)

returns False also for NaN value, so that approach doesn’t seem to work.

Some background on this: I may have found a bug that would lead to an unspecified launch failure if and only if an array is passed in after a NaN is being passed by value. I want to include some safety check for NaNs in the debug mode of my kernel code generator, such that these kinds of errors can be found quickly.

http://developer.download.nvidia.com/compute/cuda/4_1/rel/toolkit/docs/online/group__CUDA__MATH__DOUBLE_gf9a5caca44978ea06bfcd2345032e5b8.html[/code]

Hi MuellerM,

You can call CUDA C routines by adding an interface. Here’s an example of calling “isnan”. The only difficulty is determining what the CUDA C name is. In this case I had to go look through the CUDA C header files since “isnan” gets preprocessed to the particular routine depending upon data type.

Hope this helps,
Mat

% cat test.cuf

module bar
use cudafor
use iso_c_binding
real(8), dimension(:), allocatable, device :: Xd
real(8), dimension(:), allocatable         :: X

interface
   attributes(device) function isnan(a) bind(C,name="__isnand")
      use iso_c_binding
      integer(c_int) :: isnan
      real(c_double), value :: a
   end function isnan
end interface

contains

attributes(global) subroutine setnan (val)
  use iso_c_binding
  real(8),value :: val
  integer :: idx
  integer(c_int) :: nan
  idx = (blockidx%x-1)*blockdim%x + threadidx%x
  nan = isnan(val)
  Xd(idx) = dble(nan)
end subroutine
end module bar

program foo
use cudafor
use bar
real(8) val
val=sqrt(-1.0)
print *, "VAL=", val
allocate(X(1),Xd(1))
call setnan<<<1,1>>>(val)
X=Xd
print *, "ISNAN? ", X

val=sqrt(10.0)
print *, "VAL=", val
call setnan<<<1,1>>>(val)
X=Xd
print *, "ISNAN? ", X
end program foo
% pgf90 test.cuf; a.out
 VAL=                       NaN
 ISNAN?     1.000000000000000
 VAL=    3.162277698516846
 ISNAN?     0.000000000000000

Great, thanks a lot for your time!

What if I want to use isnan function in C inside an Openacc kernel? I tried with isnan function from math.h but it is not recognized. So how can i solve it?

Hi jcastro9999,

We have an open feature request (TPR#21342) for isnan, as well as isfinite, isinf, isnormal, etc., but haven’t added this support to the compiler. I’ll add your request to this TPR and see about increasing the priority.

-Mat

Thanks Mat!