Merged internal comments for FND_OWNER methods.

psblas-3.6-maint
Salvatore Filippone 5 years ago
parent 5d6a380664
commit 3368b44174

@ -30,21 +30,28 @@
! !
! !
! !
! File: psi_fnd_owner.f90 ! File: psb_fnd_owner.f90
! !
! Subroutine: psi_fnd_owner ! Subroutine: psb_fnd_owner
! Figure out who owns global indices. ! Figure out who owns global indices.
! !
! Arguments: ! Arguments:
! nv - integer Number of indices required on the calling
! process
! idx(:) - integer Required indices on the calling process. ! idx(:) - integer Required indices on the calling process.
! Note: the indices should be unique! ! Note: the indices should be unique!
! iprc(:) - integer(psb_ipk_), allocatable Output: process identifiers for the corresponding ! iprc(:) - integer(psb_ipk_), allocatable Output: process identifiers for the corresponding
! indices ! indices
! desc_a - type(psb_desc_type). The communication descriptor. ! idxmap - class(psb_indx_map). The index map
! info - integer. return code. ! info - integer. return code.
! !
! This is the default implementation of the FND_OWNER method.
! If a particular index map class has additional information, it can override it
! (see e.g. the GEN_BLOCK_MAP class).
!
! 1. Check if IDXM%PARTS is available, and use it; or
! 2. Check if TEMPVG(:) is allocated, and use it; or
! 3. Call the general method PSI_GRAPH_FND_OWNER.
!
!
subroutine psb_indx_map_fnd_owner(idx,iprc,idxmap,info) subroutine psb_indx_map_fnd_owner(idx,iprc,idxmap,info)
use psb_serial_mod use psb_serial_mod
use psb_const_mod use psb_const_mod

@ -29,22 +29,24 @@
! POSSIBILITY OF SUCH DAMAGE. ! POSSIBILITY OF SUCH DAMAGE.
! !
! !
! File: psi_a2a_fnd_owner.f90
! !
! File: psi_fnd_owner.f90 ! Subroutine: psi_a2a_fnd_owner
!
! Subroutine: psi_fnd_owner
! Figure out who owns global indices. ! Figure out who owns global indices.
! !
! Arguments: ! Arguments:
! nv - integer Number of indices required on the calling
! process
! idx(:) - integer Required indices on the calling process. ! idx(:) - integer Required indices on the calling process.
! Note: the indices should be unique! ! Note: the indices should be unique!
! iprc(:) - integer(psb_ipk_), allocatable Output: process identifiers for the corresponding ! iprc(:) - integer(psb_ipk_), allocatable Output: process identifiers for the corresponding
! indices ! indices
! desc_a - type(psb_desc_type). The communication descriptor. ! idxmap - class(psb_indx_map). The index map
! info - integer. return code. ! info - integer. return code.
! !
! This version does not assume any prior knowledge about the process topology,
! so it goes for an all-to-all by building an auxiliary neighbours list and
! reusing the neighbour version.
!
!
subroutine psi_a2a_fnd_owner(idx,iprc,idxmap,info) subroutine psi_a2a_fnd_owner(idx,iprc,idxmap,info)
use psb_serial_mod use psb_serial_mod
use psb_const_mod use psb_const_mod

