썬 스튜디오 컴파일러(C/C++/Fortran 95) 는 OpenMP 병렬화를 네이티브하게 지원합니다. OpenMP 는 공유 메모리 환경에서의 병렬 프로그래밍을 위한 표준 모델로써 발전되어 오고 있습니다. 프로그래머가 그들의 코드를 손쉽게 병렬화 할 수 있도록 pragma, 실행 루틴, 환경변수등을 제공합니다. 이 글은 OpenMP 에 대한 간단한 소개와 함께 썬 스튜디오 컴파일러의 OpenMP 지원에 대해서 간략히 소개 합니다. 이 글은 특히 OpenMP 를 처음 접하거나 Fortran, C, C++ 에서의 병렬 프로그램에 관심이 있는 프로그래머들을 위한 글입니다.
OpenMp 란 무엇입니까?
OpenMP 는 공유 메모리 환경에서의 병렬 프로그래밍을 위한 스펙입니다. OpenMP 는 Fotran, C, C++ 프로그램에서 공유-메모리의 병렬화를 지정하는데 사용할 수 있는 pragma, 실행 루틴, 환경변수들을 제공합니다.
OpenMP 의 pragma 가 프로그램 안에서 사용되면, OpenMP를 인식할 수 있는 컴파일러가 멀티 쓰레드를 사용해서 병렬적으로 실행 될 수 있도록 실행파일을 생성합니다. 약간의 소스 코드 수정만이 필요합니다(최고의 퍼포먼스를 얻기 위한 최적의 튜닝을 제외한) OpenMP pragma 는 다양한 아키텍쳐와 시스템상에서 프로그램을 병렬화 할 수 있도록 하는 우아하고 일관적이고 포터블한 인터페이스를 제공합니다. OpenmP 는 광범위하게 수용되고 있는 스펙으로써 썬, 인텔, IBM, SGI 등의 회사가 지원합니다. (아래의 참고자료 에서 OpenMP 웹사이트 링크를 참고해서 최신 OpenMP 스펙 문서를 확인하시기 바랍니다.)
OpenMP 는 프로그래머를 위해 쓰레드를 생성하고 관리함으로써 병렬 프로그래밍을 새로운 단계로 이끌어 줍니다. 여러분이 할일은 단순히 적절한 pragma 를 소스 프로그램에 삽입한 다음 OpenMP 를 지원하는 컴파일러를 이용해서 적절한 컴파일러 옵션과 함께(썬 스튜디오는 -xopenmp 컴파일러 옵션을 사용함) 프로그램을 컴파일 하는 것입니다. 컴파일러는 pragma 를 해석한다음 코드를 병렬화 합니다. OpenMP를 지원하지 않는 컴파일러를 사용하면 OpenMP pragma 들은 조용히 무시됩니다.
이 글은 OpenMP 를 C, C++ 프로그램에서 사용하는 예제를 제공합니다. 동일한 pragma 들이 Fortran 에도 존재 합니다. OpenMP 유저 가이드에서 더 자세한 정보를 확인하시기 바랍니다.
OpenMP Pragma
OpenMP 스펙은 pragma 셋을 정의 합니다. pragma 는 컴파일러 지시자로써 pragma 이후의 코드 블럭들을 어떻게 처리할지 컴파일러에게 지정합니다. 가장 기본적인 pragma 는 #pragma omp parallel 이고 병렬 구역 을 지정합니다.
OpenMP 는 병렬 실행의 fork-join 모델을 사용합니다. OpenMP 프로그램은 처음에 싱글 쓰레드로 시작하고 이것을 초기 쓰레드라고 부릅니다. 쓰레드가 병렬 구조를 만나게 되면 그 자신을 포함한 0개 혹은 그 이상의 쓰레드를 팀으로 생성하고 그 자신은 새로운 팀의 마스터가 됩니다. 새로운 팀의 모든 멤버들은(마스터 를 포함) 코드를 병렬 구조 안에서 실행하게 됩니다. 병렬 구조의 끝에는 암묵적인 장벽이 있습니다. 오직 마스터 쓰레드 만이 병렬 구조가 끝난 이후에도 계속해서 유저 코드를 수행하게 됩니다.
병렬 구역을 실행할 팀의 쓰레드 갯수는 몇가지 방법들로 제어 됩니다. 한가지 방법은 환경변수 OMP_NUM_THREADS 을 사용하는 것입니다. 다른 방법은 실행 루틴 omp_set_num_threads() 를 실행하는 것입니다. 또 다른 방법으로는 parallel pragma 와 함께 num_threads 절을 사용하는 것입니다.
OpenMP 는 병렬 구역에서 팀내의 쓰레드간 작업을 지정해줄 수 있는 2가지 종류의 작업-공유 구조를 지원합니다. 이러한 작업-공유 구조는 루프와 섹션들입니다. #pragma omp 는 루프를 위해 사용 되고 #pragma omp sections 은 섹션 을 위해 사용됩니다. -- 병렬로 수행될 수 있는 코드의 블럭들.
#pragma omp barrier 는 팀내의 모든 쓰레드들이 장벽 이후의 코드를 계속해서 실행하기 전에 서로를 기다리도록 지시 합니다. 병렬 구역의 마지막에는 암시적으로 장벽이 존재 합니다. #pragma omp master 는 코드 이후의 블럭들은 오직 마스터 쓰레드에 의해서만 실행되어야 함을 컴파일러에 지시합니다. #pragma omp single 는 코드 이후의 블럭들은 오직 팀내의 하나의 쓰레드에 의해서만 실행되어야 함을 지시합니다; 꼭 이 쓰레드가 마스터 쓰레드일 필요는 없습니다. #pragma omp critical pragma 를 이용해서 한번에 오직 하나의 쓰레드에 의해서만 코드 블럭이 수행되도록 보호할 수 있습니다. 물론 이러한 모든 pragma 들은 오직 병렬 pragma의 문맥 하에서만 의미가 있습니다.(병렬 구역).
OpenMP 실행 루틴
OpenMP 는 프로그램의 쓰레드에 관한 정보를 얻는데에 사용할 수 있는 몇가지 실행 루틴들을 제공합니다. omp_get_num_threads(), omp_set_num_threads(), omp_get_max_threads(), omp_in_parallel() 이 이러한 루틴들 입니다. 추가적으로 OpenMP는 몇가지 lock 루틴을 제공함으로써 쓰레드 동기화에 사용할 수 있도록 합니다.
OpenMP 환경 변수
OpenMP 는 OpenMP 프로그램의 동작을 제어하는데 사용될 수 있는 몇가지 환경 변수들을 제공합니다.
가장 중요한 환경변수는 OMP_NUM_THREADS 으로 병렬 구역을 실행할때 사용되는 팀 내의 쓰레드 갯수를 지정합니다. (팀의 마스터 쓰레드를 포함) 그외에 널리 이용되는 환경 변수는 OMP_DYNAMIC 입니다. 이 환경변수를 FALSE 로 조정하면 런타임시에 쓰레드의 갯수를 동적으로 조정하는 것을 비활성화 시킵니다. 일반적인 규칙은 쓰레드의 갯수를 시스템의 코어수 보다 크게 지정하지 않는다는 것입니다.
OpenMP 환경 변수에 부가적으로 썬 스튜디오 컴파일러는 런타임 환경을 좀 저 조정할 수 있도록 썬-특수한 환경 변수들을 제공합니다. 이러한 것들은 OpenMP 유저 가이드에 기술되어 있습니다.
예제
간단한 배열 곱셈 프로그램을 통해서 OpenMP 가 어떻게 프로그램을 병렬화 시키는지 알아보도록 하겠습니다. 배열 2개를 곱해 주는 작은 코드를 보시기 바랍니다. 이것은 아주 간단한 예제이고 정말로 여러분이 훌륭한 배열 곱셈 루틴을 원한다면 캐쉬 효과를 고려하던지 혹은 좀 더 낳은 알고리즘(Strassen, Coppersmith 혹은 Winograd 의 알고리즘 같은) 을 사용해야 합니다.
for (ii = 0; ii < nrows; ii++) {
for (jj = 0; jj < ncols; jj++) {
for (kk = 0; kk < nrows; kk++) {
array[ii][jj] = array[ii][kk] * array[kk][jj];
}
}
}
주의할 점으로 위의 루프의 각 레벨에서 각각의 루프 반복은 독립적으로 실행될 수 있습니다. 그러므로 위의 코드 세그먼트를 병렬화 하는 것은 매우 직관적입니다: #pragma omp parallel for pragma 를 루프의 가장 바깥에 지정합니다 (ii 루프). pragma 를 가장 바깥 루프에 지정하는 이유는 그것이 최고의 퍼포먼스 이득을 가져다 주기 때문입니다. 병렬화된 루프에서 변수 array, ncols, nrows 는 쓰레드 간에 공유 됩니다. 그러나 변수 ii, jj, kk 는 서로 공유되지 않습니다. 이제 위의 코드는 아래와 같이 바뀝니다:
#pragma omp parallel for shared(array, ncols, nrows) private(ii, jj, kk)
for (ii = 0; ii < nrows; ii++) {
for (jj = 0; jj < ncols; jj++) {
for (kk = 0; kk < nrows; kk++) {
array[ii][jj] = array[ii][kk] * array[kk][jj];
}
}
}
또 다른 예제로 0 <= x < n 구간에서 f(x) 의 합을 구하는 다음의 코드를 보시기 바랍니다.
for (ii = 0; ii < n; ii++) {
sum = sum + some_complex_long_fuction(a[ii]);
}
위의 코드를 병렬화하기 위한 첫번째 단계는 다음과 같을 것입니다
#pragma omp parallel for shared(sum, a, n) private(ii, value)
for (ii = 0; ii < n; ii++) {
value = some_complex_long_fuction(a[ii]);
#pragma omp critical
sum = sum + value;
}
혹은 좀 더 낳은 방법으로 reduction 절을 사용할 수 있습니다
#pragma omp parallel for shared(a, n) private(ii) reduction(+: sum)
for (ii = 0; ii < n; ii++) {
sum = sum + some_complex_long_fuction(a[ii]);
}
시작하기
프로그램을 병렬화 하는 방법은 여러가지가 있습니다. 첫째로 병렬화가 필요한지 결정합니다. 몇몇 알고리즘은 병렬화에 맞지 않을 수도 있습니다. 만약 새로운 프로젝트를 시작한다면 병렬화할 수 있는 알고리즘을 선택할 수도 있습니다. 가장 중요한 것은 코드가 정확한지(직렬적으로) 병렬화를 시도하기 전에 확인하는 것입니다. 직렬화시에 실행시간을 미리 알아둠으로써 병렬화가 유용한지도 미리 확인하는 것이 좋습니다.
직렬화버전의 프로그램을 최적화 옵션을 사용해서 컴파일 하십시오. 일반적으로 컴파일러는 여러분이 할 수 있는 것 보다 더 많은 최적화를 수행할 수 있습니다.
여러분의 프로그램을 병렬화할 준비가 되었다면 썬 스튜디오의 다양한 기능들이 이러한 목표를 달성할 수 있도록 도와줄 것입니다. 기능들에 대한 간략한 설명이 아래에 기술되어 있습니다.
자동 병렬화
컴파일러의 자동 병렬화 옵션 (-xautopar) 을 시도해 봅니다. 병렬화를 컴파일러에 위임함으로써 여러분의 어떠한 노력 없이도 프로그램을 병렬화할 수 있습니다. 자동병렬화 기능은 또한 OpenMP pragma 를 이용해서 병렬화 될 수 있는 코드의 부분들을 인식할 수 있도록 도와주거나 병렬화를 방해 하는 부분들을 알려 주기도 합니다(예를 들어 내부 루프간 의존성등). 컴파일러의 코멘트를 -g 플래그를 이용해서 컴파일 하고 썬스튜디오의 er_src(1) 유틸리티를 이용함으로써 볼 수 있습니다. 아래를 참고하시기 바랍니다.
% cc -g -xautopar -c source.c
% er_src source.o
자동범위화(Autoscoping)
OpenMP 프로그래밍의 가장 일반적인 타입의 에러는 범위 지정 에러입니다. 즉 private 으로 범위가 지정되어야 할 변수들이 shared 로 잘못 지정되었을 때를 말합니다. 썬스튜디오 컴파일러의 자동범위화 기능은 변수의 범위를 지정하는 작업의 부담을 덜어 줍니다. OpenMP 의 두가지 확장 기능이 지원됩니다: __auto, default(__auto) . OpenMP 유저 가이드를 참고하시기 바랍니다.
dbx 디버거
썬 스튜디오 디버거 dbx 는 쓰레드를 지원하는 디버거로써 여러분의 OpenMP 프로그램 디버깅을 도와줄 것입니다. OpenMP 프로그램을 디버깅 하기 위해 첫째로 프로그램을 -xopenmp=noopt -g 컴파일러 옵션을 이용해서 어떠한 최적화도 하지 않은 상태로 컴파일 합니다. 그 다음 dbx 를 결과 실행파일에 실행 시킵니다. dbx 를 이용해서 병렬 구역 내부에 브레이크포인트를 지정할 수도 있고 병렬 구역의 코드를 볼 수도 있고 또한 쓰레드에 private 한 변수들도 검사해 볼 수 있습니다.
퍼포먼스 분석기
썬 스튜디오 퍼포먼스 분석기를 이용해서 프로그램 내의 병목현상을 찾아 냅니다. 이 툴은 대규모의 시간이 소비되는 프로그램내의 핫 루틴을 찾는데 도움을 줍니다. 이 툴은 또한 작업단위와 시간 단위, 함수의 속성, 소스 라인, 명령어 단위등을 통해서 OpenMP 프로그램의 병목현상을 집어 내는데에 도움을 줄 수 있습니다.
OpenMP 와 MPI 혼합해서 사용하기
MPI (Message Passing Interface) 는 병렬 프로그램의 또 다른 모델입니다. OpenMP 와 다르게 MPI 는 여러개의 프로세스를 띄운다음 TCP/IP 를 이용해서 통신합니다. 이러한 프로세스들이 동일한 주소 공간을 공유하지 않기 때문에 원격 머신에서도(혹은 클러스터 머신) 실행이 가능합니다. OpenMP 와 MPI 어느쪽이 더 낳은지는 이야기 하기 불가능합니다. 각각의 장점과 단점이 존재하기 때문입니다. 이것 보다 더 흥미로운 점은 OpenMP 가 MPI 와 같이 사용될 수 있다는 것입니다. 일반적으로는 MPI 를 이용해서 대용량의 작업을 몇몇 머신들로 나눈다음 OpenMP 를 이용해서 각각의 싱글 머신상의 프로그램을 병렬화 하게 됩니다.
요약하자면 썬 스튜디오 컴파일러와 툴은 OpenMP 를 네이티브하게 지원하고 프로그램을 병렬화 할 수 있도록 도와주는 수 많은 유용한 기능을 가지고 있다는 것입니다. 좀 더 자세한 정보는 아래의 참고자료를 보시기 바랍니다.
참고자료
- OpenMP specifications for C/C++ and Fortran 95. 예제와 코멘트 포함
- compunity.org OpenMP 유저 커뮤니티
- Techniques for Optimizing Applications Rajit Garg, Ilya Sharapo 지음. 썬 울트라SPARC 플랫폼에서 계산 집약적인 프로그램의 퍼포먼스 최적화를 위한 가이드.
- Sun Studio 11: OpenMP API User's Guide. 썬 스튜디오 구현 특수한 정보를 담은 메뉴얼.
- Parallel Programming in OpenMP ISBN 1-55860-671-8.
- OpenMP Support in Sun Studio Compilers and Tools
이 아티클의 원본 : http://developers.sun.com/sunstudio/articles/omp-intro.html
"개발자코너" 카테고리의 다른 글
- C++ ABI의 안정성: 프로그래밍 언어의 진화 (댓글 1개 / 트랙백 0개) 2006/02/23
- DTrace를 사용하여 유저가 조정하는 애플리케이션 크래쉬 데이타 정보 모으기 (댓글 1개 / 트랙백 0개) 2006/08/23
- 솔라리스 상에서 "자바 GNOME" 바인딩을 이용해서 개발하기 (댓글 3개 / 트랙백 0개) 2007/04/20
- libumem 라이브러리를 이용하여 어플리케이션 내의 메모리 관리 버그를 잡아 내는 방법 (댓글 1개 / 트랙백 1개) 2006/03/23
- 솔라리스 디바이스 드라이버 작성을 원하십니까? (댓글 0개 / 트랙백 0개) 2008/09/18
- dbx가 프로세스나 코어 파일을 읽지 못하는 이유 (댓글 1개 / 트랙백 0개) 2006/01/23
- dbx를 통한 Java 어플리케이션 디버깅: Java 코드를 위한 업계 최고 수준의 디버깅 (댓글 1개 / 트랙백 0개) 2005/11/23
- OpenMP 소개: 포터블한, 공유 메모리 멀티프로세서 환경에서의 병렬 프로그래밍 API (댓글 10개 / 트랙백 1개) 2007/07/16
- SPOT을 이용한 손쉬운 어플리케이션 성능 분석 (댓글 1개 / 트랙백 0개) 2006/06/23
- Dmake 를 사용하여 어플리케이션 빌드의 속도를 향상시키기 (댓글 0개 / 트랙백 0개) 2008/10/15
TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/406
-
OpenMP 소개: 포터블한, 공유 메모리 멀티프로세서 환경에서의 병렬 프로그래밍 API
Tracked from ★ dingpong의 조그만 휴식 공간 ★ 삭제OpenMP 소개: 포터블한, 공유 메모리 멀티프로세서 환경에서의 병렬 프로그래밍 API강좌 입니다. OpenMP 에 대해서는 앞에서도 소개해본 바 있지만 이 강좌에서는 좀 더 기초적이고 개요적인 내용이 나와 있습니다. [OpenMP 는 공유 메모리 환경에서의 병렬 프로그래밍을 위한 스펙입니다. OpenMP 는 Fotran, C, C++ 프
2007/09/20 01:57
댓글을 달아 주세요
MPI가 병렬 프로그램의 또 다른 모델이로군요
2007/09/12 21:37짬짬이 좋은 공부 하고 갑니다. 좋은 자료 많이 많이 올려주세요.
2007/09/12 22:00항상 찾아 보면 좋은 자료가 참 많습니다.
2007/09/14 13:04오늘도 배우고 갑니다 ^^
하나하나 알아가는재미가 점점 생기네요..
2007/09/15 19:05좋은 정보 감사해요~
2007/09/19 03:25잘 읽었습니다.
2007/09/19 14:51오늘도 하나 배우고 갑니다 ^^
2007/09/19 19:23너무 너무 감사합니다.
2007/09/19 19:24좋은 정보 많이 배우고 가요~
2007/09/19 22:43정말 저에게 많은 도움이 될만한 글이네요. OpenMP 에 대한 여러 글중에서도 쉽고 편하게 설명이 되어 있네요^^ 도움이 정말 많이 되었어요~
2007/09/20 01:57