Variable scoping with NVIDIA Fortran compiler on CPU code (NVHPCSDK)

In making my code support GPU offloading by means of OpenACC, I ran into the following problem when using the NVIDIA Fortran compiler: https://gitlab.mpcdf.mpg.de/rwr/bspline_feec/-/snippets/201. Note that the problem itself completely unrelated to GPU offloading.

I think the code speaks for itself, but in words: I’m calling a function my_fun, which itself is passed as a procedure to a function my_wrapper, within a contained function wrapper_wrapper. The function my_fun depends on a real-valued variable defined in the main program. It seems that when using the NVIDIA compiler the variable is not available inside this double wrapper. It is available inside the singly wrapped function. Similarly, when I define the variable as a parameter (and thus a compile-time constant), it also works as expected.

I’ve tested this on my own PC using GNU, on remote gitlab runners using GNU, Intel, and my observations are that on GNU and Intel everything works as expected, but with the NVIDIA compiler it doesn’t.

Any ideas? Is this a compiler bug?

1 Like
> nagfor test_wrap.f90 && ./a.out
NAG Fortran Compiler Release 7.2(Shin-Urayasu) Build 7203
[NAG Fortran Compiler normal termination]
 Via wrapper (should equal .5):    0.5000000
 Direct call (should equal .5):    0.5000000
$ gfortran -pedantic test_wrap.f90 && ./a.out
 Via wrapper (should equal .5):   0.500000000
 Direct call (should equal .5):   0.500000000
$ flang -pedantic test_wrap.f90
$ flang -pedantic test_wrap.f90 && ./a.out
Segmentation fault: 11

Interesting! So it seems NVIDIA is not the only one where this type of indirection can’t be used. I’ve noticed that moving the variable into a module fixes the problem with the NVIDIA compiler:

module my_data
  implicit none
  real :: target_value
end module my_data

program example
  use my_module

  ! Storing the value in a module variable works on GCC and on NVHPC, even if the variable is not explicitly imported in my_fun
  use my_data

  target_value = 0.5

end program example

I think this is the same feature that the “Man or Boy” test contains (see Man or boy test - Rosetta Code). The PGI-based front-ends do not handle this case.

1 Like

Indeed, it seems related. The NVIDIA compiler is not a ‘man’ according to Knuth’s test.

The applicable concept in the Fortran Standard to look for is “host instance”.

Thank you for giving the relevant context!

On the topic of nvfortran bugs, this code gives a runtime error:

program nvfortran_maxloc_bug
  implicit none
  
  real :: A(5, 5)
  real :: norms(5)
  integer :: max_col
  
  A = 1.
  norms = 0.
  norms(1) = norm2(A(:, 1)) ! big problem
  ! norms(1) = sum(A(:, 1)) ! no problem
  
  max_col = maxloc(norms, 1)
  print *, "Found max_col =", max_col

end program nvfortran_maxloc_bug

resulting in

nvfortran nvfortran_maxloc_bug.f90 && ./a.out
0: fetch_int: non-integer type

which is quite worrisome