MPI_GATHERV by 바죠

병렬계산에서 자주 마주치게 되는 상황 중 하나에 대해서 언급하고자 합니다.
각 노드에 할당된 특정 크기(M)의 자료들을  특정 노드(0 노드)에 모두 모으고자 할 때가 있을 수 있다.
이 때, 특정 노드(0 노드)에서는 노드수(nproc)에 비례하는 배열 할당(M * nproc)이 필요하게 된다.

이러한 기본적인 데이터의 전송 패턴에 관해서는 정리가 잘 되어 있다. MPI(Message Passing Interface) 라이버러리 속에는 이러한 일들을 하는 미리 준비된 루틴들이 있다.

MPI_gatherv가 모으는 것에 해당한다면 MPI_scatterv는 모든 노드로 뿌리는 것에 해당한다고 볼 수 있다.
사실은 노드마다 데이터 크기가 다른것들을 특정한 한 노드 배열에 담을 수 있는 기능을 루틴들은 지원한다. 하지만, 아래의 예제에서는 노드마다 정확히 같은 크기로 구성된 데이터들을 한 노드로 취합하는 것만을 예제로 다루었다.






!234567890
implicit none
include 'mpif.h'
integer, allocatable :: isend(:), irecv(:)
integer, allocatable :: ircnt(:), idisp(:)
integer ierr,nproc,myid
integer i,iscnt
integer ndsize

call MPI_INIT(ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,nproc,ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)

ndsize=10
allocate(isend(ndsize),irecv(nproc*ndsize))
allocate(ircnt(0:nproc-1),idisp(0:nproc-1))


ircnt=ndsize
idisp(0)=0
do i=1,nproc-1
idisp(i)=idisp(i-1)+ircnt(i)
enddo

do i=1,ndsize           ! node specific data with a data-size ndsize
isend(i)=myid+1
enddo

iscnt=ndsize
call MPI_GATHERV(isend, iscnt, MPI_INTEGER, irecv, ircnt, idisp, MPI_INTEGER,0, MPI_COMM_WORLD, ierr)


if(myid == 0)then
print*, 'irecv= ',irecv
endif

deallocate(ircnt,idisp)
deallocate(isend,irecv)
call MPI_FINALIZE(ierr)
stop
end



irecv= 1 1 1 1 1
1 1 1 1 1 2
2 2 2 2 2 2
2 2 2 3 3 3
3 3 3 3 3 3
3 4 4 4 4 4
4 4 4 4 4


-------------------------------------------------------------------------------

!234567890
implicit none
include 'mpif.h'
real*8, allocatable :: rsend(:), rrecv(:)
integer, allocatable :: ircnt(:), idisp(:)
integer ierr,nproc,myid
integer i,iscnt
integer ndsize

call MPI_INIT(ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,nproc,ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)

ndsize=3
allocate(rsend(ndsize),rrecv(nproc*ndsize))
allocate(ircnt(0:nproc-1),idisp(0:nproc-1))


ircnt=ndsize
idisp(0)=0
do i=1,nproc-1
idisp(i)=idisp(i-1)+ircnt(i)
enddo

do i=1,ndsize
rsend(i)=float(myid+1)
enddo

iscnt=ndsize
call MPI_GATHERV(rsend, iscnt, MPI_DOUBLE_PRECISION, rrecv, ircnt, idisp, MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, ierr)


if(myid == 0)then
print*, 'rrecv= ',rrecv
endif

deallocate(ircnt,idisp)
deallocate(rsend,rrecv)
call MPI_FINALIZE(ierr)
stop
end



rrecv= 1.000000000000000 1.000000000000000
1.000000000000000 2.000000000000000 2.000000000000000
2.000000000000000 3.000000000000000 3.000000000000000
3.000000000000000 4.000000000000000 4.000000000000000
4.000000000000000






참조:
http://incredible.egloos.com/3755171

핑백

덧글

  • 떠벌이 2010/07/21 21:43 # 삭제 답글

    processor가 5개이므로 5까지 출력되는게 맞는거죠?

    그리고 root processor말고 기타 다른 processor에서도 irecv(or rrecv) 배열이 할당되어 메모리를 잡아먹는 것이 맞는 건가요?
    (비록 데이터가 채워지지는 않더라도요)
댓글 입력 영역

최근 포토로그