AMReX-Codes/amrex

Fortran interface compilation issue with `nvhpc`

ylee88 opened this issue · 4 comments

I am getting the following errors when compiling the AMReX with nvhpc:

./configure --comp=pgi --dim=2
make -j
...
Compiling AMReX_fab_mod.F90 ...
mpif90 -O2 -fast -gopt -Mnomain -Mdclchk -noacc  -module tmp_build_dir/o/2d.pgi.MPI.EXE -Itmp_build_dir/o/2d.pgi.MPI.EXE -DBL_LANG_FORT -DAMREX_LANG_FORT -DBL_USE_MPI -DAMREX_USE_MPI -DAMREX_GPU_MAX_THREADS=0 -DBL_SPACEDIM=2 -DAMREX_SPACEDIM=2 -DBL_FORT_USE_UNDERSCORE -DAMREX_FORT_USE_UNDERSCORE -DBL_Linux -DAMREX_Linux -DAMREX_PARTICLES -DNDEBUG -DOMPI_SKIP_MPICXX -DBL_USE_F_INTERFACES -Itmp_build_dir/s/2d.pgi.MPI.EXE -I. -I/home/ylee/tmp/amrex/Src/Base -I/home/ylee/tmp/amrex/Src/Base/Parser -I/home/ylee/tmp/amrex/Src/AmrCore -I/home/ylee/tmp/amrex/Src/Amr -I/home/ylee/tmp/amrex/Src/Boundary -I/home/ylee/tmp/amrex/Src/Particle -I/home/ylee/tmp/amrex/Src/F_Interfaces/Particle -I/home/ylee/tmp/amrex/Src/F_Interfaces/Base -I/home/ylee/tmp/amrex/Src/F_Interfaces/Octree -I/home/ylee/tmp/amrex/Src/F_Interfaces/AmrCore -I/home/ylee/tmp/amrex/Src/LinearSolvers/MLMG -I/home/ylee/tmp/amrex/Src/F_Interfaces/LinearSolvers  -c /home/ylee/tmp/amrex/Src/F_Interfaces/Base/AMReX_fab_mod.F90 -o tmp_build_dir/o/2d.pgi.MPI.EXE/AMReX_fab_mod.o
NVFORTRAN-S-0038-Symbol, amrex_fab_destroy, has not been explicitly declared (/home/ylee/tmp/amrex/Src/F_Interfaces/Base/AMReX_fab_mod.F90)
  0 inform,   0 warnings,   1 severes, 0 fatal for amrex_fab_dataptr
NVFORTRAN-S-0038-Symbol, amrex_fab_destroy, has not been explicitly declared (/home/ylee/tmp/amrex/Src/F_Interfaces/Base/AMReX_fab_mod.F90)
  0 inform,   0 warnings,   1 severes, 0 fatal for amrex_fab_norminf
NVFORTRAN-F-0155-FINAL subroutine must be a module procedure with one dummy argument - amrex_fab_destroy (/home/ylee/tmp/amrex/Src/F_Interfaces/Base/AMReX_fab_mod.F90: 170)
NVFORTRAN/x86-64 Linux 24.7-0: compilation aborted
make: *** [/home/ylee/tmp/amrex/Tools/GNUMake/Make.rules:329: tmp_build_dir/o/2d.pgi.MPI.EXE/AMReX_fab_mod.o] Error 2
make: *** Waiting for unfinished jobs....

As the error message suggests, adding the following lines helps to resolve the error:

diff --git a/Src/F_Interfaces/Base/AMReX_fab_mod.F90 b/Src/F_Interfaces/Base/AMReX_fab_mod.F90
index d36e8f4ea..b76e8645e 100644
--- a/Src/F_Interfaces/Base/AMReX_fab_mod.F90
+++ b/Src/F_Interfaces/Base/AMReX_fab_mod.F90
@@ -42,6 +42,10 @@ module amrex_fab_module
      module procedure amrex_fab_build_install
   end interface amrex_fab_build
 
+  interface amrex_fab_destroy
+     module procedure amrex_fab_destroy
+  end interface amrex_fab_destroy
+
 contains
 
   ! Build a fab, allocate own memory

So forth for every final subroutines in Fortran interfaces:

❯ ag "final\s::"
Src/F_Interfaces/Base/AMReX_physbc_mod.F90
21:     final :: amrex_physbc_destroy

Src/F_Interfaces/Base/AMReX_multifab_mod.F90
95:     final :: amrex_multifab_destroy
123:     final :: amrex_imultifab_destroy
149:     final :: amrex_mfiter_destroy

Src/F_Interfaces/Base/AMReX_distromap_mod.F90
24:     final :: amrex_distromap_destroy

Src/F_Interfaces/Base/AMReX_boxarray_mod.F90
35:     final :: amrex_boxarray_destroy

Src/F_Interfaces/Base/AMReX_fab_mod.F90
36:     final :: amrex_fab_destroy

Src/F_Interfaces/Base/AMReX_geometry_mod.F90
39:     final :: amrex_geometry_destroy

Src/F_Interfaces/Particle/AMReX_particlecontainer_mod.F90
40:     final :: amrex_particlecontainer_destroy

Src/F_Interfaces/AmrCore/AMReX_fluxregister_mod.F90
30:     final :: amrex_fluxregister_destroy

Src/F_Interfaces/AmrCore/AMReX_flash_fluxregister_mod.F90
39:     final :: amrex_flash_fluxregister_destroy

Src/F_Interfaces/LinearSolvers/AMReX_poisson_mod.F90
16:     final :: amrex_poisson_destroy

Src/F_Interfaces/LinearSolvers/AMReX_abeclaplacian_mod.F90
19:     final :: amrex_abeclaplacian_destroy

Src/F_Interfaces/LinearSolvers/AMReX_multigrid_mod.F90
50:     final :: amrex_multigrid_destroy

Src/Base/AMReX_parmparse_mod.F90
55:     final :: amrex_parmparse_destroy

I'm not sure whether having an explicit interface for the final subroutine is indeed necessary or if this issue should be considered as a compiler bug for nvhpc.

nvfortran appears to be wrong. Here is a link to the Fortran standard. https://j3-fortran.org/doc/year/24/24-007.pdf There are some examples of final subroutines on page 574. They do not have an explicit interface block.

That being said, we try to work around compiler bugs as much as we can. So you are welcome to submit a PR addressing the issue.

I did a bit more experimentation, and it appears that the interface block for the final subroutine does not actually matter -- what really matters is the order of the subroutine definition appearance. For example, in the Src/F_Interfaces/Base/AMReX_fab_mod.F90, the caller for the amrex_fab_destroy appears ahead of its definition. Just changing the ordering of the subroutine definitions to be appeared ahead of its caller also resolves (or bypasses) the issue. Obviously, nvfortran is wrong.

Apparently, making a module procedure before the contains keywords forces the nvfortran to see the *_destroy subroutine definitions ahead of other subroutines, resulting in the same effects. But this is just my guess.

I am willing to make a PR for this, but I'm not sure if you prefer the interface approach or the changing subroutine ordering approach. Let me know which is preferable.

BTW, does the nvhpc test compile all the Fortran interfaces? I can't find the messages for AMReX_fab_mod.F90 in its logs

@ylee88 I prefer the interface approach. Thanks!

As for the nvhpc test, we could enable AMReX_FORTRAN_INTERFACES.

Let's see if this can catch it. #4114