【发布时间】:2016-11-04 06:08:45
【问题描述】:
我正在尝试 IPC 的各种方法来执行以下操作:
- Master 启动。
- Master 启动一个 Slave。
- Master 将一个数组传递给 Slave。
- Slave 处理数组。
- 从设备将阵列发回给主设备。
我已经尝试使用 OpenMPI 来解决这个问题,方法是让父进程生成一个子进程,然后由子进程执行上述处理。但是,我也尝试过 - 我认为这是最糟糕的方法 - 让 master 将数据写入文件并让 slave 读取和写入该文件。 结果令人惊叹。
以下是我实现这一目标的两种方式。第一种方式是“文件”方式,第二种方式是使用OpenMPI。
Master.f90
program master
implicit none
integer*4, dimension (10000) :: matrix
integer :: length, i, exitstatus, cmdstatus
logical :: waistatus
! put integers in matrix and output data into a file
open(1, file='matrixdata.dat', status='new')
length = 10000
do i=1,length
matrix(i) = i
write(1,*) matrix(i)
end do
close(1)
call execute_command_line("./slave.out", wait = .true., exitstat=exitstatus)
if(exitstatus .eq. 0) then
! open and read the file changed by subroutine slave
open(1, file= 'matrixdata.dat', status='old')
do i = 1, length
read(1,*) matrix(i)
end do
close(1)
endif
end program master
Slave.f90
program slave
implicit none
integer*4, dimension (10000) :: matrix
integer :: length, i
! Open and read the file made by master into a matrix
open (1, file= 'matrixdata.dat', status = 'old')
length = 10000
do i = 1, length
read(1,*) matrix(i)
end do
close(1)
! Square all numbers and write over the file with new data
open(1, file= 'matrixdata.dat', status = 'old')
do i=1,length
matrix(i) = matrix(i)**2
write(1,*) matrix(i)
end do
close(1)
end program slave
* OpenMPI *
Master.f90
program master
use mpi
implicit none
integer :: ierr, num_procs, my_id, intercomm, i, siz, array(10000000), s_tag, s_dest, siffra
CALL MPI_INIT(ierr)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, my_id, ierr)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD, num_procs, ierr)
siz = 10000
!print *, "S.Rank =", my_id
!print *, "S.Size =", num_procs
if (.not. (ierr .eq. 0)) then
print*, "S.Unable to initilaize bös!"
stop
endif
do i=1,size(array)
array(i) = 2
enddo
if (my_id .eq. 0) then
call MPI_Comm_spawn("./slave.out", MPI_ARGV_NULL, 1, MPI_INFO_NULL, my_id, &
& MPI_COMM_WORLD, intercomm, MPI_ERRCODES_IGNORE, ierr)
s_dest = 0 !rank of destination (integer)
s_tag = 1 !message tag (integer)
call MPI_Send(array(1), siz, MPI_INTEGER, s_dest, s_tag, intercomm, ierr)
call MPI_Recv(array(1), siz, MPI_INTEGER, s_dest, s_tag, intercomm, MPI_STATUS_IGNORE, ierr)
!do i=1,10
! print *, "S.Array(",i,"): ", array(i)
!enddo
endif
call MPI_Finalize(ierr)
end program master
Slave.f90
program name
use mpi
implicit none
! type declaration statements
integer :: ierr, parent, my_id, n_procs, i, siz, array(10000000), ctag, csource, intercomm, siffra
logical :: flag
siz = 10000
! executable statements
call MPI_Init(ierr)
call MPI_Initialized(flag, ierr)
call MPI_Comm_get_parent(parent, ierr)
call MPI_Comm_rank(MPI_COMM_WORLD, my_id, ierr)
call MPI_Comm_size(MPI_COMM_WORLD, n_procs, ierr)
csource = 0 !rank of source
ctag = 1 !message tag
call MPI_Recv(array(1), siz, MPI_INTEGER, csource, ctag, parent, MPI_STATUS_IGNORE, ierr)
!do i=1,10
! print *, "C.Array(",i,"): ", array(i)
!enddo
do i=1,size(array)
array(i) = array(i)**2
enddo
!do i=1,10
! print *, "C.Array(",i,"): ", array(i)
!enddo
call MPI_Send(array(1), siz, MPI_INTEGER, csource, ctag, parent, ierr)
call MPI_Finalize(ierr)
end program name
现在,有趣的是,通过使用time 程序,我测得执行“程序的文件版本”需要 19.8 毫秒。 OpenMPI 版本需要 60 毫秒。为什么?如果您使用
我尝试将数组增加到 10^5 个整数。文件版本在 114 毫秒内执行,OpenMPI 在 53 毫秒内执行。当增加到 10^6 整数文件时:1103 ms,OpenMPI:77ms。
开销真的那么大吗?
【问题讨论】:
-
您的 MPI 时间为 60 毫秒。然后,您增加数组大小和 MPI 时间减少到 53 毫秒!?这些数组大小太小,无法使用
time命令准确测量。当我这样做时,我将计时/基准嵌入代码本身并在前后使用clock_gettime(CLOCK_REALTIME,...),重复运行大约 10 次,并使用最短的时间来解决启动问题、时间片问题。 -
在您的
open语句中使用newunit说明符以避免严重的冲突。在大型程序中手动设置连接的文件单元极易出错且难以维护。
标签: performance fortran ipc openmpi