虚拟进程
虚拟进程(MPI_PROC_NULL)是不存在的假想进程,在MPI中的主要作用是充当真实进程通信的目或源,引入虚拟进程的目的是为了在某些情况下编写通信语句的方便。当一个真实进程向一个虚拟进程发送数据或从一个虚拟进程接收数据时,该真实进程会立即正确返回,如同执行了一个空操作。
在很多情况下为通信指定一个虚拟的源或目标是非常方便的,这不仅可以大大简化处理边界的代码,而且使程序显得简洁易懂。在捆绑发送接收操作中经常用到这种通信手段。一个真实进程向虚拟进程MPI_PROC_NULL发送消息时会立即成功返回;一个真实进程从虚拟进程MPI_PROC_NULL的接收消息时也会立即成功返回,并且对接收缓冲区没有任何改变。

用虚拟进程和捆绑发送接收操作实现Jacobi叠代
program main
implicit none
include 'mpif.h'
integer totalsize,mysize,steps
parameter (totalsize=16)
parameter (mysize=totalsize/4,steps=10)

integer n, myid, numprocs, i, j,rc
real a(totalsize,mysize+2),b(totalsize,mysize+2)
integer begin_col,end_col,ierr
integer left,right,tag1,tag2
integer status(MPI_STATUS_SIZE)

call MPI_INIT( ierr )
call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr )
print *, "Process ", myid, " of ", numprocs, " is alive"

C 数组初始化
do j=1,mysize+2
do i=1,totalsize
a(i,j)=0.0
end do
end do
if (myid .eq. 0) then
do i=1,totalsize
a(i,2)=8.0
end do
end if
if (myid .eq. 3) then
do i=1,totalsize
a(i,mysize+1)=8.0
end do
end if
do i=1,mysize+2
a(1,i)=8.0
a(totalsize,i)=8.0
end do

tag1=3
tag2=4

C 设置当前进程左右两侧的进程标识
if (myid .gt. 0) then
left=myid-1
else
left=MPI_PROC_NULL
end if
if (myid .lt. 3) then
right=myid+1
else
right=MPI_PROC_NULL
end if

C Jacobi 迭代
do n=1,steps
C 从左向右平移数据
call MPI_SENDRECV(a(1,mysize+1),totalsize,MPI_REAL,right,tag1,
*a(1,1),totalsize,MPI_REAL,left,tag1,
*MPI_COMM_WORLD,status,ierr)

C 从右向左平移数据
call MPI_SENDRECV(a(1,2),totalsize,MPI_REAL,left,tag2,
*a(1,mysize+2),totalsize,MPI_REAL,right,tag2,
*MPI_COMM_WORLD,status,ierr)
begin_col=2
end_col=mysize+1
if (myid .eq. 0) then
begin_col=3
endif
if (myid .eq. 3) then
end_col=mysize
endif
do j=begin_col,end_col
do i=2,totalsize-1
b(i,j)=(a(i,j+1)+a(i,j-1)+a(i+1,j)+a(i-1,j))*0.25
end do
end do
do j=begin_col,end_col
do i=2,totalsize-1
a(i,j)=b(i,j)
end do
end do
end do
do i=2,totalsize-1
print *, myid,(a(i,j),j=begin_col,end_col)
end do
call MPI_Finalize(rc)
end