@ -30,12 +30,28 @@
! !
! !
! !
! File: psi_fnd_owner.f90
! !
! Subroutine: psi_fnd_owner ! File: psi_adjcncy_fnd_owner.f90
!
! Subroutine: psi_adjcncy_fnd_owner
! Figure out who owns global indices. ! Figure out who owns global indices.
! !
! Arguments: ! Arguments:
! idx(:) - integer Required indices on the calling process.
! Note: the indices should be unique!
! iprc(:) - integer(psb_ipk_), allocatable Output: process identifiers for the corresponding
! indices
! adj(:) - integer(psb_ipk_) Input: list of topological neighbours for current process.
!
! idxmap - class(psb_indx_map). The index map
! info - integer. return code.
!
! This version takes on input a list of processes that are assumed to
! be topological neighbours of the current one. Each process will send to all
! of its neighbours the list of indices for which it is trying to find the
! owner, prepare its own answers, and collect answers from others.
! There are three possibile implementations: using mpi_alltoallv, using mpi_isend/irecv,
! using psb_snd/psb_rcv. The default is mpi_alltoallv.
! !
subroutine psi_adjcncy_fnd_owner(idx,iprc,adj,idxmap,info) subroutine psi_adjcncy_fnd_owner(idx,iprc,adj,idxmap,info)
use psb_serial_mod use psb_serial_mod
@ -69,8 +85,10 @@ subroutine psi_adjcncy_fnd_owner(idx,iprc,adj,idxmap,info)
& last_ih, last_j, nidx, nrecv, nadj & last_ih, last_j, nidx, nrecv, nadj
integer(psb_ipk_) :: mglob, ih integer(psb_ipk_) :: mglob, ih
integer(psb_ipk_) :: ictxt,np,me integer(psb_ipk_) :: ictxt,np,me
logical, parameter :: gettime=.false., new_impl=.true. logical, parameter :: gettime=.false., debug=.false.
logical, parameter :: a2av_impl=.true., debug=.false. logical, parameter :: a2av_impl=.true.
logical, parameter :: mpi_irecv_impl=.false.
logical, parameter :: psb_rcv_impl=.false.
real(psb_dpk_) :: t0, t1, t2, t3, t4, tamx, tidx real(psb_dpk_) :: t0, t1, t2, t3, t4, tamx, tidx
character(len=20) :: name character(len=20) :: name
@ -175,6 +193,10 @@ subroutine psi_adjcncy_fnd_owner(idx,iprc,adj,idxmap,info)
call mpi_alltoallv(tproc,rvsz,rvidx,psb_mpi_ipk_integer,& call mpi_alltoallv(tproc,rvsz,rvidx,psb_mpi_ipk_integer,&
& lclidx,sdsz,sdidx,psb_mpi_ipk_integer,icomm,iret) & lclidx,sdsz,sdidx,psb_mpi_ipk_integer,icomm,iret)
!
! Because IPRC has been initialized to -1, the MAX operation selects
! the answers.
!
do i=0, np-1 do i=0, np-1
if (sdsz(i)>0) then if (sdsz(i)>0) then
! Must be nidx == sdsz(i) ! Must be nidx == sdsz(i)
@ -183,195 +205,197 @@ subroutine psi_adjcncy_fnd_owner(idx,iprc,adj,idxmap,info)
end do end do
if (debug) write(0,*) me,' End of adjcncy_fnd ',iprc(1:nidx) if (debug) write(0,*) me,' End of adjcncy_fnd ',iprc(1:nidx)
else else if (mpi_irecv_impl) then
if (new_impl) then !
! ! First simple minded version with auxiliary arrays
! First simple minded version with auxiliary arrays ! dimensioned on NP.
! dimensioned on NP. ! Could it be improved with a loop based on the maximum length
! Could it be improved with a loop based on the maximum length ! of adj(:) ???
! of adj(:) ??? !
! Allocate(hidx(0:np),hsz(np),sdsz(0:np-1),rvsz(0:np-1),&
Allocate(hidx(0:np),hsz(np),sdsz(0:np-1),rvsz(0:np-1),& & sdhd(0:np-1), rvhd(0:np-1), p2pstat(mpi_status_size,0:np-1),&
& sdhd(0:np-1), rvhd(0:np-1), p2pstat(mpi_status_size,0:np-1),& & stat=info)
& stat=info) sdhd(:) = mpi_request_null
sdhd(:) = mpi_request_null rvhd(:) = mpi_request_null
rvhd(:) = mpi_request_null !
! ! First, send sizes according to adjcncy list
! First, send sizes according to adjcncy list !
! sdsz = 0
sdsz = 0 do j=1, nadj
do j=1, nadj sdsz(adj(j)) = nidx
sdsz(adj(j)) = nidx end do
end do !write(0,*)me,' Check on sizes into a2a:',adj(:),nadj,':',sdsz(:)
!write(0,*)me,' Check on sizes into a2a:',adj(:),nadj,':',sdsz(:)
call mpi_alltoall(sdsz,1,psb_mpi_def_integer,&
call mpi_alltoall(sdsz,1,psb_mpi_def_integer,& & rvsz,1,psb_mpi_def_integer,icomm,minfo)
& rvsz,1,psb_mpi_def_integer,icomm,minfo) hidx(0) = 0
hidx(0) = 0 do i=0, np-1
do i=0, np-1 hidx(i+1) = hidx(i) + rvsz(i)
hidx(i+1) = hidx(i) + rvsz(i) end do
end do hsize = hidx(np)
hsize = hidx(np) ! write(0,*)me,' Check on sizes from a2a:',hsize,rvsz(:)
! write(0,*)me,' Check on sizes from a2a:',hsize,rvsz(:) !
! ! Second, allocate buffers and exchange data
! Second, allocate buffers and exchange data !
! Allocate(rmtidx(hsize),lclidx(max(hsize,nidx*nadj)),tproc(max(hsize,nidx)),stat=info)
Allocate(rmtidx(hsize),lclidx(max(hsize,nidx*nadj)),tproc(max(hsize,nidx)),stat=info)
if (info /= psb_success_) then
if (info /= psb_success_) then call psb_errpush(psb_err_from_subroutine_,name,a_err='Allocate')
call psb_errpush(psb_err_from_subroutine_,name,a_err='Allocate') goto 9999
goto 9999 end if
do i = 0, np-1
if (rvsz(i)>0) then
! write(0,*) me, ' First receive from ',i,rvsz(i)
call psb_get_rank(prc,ictxt,i)
p2ptag = psb_int_swap_tag
!write(0,*) me, ' Posting first receive from ',i,rvsz(i),prc
call mpi_irecv(rmtidx(hidx(i)+1),rvsz(i),&
& psb_mpi_ipk_integer,prc,&
& p2ptag, icomm,rvhd(i),iret)
end if end if
do i = 0, np-1 end do
if (rvsz(i)>0) then do j=1, nadj
! write(0,*) me, ' First receive from ',i,rvsz(i) if (nidx > 0) then
call psb_get_rank(prc,ictxt,i) !call psb_snd(ictxt,idx(1:nidx),adj(j))
p2ptag = psb_int_swap_tag call psb_get_rank(prc ,ictxt,adj(j))
!write(0,*) me, ' Posting first receive from ',i,rvsz(i),prc p2ptag = psb_int_swap_tag
call mpi_irecv(rmtidx(hidx(i)+1),rvsz(i),& !write(0,*) me, ' First send to ',adj(j),nidx, prc
& psb_mpi_ipk_integer,prc,& call mpi_send(idx,nidx,&
& p2ptag, icomm,rvhd(i),iret) & psb_mpi_ipk_integer,prc,&
end if & p2ptag, icomm,iret)
end do end if
do j=1, nadj end do
if (nidx > 0) then
!call psb_snd(ictxt,idx(1:nidx),adj(j))
call psb_get_rank(prc ,ictxt,adj(j))
p2ptag = psb_int_swap_tag
!write(0,*) me, ' First send to ',adj(j),nidx, prc
call mpi_send(idx,nidx,&
& psb_mpi_ipk_integer,prc,&
& p2ptag, icomm,iret)
end if
end do
!!$ do i = 0, np-1 !!$ do i = 0, np-1
!!$ if (rvsz(i)>0) then !!$ if (rvsz(i)>0) then
!!$ ! write(0,*) me, ' First receive from ',i,rvsz(i) !!$ ! write(0,*) me, ' First receive from ',i,rvsz(i)
!!$ call psb_rcv(ictxt,rmtidx(hidx(i)+1:hidx(i)+rvsz(i)),i) !!$ call psb_rcv(ictxt,rmtidx(hidx(i)+1:hidx(i)+rvsz(i)),i)
!!$ end if !!$ end if
!!$ end do !!$ end do
call mpi_waitall(np,rvhd,p2pstat,iret) call mpi_waitall(np,rvhd,p2pstat,iret)
! !
! Third, compute local answers ! Third, compute local answers
! !
call idxmap%g2l(rmtidx(1:hsize),lclidx(1:hsize),info,owned=.true.) call idxmap%g2l(rmtidx(1:hsize),lclidx(1:hsize),info,owned=.true.)
do i=1, hsize do i=1, hsize
tproc(i) = -1 tproc(i) = -1
if ((0 < lclidx(i)).and. (lclidx(i) <= n_row)) tproc(i) = me if ((0 < lclidx(i)).and. (lclidx(i) <= n_row)) tproc(i) = me
end do end do
! !
! At this point we can reuse lclidx to receive messages ! At this point we can reuse lclidx to receive messages
! !
rvhd(:) = mpi_request_null rvhd(:) = mpi_request_null
do j=1, nadj do j=1, nadj
!write(0,*) me, ' First send to ',adj(j),nidx !write(0,*) me, ' First send to ',adj(j),nidx
if (nidx > 0) then if (nidx > 0) then
!call psb_snd(ictxt,idx(1:nidx),adj(j)) !call psb_snd(ictxt,idx(1:nidx),adj(j))
call psb_get_rank(prc,ictxt,adj(j)) call psb_get_rank(prc,ictxt,adj(j))
p2ptag = psb_int_swap_tag p2ptag = psb_int_swap_tag
!write(0,*) me, ' Posting second receive from ',adj(j),nidx, prc !write(0,*) me, ' Posting second receive from ',adj(j),nidx, prc
call mpi_irecv(lclidx((j-1)*nidx+1),nidx, & call mpi_irecv(lclidx((j-1)*nidx+1),nidx, &
& psb_mpi_ipk_integer,prc,& & psb_mpi_ipk_integer,prc,&
& p2ptag, icomm,rvhd(j),iret) & p2ptag, icomm,rvhd(j),iret)
end if end if
end do end do
! !
! Fourth, send data back; ! Fourth, send data back;
! !
do i = 0, np-1 do i = 0, np-1
if (rvsz(i)>0) then if (rvsz(i)>0) then
!call psb_snd(ictxt,tproc(hidx(i)+1:hidx(i)+rvsz(i)),i) !call psb_snd(ictxt,tproc(hidx(i)+1:hidx(i)+rvsz(i)),i)
call psb_get_rank(prc,ictxt,i) call psb_get_rank(prc,ictxt,i)
p2ptag = psb_int_swap_tag p2ptag = psb_int_swap_tag
!write(0,*) me, ' Second send to ',i,rvsz(i), prc !write(0,*) me, ' Second send to ',i,rvsz(i), prc
call mpi_send(tproc(hidx(i)+1),rvsz(i),& call mpi_send(tproc(hidx(i)+1),rvsz(i),&
& psb_mpi_ipk_integer,prc,& & psb_mpi_ipk_integer,prc,&
& p2ptag, icomm,iret) & p2ptag, icomm,iret)
end if
end do
!
! Fifth: receive and combine. MAX works because default
! answer is -1.
!
call mpi_waitall(np,rvhd,p2pstat,iret)
do j = 1, nadj
!write(0,*) me, ' Second receive from ',adj(j), nidx
!if (nidx > 0) call psb_rcv(ictxt,tproc(1:nidx),adj(j))
iprc(1:nidx) = max(iprc(1:nidx), lclidx((j-1)*nidx+1:(j-1)*nidx+nidx))
end do
if (debug) write(0,*) me,' End of adjcncy_fnd ',iprc(1:nidx)
else
Allocate(hidx(0:np),hsz(np),&
& sdsz(0:np-1),rvsz(0:np-1),stat=info)
!
! First, send sizes according to adjcncy list
!
sdsz = 0
do j=1, nadj
sdsz(adj(j)) = nidx
end do
!write(0,*)me,' Check on sizes into a2a:',adj(:),nadj,':',sdsz(:)
call mpi_alltoall(sdsz,1,psb_mpi_def_integer,&
& rvsz,1,psb_mpi_def_integer,icomm,minfo)
hidx(0) = 0
do i=0, np-1
hidx(i+1) = hidx(i) + rvsz(i)
end do
hsize = hidx(np)
! write(0,*)me,' Check on sizes from a2a:',hsize,rvsz(:)
!
! Second, allocate buffers and exchange data
!
Allocate(rmtidx(hsize),lclidx(hsize),tproc(max(hsize,nidx)),stat=info)
if (info /= psb_success_) then
call psb_errpush(psb_err_from_subroutine_,name,a_err='Allocate')
goto 9999
end if end if
do j=1, nadj end do
!write(0,*) me, ' First send to ',adj(j),nidx !
if (nidx > 0) call psb_snd(ictxt,idx(1:nidx),adj(j)) ! Fifth: receive and combine. MAX works because default
end do ! answer is -1.
do i = 0, np-1 !
if (rvsz(i)>0) then call mpi_waitall(np,rvhd,p2pstat,iret)
! write(0,*) me, ' First receive from ',i,rvsz(i) do j = 1, nadj
call psb_rcv(ictxt,rmtidx(hidx(i)+1:hidx(i)+rvsz(i)),i) !write(0,*) me, ' Second receive from ',adj(j), nidx
end if !if (nidx > 0) call psb_rcv(ictxt,tproc(1:nidx),adj(j))
end do iprc(1:nidx) = max(iprc(1:nidx), lclidx((j-1)*nidx+1:(j-1)*nidx+nidx))
end do
! if (debug) write(0,*) me,' End of adjcncy_fnd ',iprc(1:nidx)
! Third, compute local answers
! else if (psb_rcv_impl) then
call idxmap%g2l(rmtidx(1:hsize),lclidx(1:hsize),info,owned=.true.)
do i=1, hsize Allocate(hidx(0:np),hsz(np),&
tproc(i) = -1 & sdsz(0:np-1),rvsz(0:np-1),stat=info)
if ((0 < lclidx(i)).and. (lclidx(i) <= n_row)) tproc(i) = me !
end do ! First, send sizes according to adjcncy list
!
! sdsz = 0
! Fourth, send data back; do j=1, nadj
! sdsz(adj(j)) = nidx
do i = 0, np-1 end do
if (rvsz(i)>0) then !write(0,*)me,' Check on sizes into a2a:',adj(:),nadj,':',sdsz(:)
!write(0,*) me, ' Second send to ',i,rvsz(i)
call psb_snd(ictxt,tproc(hidx(i)+1:hidx(i)+rvsz(i)),i) call mpi_alltoall(sdsz,1,psb_mpi_def_integer,&
end if & rvsz,1,psb_mpi_def_integer,icomm,minfo)
end do hidx(0) = 0
! do i=0, np-1
! Fifth: receive and combine. MAX works because default hidx(i+1) = hidx(i) + rvsz(i)
! answer is -1. Reuse tproc end do
! hsize = hidx(np)
do j = 1, nadj ! write(0,*)me,' Check on sizes from a2a:',hsize,rvsz(:)
!write(0,*) me, ' Second receive from ',adj(j), nidx !
if (nidx > 0) call psb_rcv(ictxt,tproc(1:nidx),adj(j)) ! Second, allocate buffers and exchange data
iprc(1:nidx) = max(iprc(1:nidx), tproc(1:nidx)) !
end do Allocate(rmtidx(hsize),lclidx(hsize),tproc(max(hsize,nidx)),stat=info)
if (info /= psb_success_) then
call psb_errpush(psb_err_from_subroutine_,name,a_err='Allocate')
goto 9999
end if end if
do j=1, nadj
!write(0,*) me, ' First send to ',adj(j),nidx
if (nidx > 0) call psb_snd(ictxt,idx(1:nidx),adj(j))
end do
do i = 0, np-1
if (rvsz(i)>0) then
! write(0,*) me, ' First receive from ',i,rvsz(i)
call psb_rcv(ictxt,rmtidx(hidx(i)+1:hidx(i)+rvsz(i)),i)
end if
end do
!
! Third, compute local answers
!
call idxmap%g2l(rmtidx(1:hsize),lclidx(1:hsize),info,owned=.true.)
do i=1, hsize
tproc(i) = -1
if ((0 < lclidx(i)).and. (lclidx(i) <= n_row)) tproc(i) = me
end do
!
! Fourth, send data back;
!
do i = 0, np-1
if (rvsz(i)>0) then
!write(0,*) me, ' Second send to ',i,rvsz(i)
call psb_snd(ictxt,tproc(hidx(i)+1:hidx(i)+rvsz(i)),i)
end if
end do
!
! Fifth: receive and combine. MAX works because default
! answer is -1. Reuse tproc
!
do j = 1, nadj
!write(0,*) me, ' Second receive from ',adj(j), nidx
if (nidx > 0) call psb_rcv(ictxt,tproc(1:nidx),adj(j))
iprc(1:nidx) = max(iprc(1:nidx), tproc(1:nidx))
end do
else
info = psb_err_internal_error_
call psb_errpush(info,name,a_err='invalid exchange alg choice')
goto 9999
end if end if
call psb_erractionrestore(err_act) call psb_erractionrestore(err_act)

Loading…
Cancel
Save