MPI 튜토리얼을 제공하는 원본게시글을 따라가며 이해한 내용들을 기록한 문서이다.
포트란으로 병렬컴퓨팅 배우기 ←링크
V MPI 유도데이터타입 _____________________
- Derived Data Type.
코딩을 하다보면, 데이터를 읽어 올때 내장 된 데이터 타입 외의 데이터 구조를 사용하면 편한 경우가 있다. 예를 들어 1~100을 1~10, 10 단위로 나눠야하는 상황(1~10, ... , 91~100)을 생각해 보자. 이런경우 루프를 통해 정수를 하나씩 읽어오기에는 다소 비효율적이다. 그보다 정수 10개짜리 리스트 형식을 정의해 한번에 10개씩 읽어오면 코드는 훨씬 간결하해지고 가독성이 좋아질 수 있다.
데이터 구조를 지정해주는 기법이 MPI 표준에도 존재한다. MPI 기본 데이터 유형을 기반으로 고유 한 데이터 구조를 정의 할 수있는 기능이다. 아에 데이터 구조를 만든다기보다, 기 존재하는 유형을 바탕으로 하기 때문에 파생 데이터 형식이라 부른다. 이러한 유도데이터 타입으로는 기본적으로 Contiguous, Vector, Indexed, 그리고 Struct이 존재한다.
˙MPI_TYPE_CONTIGUOUS : 가장 간단한 기법으로 기 존재하는 데이터 유형이 반복되어있는 형식을 정의한다.

˙MPI_TYPE_VECTOR (hvector) : contiguous와 비슷하나, 데이터간 일정한 간격(hvector는 간격이 바이드 단위)을 둔다.

˙MPI_TYPE_INDEXED (hindexed) : 데이터의 시작지점(offset) 및 블록의 길이(blocklens)을 지정하여 데이터를 읽어온다.

˙MPI_TYPE_STRUCT (MPI_Type_create_struct in MPI-3.0) : 한번에 여러 데이터 형식을 지정할 수 있다.

당연히 위 짧은 설명과 코드의 파라미터만 봐서는 이해하기 어려우니, 예제를 통해서 알아보자.
V.1 MPI_TYPE_CONTIGUOUS _________________________________
언어가 포트란이라 아쉬운 사람은 C 코드도 원본게시글(링크)에 함께 첨부되어있으니 활용하면 좋을 것이다. 코드는 다음과 같다.
program contiguous include 'mpif.h' integer SIZE parameter(SIZE=4) integer numtasks, rank, source, dest, tag, i, ierr real*4 a(0:SIZE-1,0:SIZE-1), b(0:SIZE-1) integer stat(MPI_STATUS_SIZE) integer columntype ! required variable tag = 1 ! Fortran stores this array in column major order data a /1.0, 2.0, 3.0, 4.0, & 5.0, 6.0, 7.0, 8.0, & 9.0, 10.0, 11.0, 12.0, & 13.0, 14.0, 15.0, 16.0 / call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) ! create contiguous derived data type call MPI_TYPE_CONTIGUOUS(SIZE, MPI_REAL, columntype, ierr) call MPI_TYPE_COMMIT(columntype, ierr) if (numtasks .eq. SIZE) then ! task 0 sends one element of columntype to all tasks if (rank .eq. 0) then do i=0, numtasks-1 call MPI_SEND(a(0,i), 1, columntype, i, tag, MPI_COMM_WORLD,ierr) end do endif ! all tasks receive columntype data from task 0 source = 0 call MPI_RECV(b, SIZE, MPI_REAL, source, tag, MPI_COMM_WORLD, stat, ierr) print *, 'rank= ',rank,' b= ',b else print *, 'Must specify',SIZE,' processors. Terminating.' endif ! free datatype when done using it call MPI_TYPE_FREE(columntype, ierr) call MPI_FINALIZE(ierr) end
그대로 컴파일하고 수행을 하였을때, 결과가 나오지 않는 체 멈추는 현상이 발견되었다. 무한루프가 돌 일도 없는데 말이다. 디버깅을 좀 해봤더니, 마스터 프로세서(0)에서 MPI_SEND를 마스터 프로세서로 보낼 시 멈춰 있었다. 블로킹 통신이라그런지 SEND에 걸리고 RECV도 같은 버퍼를 찾으려하는 등진행하지 못하고 멈춰 있던 것이다. 하지만 정확한 요인을 잘 모르겠다...공부해야지
어쨋든 같은 결과 값을 내기 위해서 다음과 같이 수정하였다.
program contiguous include 'mpif.h' integer SIZE parameter(SIZE=4) integer numtasks, rank, source, dest, tag, i, ierr real*4 a(0:SIZE-1,0:SIZE-1), b(0:SIZE-1) integer stat(MPI_STATUS_SIZE) integer columntype ! required variable tag = 1 ! Fortran stores this array in column major order data a /1.0, 2.0, 3.0, 4.0, & 5.0, 6.0, 7.0, 8.0, & 9.0, 10.0, 11.0, 12.0, & 13.0, 14.0, 15.0, 16.0 / call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr) ! create contiguous derived data type call MPI_TYPE_CONTIGUOUS(SIZE, MPI_REAL, columntype, ierr) call MPI_TYPE_COMMIT(columntype, ierr) if (numtasks .eq. SIZE) then ! task 0 sends one element of columntype to all tasks if (rank .eq. 0) then do i=1, numtasks-1 call MPI_SEND(a(0,i), 1, columntype, i, tag, & MPI_COMM_WORLD,ierr) end do print *, 'rank= ', rank, ' b= ', a(0:3,0) else ! all tasks receive columntype data from task 0 source = 0 call MPI_RECV(b, SIZE, MPI_REAL, source, tag,& MPI_COMM_WORLD,stat, ierr) print *, 'rank= ',rank,' b= ',b endif else print *, 'Must specify',SIZE,' processors. Terminating.' endif ! free datatype when done using it call MPI_TYPE_FREE(columntype, ierr) call MPI_FINALIZE(ierr) end
결과적으로 이쁜 출력을 보여줬다.
$ mpirun -n 4 ./contiguous_ex.exe rank= 0 b= 1.0000000 2.0000000 3.0000000 4.0000000 rank= 1 b= 5.0000000 6.0000000 7.0000000 8.0000000 rank= 3 b= 13.000000 14.000000 15.000000 16.000000 rank= 2 b= 9.0000000 10.000000 11.000000 12.000000
본 포스팅에서는 가장 간단한 기법인 MPI_TYPE_CONTIGUOUS 만 다뤘다. 추가적으로 Vector, Indexed, 그리고 Struct에 대해서도 다루도록 하겠다.
'Engineer > 병렬컴퓨팅' 카테고리의 다른 글
개념-1 : Concurrency vs. Parallelism (0) | 2020.03.24 |
---|---|
6. 유도데이터타입2(STRUCT), 예제로 배우기 (0) | 2020.03.24 |
4. 집합통신-2, 예제(수치적분)로 배우기 (0) | 2020.03.24 |
3. 집합통신, 예제(수치적분)로 배우기 (0) | 2020.03.24 |
2. 논블로킹 통신, 예제(수치적분)로 배우기 (0) | 2020.03.24 |
댓글