Search code examples
fortranmpihpc

Why does MPI_REDUCE returns a syntax error at compile time?


I haven't coded in Fortran since my college days in the late 70's (and that was with punch cards!), but now I am trying to learn how to use MPI with the language. I am getting a syntax error in the call to MPI_REDUCE but I can't figure out why. I just know I am missing something simple.

C Test program

      program pi_reduce
      include 'mpif.h'

      double precision PI25DT
      parameter (PI25DT = 3.141592535897932384662643d0)
      double precision mypi, pi, h, sum, x, f, a
      integer n, myid, numprocs, i, ierr
      f(a) = 4.d0/(1.d0 + a*a)

      call MPI_INIT(ierr)
      call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr)
      call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)
      do
        if (myid .eq. 0) then
          print *, 'Enter the number of intervals: (0 quits) '
          read(*,*) n
        endif
        call MPI_BCAST(n, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
        if (n .le. 0) exit
        h = 1.0d0/n
        sum = 0.0d0
        do i = myid + 1, n, numprocs
          x = h * (dble(i) - 0.5d0)
          sum = sum + f(x)
        enddo
        mypi = h * sum
        call MPI_REDUCE(mypi, pi, 1, MPI_DOUBLE_PRECISION, MPI_SUM, 0, MPI_COMM_WORLD, ierr)
        if (myid .eq. 0) then
          print *, 'pi is ', pi, ' Error is', abs(pi-PI25DT)
        endif
      enddo
      call MPI_FINALIZE(ierr)
      end

Solution

  • As stated in the comments one of your lines is too long. With gfortran at least if you turn warnings up to the max (as you should if developing code) you get a more informative message

    ian@eris:~/work/stack$ mpif90 --version
    GNU Fortran (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
    Copyright (C) 2017 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    ian@eris:~/work/stack$ mpif90 -O -fcheck=all -std=f2008 -Wall -Wextra long.f 
    long.f:8:72:
    
           f(a) = 4.d0/(1.d0 + a*a)
                                                                            1
    Warning: Obsolescent feature: Statement function at (1)
    long.f:27:72:
    
             call MPI_REDUCE(mypi, pi, 1, MPI_DOUBLE_PRECISION, MPI_SUM, 0, MPI_COMM_WORLD, ierr)
                                                                            1
    Warning: Line truncated at (1) [-Wline-truncation]
    long.f:27:72:
    
             call MPI_REDUCE(mypi, pi, 1, MPI_DOUBLE_PRECISION, MPI_SUM, 0, MPI_COMM_WORLD, ierr)
                                                                            1
    Error: Syntax error in argument list at (1)
    

    I suggest you move the the "new" (i.e. available for 30 years) free format which is more flexible than the archaic punch card based form. In fact in general it would be a great opportunity to learn modern, safer practices than what you used all those years ago (I am guessing from what you say we are of a very similar vintage). Here's a somewhat modernised version of your code

    ian@eris:~/work/stack$ cat long.f90
    program pi_reduce
    
      Use, Intrinsic :: iso_fortran_env, Only :  wp => real64
      ! Even better Use mpi_f08
      Use            :: mpi, Only : mpi_init, mpi_comm_rank, mpi_comm_size, mpi_reduce, &
           MPI_INTEGER, MPI_DOUBLE_PRECISION, MPI_COMM_WORLD, MPI_SUM
    
      Implicit None
      
      Real( wp ), Parameter :: PI25DT = 3.141592535897932384662643_wp
    
      Real( wp ) :: mypi, pi, h, sum, x
      integer    :: n, myid, numprocs, i, ierr
    
      call MPI_INIT(ierr)
      call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr)
      call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)
      do
         if (myid == 0) then
            print *, 'Enter the number of intervals: (0 quits) '
            read(*,*) n
         endif
         call MPI_BCAST(n, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
         if (n .le. 0) exit
         h = 1.0_wp/n
         sum = 0.0_wp
         do i = myid + 1, n, numprocs
            x = h * ( Real( i , wp ) - 0.5_wp)
            sum = sum + f(x)
         enddo
         mypi = h * sum
         call MPI_REDUCE(mypi, pi, 1, MPI_DOUBLE_PRECISION, MPI_SUM, 0, MPI_COMM_WORLD, ierr)
         if (myid .eq. 0) then
            print *, 'pi is ', pi, ' Error is', abs(pi-PI25DT)
         endif
      enddo
      call MPI_FINALIZE(ierr)
    
    Contains
    
      Pure Function f( a ) 
    
        Use, Intrinsic :: iso_fortran_env, Only :  wp => real64
    
        Implicit None
    
        Real( wp ) :: f
    
        Real( wp ), Intent( In ) :: a
    
        f = 4.0_wp / ( 1.0_wp + a * a )
        
      End Function f
      
    end program pi_reduce
    ian@eris:~/work/stack$ mpif90 --version
    GNU Fortran (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
    Copyright (C) 2017 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    ian@eris:~/work/stack$ mpif90 -O -fcheck=all -std=f2008 -Wall -Wextra long.f90
    ian@eris:~/work/stack$ mpirun -np 8 ./a.out
     Enter the number of intervals: (0 quits) 
    345435
     pi is    3.1415926535904788       Error is   1.1769254637528093E-007
     Enter the number of intervals: (0 quits) 
    0
    ian@eris:~/work/stack$