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 |
댓글