Fortran MPI_ALLGATHER错误并行化代码
我正在尝试并行化以下代码Fortran MPI_ALLGATHER错误并行化代码,fortran,mpi,Fortran,Mpi,我正在尝试并行化以下代码 subroutine log_likelihood(y, theta, lli, ll) doubleprecision, allocatable, intent(in) :: y(:) doubleprecision, intent(in) :: theta(2) doubleprecision, allocatable, intent(out) :: lli(:) doubleprecisi
subroutine log_likelihood(y, theta, lli, ll)
doubleprecision, allocatable, intent(in) :: y(:)
doubleprecision, intent(in) :: theta(2)
doubleprecision, allocatable, intent(out) :: lli(:)
doubleprecision, intent(out) :: ll
integer :: i
ALLOCATE (lli(size(y)))
lli = 0.0d0
ll = 0.0d0
do i = 1, size(y)
lli(i) = -log(sqrt(theta(2))) - 0.5*log(2.0d0*pi) &
- (1.0d0/(2.0d0*theta(2)))*((y(i)-theta(1))**2)
end do
ll = sum(lli)
end subroutine log_likelihood
为此,我尝试使用MPI_ALLGATHER。这是我写的代码
subroutine log_likelihood(y, theta, lli, ll)
doubleprecision, allocatable, intent(in) :: y(:)
doubleprecision, intent(in) :: theta(2)
doubleprecision, allocatable, intent(out) :: lli(:)
doubleprecision, intent(out) :: ll
integer :: i, size_y, diff
size_y=size(y)
ALLOCATE (lli(size_y))
!Broadcasting
call MPI_BCAST(theta, 1, MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, ierr)
call MPI_BCAST(y, 1, MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, ierr)
! Determine how many points to handle with each proc
points_per_proc = (size_y + numprocs - 1)/numprocs
! Determine start and end index for this proc's points
istart = proc_num * points_per_proc + 1
iend = min((proc_num + 1)*points_per_proc, size_y)
diff = iend-istart+1
allocate(proc_contrib(istart:iend))
do i = istart, iend
proc_contrib(i) = -log(sqrt(theta(2))) - 0.5*log(2.0d0*pi) &
- (1.0d0/(2.0d0*theta(2)))*((y(i)-theta(1))**2)
end do
call MPI_ALLGATHER(proc_contrib, diff, MPI_DOUBLE_PRECISION, &
lli, diff, MPI_DOUBLE_PRECISION, &
MPI_COMM_WORLD, ierr)
ll = sum(lli)
end subroutine log_likelihood
当我试图运行我的程序时,我得到以下错误
$ mpiexec -n 2 ./mle.X
Fatal error in PMPI_Allgather: Internal MPI error!, error stack:
PMPI_Allgather(961)......: MPI_Allgather(sbuf=0x7ff2f251b860, scount=1500000, MPI_DOUBLE_PRECISION, rbuf=0x7ff2f2ad5650, rcount=3000000, MPI_DOUBLE_PRECISION, MPI_COMM_WORLD) failed
MPIR_Allgather_impl(807).:
MPIR_Allgather(766)......:
MPIR_Allgather_intra(560):
MPIR_Localcopy(357)......: memcpy arguments alias each other, dst=0x7ff2f2ad5650 src=0x7ff2f251b860 len=12000000
===================================================================================
= BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
= EXIT CODE: 1
= CLEANING UP REMAINING PROCESSES
= YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
===================================================================================
谁能给我解释一下我做错了什么
谢谢 我终于解决了我的问题。我的代码的串行和并行版本在
您正在写入
proc\u contrib(istart:iend)
,但您已将其分配为从1:diff;等级1及以上将覆盖proc_contrib的结尾,这可能会导致问题。(还有一堆缺失的变量;numproc等)。此外,allgather尝试读取数组边界之外的内容。您可以分配(proc_contrib(istart:iend))
并更改对allgatherv的调用,等等。此外,您实际上不需要执行allgather;安会帮你算数,这就是你在这里所需要的。事实上,我建议不要修改程序,而是在外面算数。理想情况下,您不会让每个处理器“知道”所有的y(i)
s;他们会有自己的局部问题,调用log\u likelion
例程,然后全部减少部分和(或者如果log likelion是最终结果,只需要打印出来,就减少部分和)。1。缺少的变量都在该子例程之外声明为全局变量。2.我理解了我的第一个错误,我改为分配(proc_contrib(istart:iend))3。你能给我解释一下怎么修Allgather吗?我需要一个Allgather,因为在我的实际程序中,我需要lli作为输出。谢谢正如乔纳森·杜西(Jonathan Dursi)在上文中指出的那样,你的“diff”论点可能会随着等级的不同而有所不同,即最后一个论点的值可能与所有其他论点的值不同。要处理这个问题,您需要使用allgatherv例程。
subroutine log_likelihood(y, n, theta, lli, ll)
integer, intent(in) :: n
doubleprecision, intent(in) :: y(n)
doubleprecision, intent(in) :: theta(2)
doubleprecision, intent(out) :: lli(n)
doubleprecision, intent(out) :: ll
integer :: i
do i = istart, iend
proc_contrib(i-istart+1) = -log(sqrt(theta(2))) - 0.5*log(2.0d0*pi) &
- (1.0d0/(2.0d0*theta(2)))*((y(i)-theta(1))**2)
end do
if ( mod(n,numprocs)==0 ) then
call MPI_ALLGATHER(proc_contrib, points_per_proc, MPI_DOUBLE_PRECISION, &
lli, points_per_proc, MPI_DOUBLE_PRECISION, &
MPI_COMM_WORLD, ierr)
else if (numprocs-1 == proc_num ) then
recvcounts(numprocs) = iend-istart+1
call MPI_ALLGATHERV(proc_contrib, points_per_proc, MPI_DOUBLE_PRECISION, &
lli, recvcounts, displs, MPI_DOUBLE_PRECISION, &
MPI_COMM_WORLD, ierr)
end if
ll = sum(lli)
end subroutine log_likelihood