我正在尝试在Fortran中学习一些MPI,但我遇到了一些问题。这个ping pong程序在SEGFAULT HERE的两条评论之间发生了段落,但对于我的生活,我无法理解为什么会这样。
program MPI_PING_PONG
implicit none
include 'mpif.h'
integer rank, size, ierror, tag, status(MPI_STATUS_SIZE)
integer ping_pong_counter ! This will increment each time a message is received.
integer isEven
integer partner_rank
call MPI_INIT(ierror) ! Initialize MPI on all processes.
call MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierror) ! Tell each process the size of the world.
call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierror) ! Tell each process its rank.
ping_pong_counter = 0
partner_rank = mod(rank + 1,2)
print *,'Process has rank ',rank
do
if (ping_pong_counter == 50) then
exit
endif
isEven = mod(ping_pong_counter,2)
if (rank == isEven) then
ping_pong_counter = ping_pong_counter + 1
print *,'Process ',rank,'sending counter value of ',ping_pong_counter
call MPI_SEND(ping_pong_counter,1,MPI_INTEGER,partner_rank,5,MPI_COMM_WORLD,ierror)
else
!******************** SEGFAULT HERE ********************!
call MPI_RECV(ping_pong_counter,1,MPI_INTEGER,partner_rank,5,MPI_COMM_WORLD,ierror)
!******************** SEGFAULT HERE ********************!
print *,'Process ',rank,' has received a counter with value ',ping_pong_counter
endif
enddo
end program MPI_PING_PONG
这是下面的输出:
Process has rank 0
Process 0 sending counter value of 1
Process has rank 1
Program received signal SIGSEGV: Segmentation Fault - invalid memory reference
Backtrace for this error:
#0: 0x7F49425F2117
#1: 0x7F49425F26F4
#2: 0x7F49425F20AF
#3: 0x7F49425F22C7
#4: 0X400DDF in mpi_ping_pong at MPI_PING_PONG.f90:28
答案 0 :(得分:2)
您缺少status
参数。 MPI_Recv
的正确签名是
MPI_RECV(BUF, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
<type> BUF(*)
INTEGER COUNT, DATATYPE, SOURCE, TAG, COMM
INTEGER STATUS(MPI_STATUS_SIZE), IERROR
您的参数数量错误。
答案 1 :(得分:1)
通常属于堆栈空间的地址的回溯存在暗示缺少非可选子例程或函数参数。
不应在现代Fortran程序中使用mpif.h
接口,而应使用mpi
模块接口(USE mpi
)。使用MPI-3.0实现时,应使用mpi_f08
接口。 mpi
模块接口为许多函数提供参数检查,并且在编译程序期间将捕获传递错误数量的参数。不幸的是MPI_RECV
是一个接受不同类型参数(缓冲区)的函数,因此经常从mpi
模块接口中省略,因为2008版之前的Fortran不允许具有不同类型参数的接口声明。一些MPI实现通过使用缓冲区参数的可能类型的长列表来解决此限制。这同样适用于其他通信呼叫,例如,到MPI_SEND
。
在理想的世界中,我们都将拥有MPI-3.0兼容的实现和实现TR 29113的Fortran 2008编译器。mpi_f08
模块接口利用了使用不同类型和形状的参数声明子例程接口的能力。编译器能够在编译时轻松检查所有参数。