이 글은 점대점 통신(블로킹과 논블로킹)에 대한 이해를 바탕으로 집합 통신(Collective communication)의 예제를 다뤘다.
MPI 코드로 수치적분을 구현한 원본게시글을 따라가며 이해한 내용들을 기록한 문서이다.
포트란으로 병렬컴퓨팅 배우기 ←링크
IV MPI 집합통신과 수치적분
- Numerical Integration wtih MPI Collective Communications.

MPI 집합통신 예제로 평범하고 하찮은(원본이 이렇게 소개한다.) 그리고 간단한 알고리즘인 수치적분법을 가져왔다. 부분적분을 각 프로세서에서 진행하고, 그 합을 다시 마스터 프로세서에서 수행하는 것으로 적분이 완료되는 알고리즘이다. 코드만 보고 알고리즘 이해가 어렵다면, 앞 포스트의 수치적분 개념설명(링크)을 참고하길 바란다.
위 그림과 함께 예제를 간단히 소개하겠다. P0 ~ P3 은 프로세서로써 각각 노란 박스안을 적분할 것이다. 그리고 그 로컬(local)적분값을 P0(마스터프로세서)로 송신해 최종 적분 값을 도출해낸다. 여기서 사용된 기법은 중앙점(Midpoint) 적분으로, 적분과정에서 사각형의 넓이들의 덧샘만 존재한다. 따라서 병렬 프로그램으로 작성하기 수월하다.
IV.1 집합통신이란?
집합통신(Collective Communications)이란, 프로세서들 간 메세지를 동시에(엄밀하게는 동시는아니다.) 주고 받는 통신을 말한다. 다시말하면, 한 그룹의 프로세서가 참여하는 통신이다. 점대점 통신을 기반으로하나, 그보다 구현이 편리하고 성능이 좋다. 대신, 논블로킹 루틴과 꼬리표(TAG)가 없다.

집합통신의 종류는 몇가지로 나눌 수 있는데, 오른쪽 그림과 같이 한 프로세서의 하나의 데이터(메시지)를 다른 프로세서들에게 보내는 Broadcast; 한 프로세서의 여러 데이터를 다른 프로세서들에게 하나씩 뿌려주는 Scatter, 그리고 그 반대의 Gather; 프로세서에 각각 분산되어있던 데이터를 모두가 공유하는 All gather; 각자 가진 프로세서의 데이터를 모두에게 뿌려 나눠갖는 All to All 이 있다.
메시지 통신과 동시에, 어떤 임의의 계산도 가능하다. Reduce와 Scan을 통해서가능한데, Gather 수행과 동시에 계산을 하는 Reduce; 프로세서 순서별로 하나씩 계산을 더해가며 다시 뿌려주는 Scan이 있다.
본 게시글의 예시에는 Broadcast 와 Reduce를 사용해 수치적분을 구현하였다.
IV.2 포트란 + MPI 코드
언어가 포트란이라 아쉬운 사람은 C 코드도 원본게시글(링크)에 함께 첨부되어있으니 활용하면 좋을 것이다.
Program Example1_5 implicit none integer n, p, i, j, proc, ierr, master, myid, tag, comm real h, a, b, integral, pi, ai, my_int, integral_sum include "mpif.h" ! brings in pre-defined MPI constants, ... integer status(MPI_STATUS_SIZE) ! size defined in mpif.h 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/2. ! upper limit of integration tag = 123 ! message tag if(myid .eq. master) then print *,'The requested number of processors =',p print *,'enter number of increments within each process' read(*,*)n endif c**Broadcast "n" to all processes defined by "comm" call MPI_Bcast( ! Broadcast "n" to all procs & n, 1, MPI_INTEGER, ! Buffer, size, data type & master, comm, ierr) ! source of message 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_Reduce( ! a collective reduction operation & my_int, ! message to send & integral_sum, 1, MPI_REAL, ! Triplet of receive buffer, size, data type & MPI_SUM, ! Reduction operator & master, & comm, ierr) if(myid .eq. master) then 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
코드를 이해했다면 컴파일을 하고,
mpif90 Collective2.for -o Collective2.exe
코드를 구동시켜본다. 다음과 같이 에러가 거의 없는 결과를 낼수 있었다.
$ mpiexec -n 4 ./Collective2.exe The requested number of processors = 4 enter number of increments within each process 700 Process 0 has the partial sum of 0.382683 Process 1 has the partial sum of 0.324423 Process 2 has the partial sum of 0.216773 Process 3 has the partial sum of 0.076120 The Integral = 0.99999964
'Engineer > 병렬컴퓨팅' 카테고리의 다른 글
6. 유도데이터타입2(STRUCT), 예제로 배우기 (0) | 2020.03.24 |
---|---|
5. 유도데이터타입(CONTIGUOUS), 예제로 배우기 (0) | 2020.03.24 |
3. 집합통신, 예제(수치적분)로 배우기 (0) | 2020.03.24 |
2. 논블로킹 통신, 예제(수치적분)로 배우기 (0) | 2020.03.24 |
1. 블로킹 통신, 예제(수치적분)로 배우기 (2) | 2020.03.19 |
댓글