이 글은 점대점 통신(블로킹과 논블로킹)에 대한 이해를 바탕으로 집합 통신(Collective communication)의 예제를 다뤘다.
MPI 코드로 수치적분을 구현한 원본게시글을 따라가며 이해한 내용들을 기록한 문서이다.
포트란으로 병렬컴퓨팅 배우기 ←링크
III MPI 집합통신과 수치적분
- Numerical Integration wtih MPI Collective Communications.
MPI 집합통신 예제로 평범하고 하찮은(원본이 이렇게 소개한다.) 그리고 간단한 알고리즘인 수치적분법을 가져왔다. 부분적분을 각 프로세서에서 진행하고, 그 합을 다시 마스터 프로세서에서 수행하는 것으로 적분이 완료되는 알고리즘이다. 코드만 보고 알고리즘 이해가 어렵다면, 앞 포스트의 수치적분 개념설명(링크)을 참고하길 바란다.
위 그림과 함께 예제를 간단히 소개하겠다. P0 ~ P3 은 프로세서로써 각각 노란 박스안을 적분할 것이다. 그리고 그 로컬(local)적분값을 P0(마스터프로세서)로 송신해 최종 적분 값을 도출해낸다. 여기서 사용된 기법은 중앙점(Midpoint) 적분으로, 적분과정에서 사각형의 넓이들의 덧샘만 존재한다. 따라서 병렬 프로그램으로 작성하기 수월하다.
III.1 집합통신이란?
집합통신(Collective Communications)이란, 프로세서들 간 메세지를 동시에(엄밀하게는 동시는아니다.) 주고 받는 통신을 말한다. 다시말하면, 한 그룹의 프로세서가 참여하는 통신이다. 점대점 통신을 기반으로하나, 그보다 구현이 편리하고 성능이 좋다. 대신, 논블로킹 루틴과 꼬리표(TAG)가 없다.
집합통신의 종류는 몇가지로 나눌 수 있는데, 오른쪽 그림과 같이 한 프로세서의 하나의 데이터(메시지)를 다른 프로세서들에게 보내는 Broadcast; 한 프로세서의 여러 데이터를 다른 프로세서들에게 하나씩 뿌려주는 Scatter, 그리고 그 반대의 Gather; 프로세서에 각각 분산되어있던 데이터를 모두가 공유하는 All gather; 각자 가진 프로세서의 데이터를 모두에게 뿌려 나눠갖는 All to All 이 있다.
메시지 통신과 동시에, 어떤 임의의 계산도 가능하다. Reduce와 Scan을 통해서가능한데, Gather 수행과 동시에 계산을 하는 Reduce; 프로세서 순서별로 하나씩 계산을 더해가며 다시 뿌려주는 Scan이 있다.
본 게시글의 예시에는 이 중 Gather 만이 사용되었지만, 많은 예시들이 있으므로 추가적인 게시글을 통해 공유하도록 하겠다.
III.2 포트란 + MPI 코드
언어가 포트란이라 아쉬운 사람은 C 코드도 원본게시글(링크)에 함께 첨부되어있으니 활용하면 좋을 것이다.
Program Example1_4
implicit none
integer n, p, i, j, proc, ierr, master, myid, tag, comm
real h, a, b, integral, pi, ai, my_int, integral_sum, buf(50) !<- buf to gather messages
include "mpif.h" ! brings in pre-defined MPI constants, ...
data master/0/ ! processor 0 collects integral sums from other processors
comm = MPI_COMM_WORLD
call MPI_Init(ierr) ! starts MPI
call MPI_Comm_rank(comm, myid, ierr) ! get current proc ID
call MPI_Comm_size(comm, p, ierr) ! get number of procs
pi = acos(-1.0) ! = 3.14159...
a = 0.0 ! lower limit of integration
b = pi*1./2. ! upper limit of integration
n = 500 ! number of intervals in (b-a)/p
h = (b-a)/n/p ! length of increment
ai = a + myid*n*h ! lower limit of integration for partition myid
my_int = integral(ai, h, n)
write(*,"('Process ',i2,' has the partial sum of',f10.6)")
& myid,my_int
call MPI_Gather(
& my_int, 1, MPI_REAL, ! Send buffer, size, data type
& buf, 1, MPI_REAL, ! Receive buffer, size, data type
& master, ! destination process
& comm, ierr)
write(*,"( 'Message of P#',i2,' is sended')") myid
if(myid .eq. master) then
integral_sum = 0.0
do i=1,p
write(*,"('buffer #',i2,'=',f10.6)") i,buf(i)
integral_sum = integral_sum + buf(i)
enddo
print *,'The Integral =',integral_sum
endif
call MPI_Finalize(ierr) ! let MPI finish up ...
end
real function integral(ai, h, n)
implicit none
integer n, j
real h, ai, aij
integral = 0.0 ! initialize integral
do j=0,n-1 ! sum integrals
aij = ai +(j+0.5)*h ! abscissa mid-point
integral = integral + cos(aij)*h
enddo
return
end
컴파일을 하고, 실행하면 다음과 같이 출력된다! 적분 값이 1.0000001로 출력되어 잘 구동되었음을 알 수 있다.
$ mpiexec -n 4 ./Collective.exe
Process 0 has the partial sum of 0.382684
Process 2 has the partial sum of 0.216773
Message of P# 2 is sended
Process 1 has the partial sum of 0.324423
Message of P# 1 is sended
Message of P# 0 is sended
buffer # 1= 0.382684
buffer # 2= 0.324423
buffer # 3= 0.216773
buffer # 4= 0.076120
The Integral = 1.0000001
Process 3 has the partial sum of 0.076120
Message of P# 3 is sended
'Engineer > 병렬컴퓨팅' 카테고리의 다른 글
5. 유도데이터타입(CONTIGUOUS), 예제로 배우기 (0) | 2020.03.24 |
---|---|
4. 집합통신-2, 예제(수치적분)로 배우기 (0) | 2020.03.24 |
2. 논블로킹 통신, 예제(수치적분)로 배우기 (0) | 2020.03.24 |
1. 블로킹 통신, 예제(수치적분)로 배우기 (2) | 2020.03.19 |
포트란으로 MPI 배우기 (0) | 2020.03.19 |
댓글