【问题标题】:Why does MPI_REDUCE returns a syntax error at compile time? [duplicate]为什么 MPI_REDUCE 在编译时返回语法错误? [复制]
【发布时间】:2021-04-28 23:06:03
【问题描述】:

自从我 70 年代后期的大学时代以来,我就没有使用 Fortran 编码(那是使用打孔卡!),但现在我正在尝试学习如何将 MPI 与该语言一起使用。我在调用 MPI_REDUCE 时遇到语法错误,但我不知道为什么。我只知道我错过了一些简单的东西。

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

【问题讨论】:

  • 首先,您应该将“旧版”include 'mpif.h' 替换为 use mpi,紧随其后的是 implicit none。如果这没有指出错误,请使用新代码和完整的错误消息更新您的问题。
  • 仔细检查违规行不超过允许的长度(例如,固定格式源文件中的 72 列)
  • @GillesGouaillardet include 'mpif.h' 和使用 mpi 没有区别。隐含的也没有,但 72 字符截断是正确的。奇怪的是,使用 & 继续下一行的其余部分也会引发错误。我想我会放弃这个 Fortran 的东西并使用更现代的语言,比如 C 或 Python。
  • 您是否(也)在第 6 列添加了续行符?无论如何,不​​要把婴儿和洗澡水一起扔出去。 Fortran 90 及更高版本就是您所需要的(将您的 .F 文件重命名为 .f90,更改第一行(注释),您应该会很好。

标签: fortran mpi hpc


【解决方案1】:

正如 cmets 中所述,您的其中一条线太长了。至少使用 gfortran,如果您将警告调到最大(开发代码时应该这样做),您会得到更多信息

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)

我建议您移动“新”(即可用 30 年)免费格式,它比基于古老打孔卡的形式更灵活。事实上,总的来说,这将是一个学习现代、比你多年前使用的更安全的做法的好机会(我从你所说的猜测我们是一个非常相似的年份)。这是您的代码的现代化版本

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$ 

【讨论】:

  • 谢谢,这只是一个示例,来自 MIT Press. 的“使用 MPI”教科书 v3,图 3.2。我想我买错书了,应该使用 C 或 Python。
  • 那是 1994 年出版的,这就是它显示它年龄的原因。对于高性能数值工作 IMO Fortran,特别是如果您使用 Fortran 2003 或更高版本,仍然是非常可行的方法,当然 C 没有我能看到的优势。 Python 可以更轻松地完成任务,但不要期望相同的性能。
  • 我的目标是学习使用 MPI,而不是高性能数值工作。 C 没有像 F90 那样过时的 my-way-or-the-highway 声明规则和缺乏向后兼容性,而 Python 是其他工作(如生物信息学)的首选语言。一旦我了解了 MPI 的工作原理,如果客户需要,我可能会回到 Fortran。谢谢!
猜你喜欢
  • 1970-01-01
  • 2017-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-28
  • 2019-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多