본문 바로가기
Engineer/병렬컴퓨팅

4. 집합통신-2, 예제(수치적분)로 배우기

by _제이빈_ 2020. 3. 24.

이 글은 점대점 통신(블로킹과 논블로킹)에 대한 이해를 바탕으로 집합 통신(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
반응형

댓글