NAG 7.1 and the `mpi_f08` module
The latest NAG 7.1 compiler finally includes the F2018 features needed to support the build of the mpi_f08 module, but I ran into an issue when compiling MPICH 4.0.1. I used GNU C/C++, but NAG for the Fortran compiler. It compiled without error, but I ran into a missing symbol when linking a Fortran code against the MPI libraries. The problem was that the MPICH build was picking up the ISO_Fortran_binding.h header file from GNU/gfortran, and not the version for the NAG Fortran compiler. I "fixed" things by adding CFLAGS=-I/path/to/nag/include/dir when configuring the MPICH build. This feels like a heavy-handed solution, but does appear so far to have worked with no unintended side effects. Is that the best solution to the problem? I'd also suggest that introducing a configure option that gives the path to the directory containing the ISO_Fortran_binding.h header file might be a good idea.
I think setting CFLAGS is an okay solution. The only effect is to have the header files in the specified folder to take priority, and that is the exact intention no matter what solution we choose. We potentially can add the exact CFLAGS internally when we are configuring with nagfor. But that will depend on heuristics in guessing/probing where the nag include path is.
Thanks for your affirmation about CFLAGS @hzhou . I think it would be ill-advised to have mpich try and guess where the nag include path is; much better to just have the user specify it explicitly. This case with NAG may merit a special comment in the installation instructions, though, as it isn't at all obvious at first that the C code supporting mpi_f08 relies on a header file from the Fortran vendor -- seemingly not an issue when the C and Fortran vendors are the same.
Yeah, if the C and Fortran compilers are from the same vendor, it will be easy for the vendor to make sure the inter-op works.
Adding some instructions in README is a good idea. We'll do that.
I think it would be ill-advised to have mpich try and guess where the nag include path is; much better to just have the user specify it explicitly.
Ideally, NAG should provide some standard query interface for this. I would say this is their responsibility. Short of that, all other solutions are "workarounds".
Ideally, NAG should provide some standard query interface for this. I would say this is their responsibility. Short of that, all other solutions are "workarounds".
Well actually, this is possible in an indirect, round-about way (but I'm not suggesting this is something mpich should necessarily do -- it still seems fragile). In working out this issue with someone at NAG, they pointed out to me that you can actually feed C code to the compiler which it passes on to gcc, and the -# flag shows exactly what it does:
$ nagfor -# -c dummy.c
NAG Fortran Compiler Release 7.1(Hanzomon) Build 7105
/usr/bin/gcc -I/opt/nag/nagfor-7.1/lib -c -w -funsigned-char -DINT64=long -DOBJECT_SIZE_64 -mcmodel=medium -fsignaling-nans -frounding-math -m64 -o dummy.o dummy.c
That second command line token will be exactly the include option that C needs, regardless of where/how the NAG compiler is installed.
Keep this issue open until
- either README is updated and configure issues warning for the user
- or configure add nag include path when nagfor is used.
Hello, I provide tech support for the NAG Fortran Compiler at NAG. With a recent nagfor executable in the PATH, the following configure command has been tested on an x64/Linux system with mpich-4.0.1, when run in a directory that has the same parent as the mpich-4.0.1 directory. It helps when you use directory names without spaces for nagfor installation.
../mpich-4.0.1/configure --with-device=ch3 --prefix=/opt/mpich-hanzomon FC=nagfor CC=gcc CFLAGS=$(nagfor -# foo.c 2>&1 |grep -o -e '\-I[^ ]*') FFLAGS="-f2018 -mismatch" FCFLAGS="-f2018 -mismatch" --enable-f08
@ThemosTsikas Thanks for chiming in. Is $(nagfor -# foo.c 2>&1 |grep -o -e '\-I[^ ]*') the best way to grab standard include path? We can add it to our configure logic to provide some convenience to users. It would be cleaner if nagfor can spit out the path without dummy source and grep, but we can work with that for now.
A comment about the configure line @ThemosTsikas showed. The -f2018 gets rid of the otherwise harmless "extension" warning messages. However that flag somehow leaks into the generated compiler wrappers (but -mismatch doesn't) and the end result for a mixed language C/Fortran mixed language CMake project is that -f2018 winds up in CFLAGS which obviously breaks things as it's an unknown option to the C compiler (here gcc). I had to drop the -f2018 to get things working again. I haven't dug into how this all happens yet.
User provided FCFLAGS is supposed to be included in the wrapper scripts (mpifort). I am not sure why -mismatch got dropped. I would say the CMake logic is broken as they shouldn't grab mpifort flags into CFLAGS.
If your application uses mpi_f08, you probably don't need -mismatch flags. With current main branch and the next major release, I believe you won't need that flag for legacy Fortran applications either.
@ThemosTsikas Thanks for chiming in. Is
$(nagfor -# foo.c 2>&1 |grep -o -e '\-I[^ ]*')the best way to grab standard include path? We can add it to our configure logic to provide some convenience to users. It would be cleaner ifnagforcan spit out the path without dummy source andgrep, but we can work with that for now.
We are thinking through simpler alternatives.
Although I tried providing MPICHLIB_FCFLAGS and MPICHLIB_FFLAGS (to "-f2018 -mismatch"), configure fails telling me I also need FFLAGS set. Is that a feature or a bug?
Although I tried providing MPICHLIB_FCFLAGS and MPICHLIB_FFLAGS (to "-f2018 -mismatch"), configure fails telling me I also need FFLAGS set. Is that a feature or a bug?
It is a side effect of testsuite configure requiring FFLAGS. This will be fixed in the next major release.
Although I tried providing MPICHLIB_FCFLAGS and MPICHLIB_FFLAGS (to "-f2018 -mismatch"), configure fails telling me I also need FFLAGS set. Is that a feature or a bug?
It is a side effect of testsuite configure requiring
FFLAGS. This will be fixed in the next major release.
Also the -mismatch flag is for mpif90 wrappers to be able to compile Fortran applications. MPICHLIB_FCFLAGS will not be included in the wrapper scripts.
I am not sure you want to include "-mismatch" in the installed mpif90 & scripts. Standard-compliant Fortran programs will lose some of the checking abilities of the NAG Compiler if that option is passed silently.
I am not sure you want to include "-mismatch" in the installed mpif90 & scripts. Standard-compliant Fortran programs will lose some of the checking abilities of the NAG Compiler if that option is passed silently.
We understand that. The next major release should allow users to omit that. But currently, without that flag, users will not be able compile their MPI programs if, for example, they call MPI_Send(buf, ...) with different data types. MPICH does not really need the -mismatch flag to build. But users need that to bypass the compiler type check for those MPI routines. In the next release, we will add the the "IGNORE TKR" pragama in the routine interface.
The NAG Compiler ignores IGNORE_TKR pragma.
The NAG Compiler ignores IGNORE_TKR pragma.
That is unfortunate. That means we have to put -mismatch in mpif90 wrapper or most users won't be able to compile their Fortran MPI code.
A better solution might be to include the option -wmismatch=MPI_xxx,MPI_yyy,MPI_zzz which suppresses consistency checking for the specified procedures.
A better solution might be to include the option -wmismatch=MPI_xxx,MPI_yyy,MPI_zzz which suppresses consistency checking for the specified procedures.
So NAG is able to do per-routine ignore-mismatch! All we need is to specify that in code or in module interface. Doing that for hundreds of MPI functions on the command line switch is not practical.
The "-indirect
The "-indirect " option will read options from the named file, so you can collect all of the MPI_xxx routines in a file and use that, keeping the command line relatively clean.
I see. How can we do that neatly in the wrapper script -- mpif90?
First, you construct a file with the contents
-wmismatch=MPI_SEND,MPI_BCAST,MPI_RECV,MPI_ALLREDUCE,... and you save it in the installation directory (share subdirectory, perhaps, or bin). Then, you modify the Fortran compiler command line in the mpif90 script to include "-indirect $prefix/filename" in the options passed to the compiler. You can repeat the -wmismatch=
option to add more names.
Okay, we'll give it a try.