Nawal Copty (Scalable Systems Group  엔지니어, OpenMP 프로젝트 리더 )


OpenMP 는 멀티-쓰레드 공유 메모리 병렬화를 위해 사용될 수 있는 컴파일러 지시자, 라이브러리 루틴, 환경 변수들의 집합등을 정의한 스펙입니다. OpenMP 는 매우 빠르게 어플리케이션 병렬화의 표준 패러다임으로 변하고 있습니다. 상대적으로 작은 수준의 코드 수정 만으로도 프로그래머는 공유 메모리 멀티 프로세서 시스템 상에서 어플리케이션의 퍼포먼스 스케일 향상을 얻을 수 있습니다.


이 문서는 OpenMP 의 계산 모델에 대한 소개와 썬 스튜디오 컴파일러에서의 OpenMP 지원에 대해 설명합니다. 추가적으로 SPEC OMP2001 벤치마크 를 통한 퍼포먼스 결과와 향후 발전 방향에 대해서도 소개 합니다.


OpenMP 는 무엇입니까?


OpenMP 는 어플리케이션 프로그래밍 인터페이스(API) 로 C, C++ 그리고 프토란 프로그램에서 명시적인 멀티쓰레드 공유 메모리 병렬화에서 사용할 수 있습니다. OpenMP 는 3가지 컴포넌트로 이루어져 있습니다.
  • 컴파일러 지시자,
  • 런타임 라이브러리 루틴, 그리고
  • 환경 변수들
C/C++ 에서 OpenMP 지시자는 #pragma 메카니즘을 통해 지정됩니다. 포트란에서 OpenMP 지시자는 유일무이한 표식에 의해 인식되는 특별한 커멘트를 이용해서 지정됩니다 (고정된 형식의 소스 파일들에서 !$omp, c$omp, 그리고 *$omp 같은 표식들이 인식됨).

OpenMP 스펙은 OpenMP 의 명확한 참고자료 입니다. 참고자료 [1] 을 참고하시기 바랍니다. 최신 스펙은 버전 2.5 이고 C, C++, 포트란 스펙들이 모두 포함되어 있습니다. 스펙은 OpenMP 1997년에 비영리 단체로 설립된 아키텍쳐 리뷰 보드(ARB) [2]에 의해 소유되고 관리됩니다.  

ARB 의 멤버쉽은 기업, 연구 기관, 교육 기관들에 열려 있습니다. 썬 마이크로시스템즈는 OpenMP ARB 의 멤버로 API 의 미래를 설계 하는데 중요한 역활을 담당하고 있습니다. 그리고 스펙이 논의되고 업데이트 되어 지는 ARB 의 프로그래밍 언어 분과의 주간 회의에 활동적으로 참여하고 있습니다. 또한 썬의 Distinguished Enginner 가 ARB의 운영위원이자 썬의 엔지니어가 ARB 의 의장을 맡고 있습니다.

OpenmP 를 사용하는 주된 동기는 퍼포먼스, 확장성, 이식성, 그리고 표준성 입니다. 어플리케이션의 요구사항과 데이타 셋은 점점 증가하고 좀 더 강력한 연산 능력이 요구되고 있습니다. 고성능은 하나의 어플리케이션을 실행하는데 여러개의프로세서를 활용함으로써 얻을 수 있습니다. OpenMP 는 공유 메모리 머신에서의 프로그래밍을 지원하는 광범위한 API 를 제공합니다. 상대적으로 적은량의 코딩 노력만으로도 사용자들은 이러한 멀티프로세스 머신에서 그들의 어플리케이션에 퍼포먼스 향상을 얻을 수 있습니다.

썬 스튜디오 어플리케이션 개발 스윗[3] 은 사용하기 쉽고, 썬 플랫폼에서 어플리케이션을 개발하고 배치할 수 있는 도구들과 컴파일러들이 통합되어 있습니다. 썬 컴파일러는 OpenMP 스펙 버전 2.5 를 지원합니다. 또한 썬 스튜디오 툴들은 OpenMP 어플리케이션의 작성, 디버깅 그리고 퍼포먼스 분석을 지원합니다.

OpenMP 실행 모델


OpenMP 의 기반 머신 모델은 공유-메모리 머신 입니다. 즉 모든 프로세서가 하나의 글로벌 메모리를 접근하는 것을 의미 합니다. 공유 메모리 머신의 예로써 4개 이상의 듀얼 코어 AMD 옵테론 프로세서를 가지고 있는 썬 파이어 V40z, 8개 이상의 듀얼 코어 울트라SPARC IV+ 프로세서를 가지고 있는 썬 파이어 V890, 그리고 72개 이상의 듀얼 코어 울트라SPARC IV+ 프로세서를 가지고 있는 썬 엔터프라이즈 E25K 등 입니다. Figure 1은 n 개의 프로세서를 가지고 있는 공뮤 메모리 머신의 간단한 예를 보여 줍니다.

Figure 1



OpenMP 는 병렬 실행에서 fork-join 모델을 사용합니다. 쓰레드가 병렬 구문를 만나면 쓰레드는 그 자신을 포함한 추가적인 쓰레드(0개 이상의)로 이루어진 쓰레드 팀을 만듭니다. 병렬 구문를 만난 쓰레드는 팀의 마스터 쓰레드를 호출 합니다. 다른 쓰레드들은 팀의 slave 쓰레드라고 부릅니다.

모든 팀 멤버는 병렬 구문내의 코드를 실행합니다. 쓰레드가 작업을 마치면 구문 제일 마지막의 암시적인 장벽에서 대기합니다. 모든 팀 멤버가 장벽에 도착하면 마스터 쓰레드만 계속해서 병렬 구문 이후의 유저 코드를 실행하게 됩니다. 하나의 프로그램에는 여러개의 병렬 구문가 지정될 수 있습니다.

OpenMP 지시자들


OpenMP 는 사용자가 프로그램내에서 병렬화를 지정하는데 사용할 수 있는 다양한 지시자들 셋을 가지고 있습니다. 이 섹션에서는 PARALLEL 지시자, DO/for 지시자directive, 그리고 SECTIONS 지시자등 총 3가지 OpenMP 지시자들의 예를 보여 드립니다. 이들에 대한 좀 더 자세한 정보와 다른 지시자들에 대한 정보들은 [1], [4] 에서 보실 수 있습니다.

OpenMP 는 공유-메모리 프로그래밍 모델에 기반하고 있기 때문에 변수들은 기본적으로 공유 됩니다. OpenMP 데이타 범위 속성 절은 변수의 범위를 명시적으로 지정하는데 사용할 수 있습니다. 이러한 절은 SHARED, PRIVATE, FIRSTPRIVATE, LASTPRIVATE, 그리고 REDUCTION 등이 있습니다.

병렬화 구문을 실행할 쓰레드의 갯수는 환경변수 OMP_NUM_THREADS 를 설정하거나, omp_set_num_threads 런타임 라이브러리 루틴을 실행하거나, 혹은 NUM_THREADS 절을 사용해서 설정할 수 있습니다.

Parallel

PARALLEL 지시자는 복수개의 쓰레드에 의해 병렬로 실행될 코드의 구역을 정의 합니다. PARALLEL 구문을 실행하는데 참여하는 모든 쓰레드들은 동일한 코드를 실행하게 됩니다. 결과적으로 코드의 구역들은 각 쓰레드들로 복제 됩니다.

쓰레드가 PARALLEL 구문을 만나면 쓰레드 팀을 생성하고 팀의 마스터가 됩니다. 마스터는 팀내에서 쓰레드 번호 0번을 가집니다. 다른 쓰레드들은 1, 2, ..., n-1 형식으로 넘버링 되고 여기서 n 은 쓰레드의 총 갯수를 나타 냅니다. PARALLEL 구문의 제일 마지막에는 암묵적인 장벽이 존재 합니다. 오직 마스터 쓰레드만이 이 지점 이후의 코드를 실행시킬 수 있습니다.

부록 A.1 은 PARALLEL 구문의 예제 입니다.

DO/for

DO/for 지시자는 작업 공유 지시자로 DO 루프(포트란) 혹은 for 루프(C/C++) 에 적용 됩니다. DO/for 구문은 DO/for 루프의 매 반복실행문을 팀의 쓰레드에 각각 배분하게 됩니다. DO/for 구문의 제일 마지막에는 NOWAIT 절이 지정된 경우를 제외하고는 암시적인 장벽이 존재합니다.

DO/for 지시자가 지정된 루프의 각 반복실행문이 서로 의존적이지 않음을 확인하는 것은 전적으로 프로그래머의 책임입니다. 즉 한 루프의 실행 결과가 다른 루프의 실행 결과에 의존성을 가지지 않아야 한다는 것입니다. 만약 이러한 조건이 성립 된다면 두개의 서로 다른 루프 반복실행문이 두개의 서로 다른 쓰레드에 의해 병렬적으로 실행될 수 있습니다.

부록 A.2 는 DO/for 지시자의 예제 입니다.

Sections

SECTIONS 지시자는 작업 공유 지시자로 구조화된 코드 블럭에 적용 됩니다. (각 구조화된 블럭을 SECTION 이라고 부름) SECTIONS 구문은 코드의 해당 구문을 만나면 코드의 블럭을 여러개의 쓰레드에 배분합니다. 각 블럭은 팀 내의 하나의 쓰레드에 의해서만 실행 됩니다. SECTIONS 구문의 제일 마지막에는 NOWAIT 절이 지정된 경우를 제외하고는 암시적인 장벽이 존재합니다.

SECTIONS 구문 내의 구조화된 코드 블럭이 서로 의존적이지 않아서 여러개의 서로 다른 쓰레드에 의해 병렬로 실행될 수 있음을 확인하는 것은 전적으로 프로그래머의 책임입니다.

부록 A.3 은 SECTIONS 지시자의 예제 입니다.

썬 스튜디오 소프트웨어에서의 OpenMP 지원


-xopenmp 컴파일러 옵션은 썬 스튜디오 컴파일러가 프로그램 내의 OpenMP 지시자를 인식할 수 있도록 지시 합니다.

컴파일러의 OpenMP 지원은 총 두가지 부분으로 이루어 집니다. 첫째로 컴파일러는 OpenMP 지시자를 처리하고 코드를 변환함으로써 복수개의 쓰레드에 의해 실행 될 수 있도록 해 줍니다. 둘째로 런타임 라이브러리가 쓰레드의 관리, 동기화 그리고 작업 스케줄링을 지원해 줍니다.

컴파일러 지원

Figure 2 는 컴파일러의 다양한 단계와 컴포넌트들을 보여 줍니다. 각 부분들은 각 언어에 맞는 Front-End, Optimizer, machine-dependent Code Generator 로 이루어져 있습니다. 컴파일러의 Front-End 컴포넌트는 OpenMP 지시자를 인식하고, 연관된 정보를 처리하고 그 다음 정보를 Optimizer 로 넘깁니다. Optimizer 는 Fron-End 에서 넘어온 정보를 처리하고 코드를 변환해서 여러개의 쓰레드의 의해 실행될 수 있도록 합니다. 코드 변환시에 Optimizer 는 OpenMP 런타임 라이브러리 libmtsk 을 호출 하는 코드를 삽입합니다. 최종적으로 Code Generator 가 타겟 머신에 맞는 코드를 생성하게 됩니다.

Optimizer 가 프로그램 내의 PARALLEL 구문을 처리할때 다음과 같은 절차를 거칩니다:

Figure 2



첫째로 Optimizer 는 PARALLEL 구문 내의 변수의 범위를 분석 합니다. 즉 PARALLEL 구문 내에서 접근 되는 변수가 SHARED, PRIVATE, FIRSTPRIVATE, LASTPRIVATE, REDUCTION 중에 하나인지를 결정 합니다.

두번째로 Optimizer 가 PARALLEL 구문의 본체를 추출해서 이것을 outlined 루틴이라고 불리우는 분리된 루틴에 위치 시킵니다. SHARED 변수들은 outlined 루틴에 매개변수를 통해서 넘겨지게 됩니다. 그럼으로써 복수개의 쓰레드의 의해 접근이 가능하도록 합니다. PRIVATE 변수들은 outlined 루틴내에서 로컬 변수로 정의 됩니다. 그러므로 이러한 변수들의 독립적인 복사본들이 각각의 다른 쓰레드 스택에 할당됩니다. FIRSTPRIVATE 변수를 초기화 하기 위해 부가적인 코드가 추가 되고, LASTPRIVATE 변수를 업데이트 하고, 축소된 결과들을 합치는 등의 작업을 합니다.

셋째로, Optimizer 는 libmtsk 라이브러리 루틴 __mt_MasterFunction_ 을 호출하도록 본래의 PARALLEL 구문을 변경합니다.  __mt_MasterFunction_  이 런타임시에 실행되면 outlined 루틴을 실행하기 위해 쓰레드 팀을 디스패치 합니다.

위에서 언급된 outlining 변환은 몇가지 장점을 가집니다. 첫째로 outlined 루틴은 복수개의 쓰레드에 의해 쉽게 실행 될 수 있도록 하는 병렬 실행 문맥을 정의 합니다. 둘째로 outlining 은 스토리지 관리를 단순화 시킵니다. outlined 루틴에 로컬 변수들은 자동적으로 서로 다른 쓰레드 스택에 할당될 것이기 때문입니다.

Figures 3(a) 과 3(b) 는 outlining 변환을 나타냅니다. Figure 3(a) 의 PARALLEL 구문 본체는 추출되서 outlined 루틴 __mf_par_001 에 위치됩니다. PARALLEL 구문에서 변수 n 이 SHARED i이기 떄문에 그 주소가 __mf_par_001 의 매개변수로 전달되고 따라서 모든 쓰레드 __mf_par_001 를 실행하고 있는 모든 쓰레드는 동일한 복사본에 접근할 것입니다. 한편으로 변수 id 는 PRIVATE 이므로 이것은 __mf_par_001 에 로컬변수로 선언됩니다. 그러므로 __mf_par_001 를 실행하고 있는 모든 쓰레드는 각 쓰레드의 스택에 해당 변수의 복사본을 가지고 있을 것입니다.

Figure 3(b) 는 PARALLEL 구문이 어떻게  __mt_MasterFunction_ 를 호출하는 구문으로 바뀌고  __mf_par_001 주소가 어떻게  __mt_MasterFunction_ 의 매개변수로 전달되는지 보여 줍니다.

다른 구문들 즉 작업 공유 지시자인 DO/for 와 SECTIONS 은 Optimizer 에 의해 비슷한 방법으로 처리 됩니다. 어쨌든 Optimizer 는 작업-공유 구문을 libmtsk 라이브러리 루틴 __mt_WorkSharing_을 호출하는 것으로 변경합니다.

Figure 3


자동 병렬화

OpenMP 의 지시자-기반의 병렬화 외에도 Optimizer 가 프로그램내의 루프를 자동으로 병렬화 할 수 있습니다. 프로그램이 -xautopar 옵션과 함께 컴파일 되면 Optimizer 는 프로그램 내의 모든 루프를 검사하고 데이타-흐름 분석을 통해 어떠한 루프들이 서로에게 독립적으로 실행될 수 있는지를 결정합니다. Optimizer 는 이때 이러한 루프틀들 위에서 언급된 방법과 비슷한 방법으로 변환하게 됩니다.

런타임 라이브러리 지원

OpenMP 런타임 지원 라이브러리, libmtsk 는 쓰레드 관리, 동기화 및 작업 스케줄링 지원을 제공합니다. 라이브러리는 POSIX 쓰레드 라이브러리 기반으로 구현되었습니다.

위에서 언급한데로 Optimizer 는 PARALLEL 구문을 __mt_MasterFunction_ 을 호출 하는 것으로 변경합니다. 쓰레드가 __mt_MasterFunction_ 을 호출하면 PARALLEL 구문을 실행하기 위한 쓰레드 팀을 생성하고 그 자신이 팀의 마스터 쓰레드가 됩니다. 이후 마스터 쓰레드는 slave 쓰레드들은 디스패치 해서 outlined 루틴들을 작업합니다. 마스터 쓰레드 자신도 outlined 루틴 실행에 동참합니다. 모든 작업이 끝나면 마스터 쓰레드는 __mt_EndOfTask_Barrier_ 장벽 루틴 호출을 통해서 팀내의 다른 쓰레드들과 동기화 됩니다. 일반적인 __mt_MasterFunction_ 로직은 Figure 4 를 참고하시기 바랍니다.

런타임 라이브러리 libmtsk 은 PARALLEL 구문에서 slave 쓰레드로 사용될 수 있는 쓰레드 풀을 유지 합니다. 풀 내의 쓰레드들은 POSIX 쓰레드 라이브러리 루틴 pthread_create 에 의해 생성됩니다. 마스터 쓰레드가 하나 이상의 쓰레드를 갖는 팀을 생성해야 한다면 풀을 검사한다음 풀 내의 idle 한 쓰레드를 끌어내서 이것들을 팀의 slave 쓰레드로 만듭니다. 팀이 PARALLEL 구역 실행을 끝마치면 slave 쓰레드들은 풀로 되돌아 가게 됩니다.

실행동안에 slave 쓰레드는 다음 PARALLEL 작업 대기와 PARALLEL 작업 수행 이 교차되는 시기에 런타임 루틴 slave_startup_function 을 실행합니다. PARALLEL 작업을 기다리는 동안 slave 쓰레드는 교체되거나 sleep 하고 있을 수 있습니다. 이러한 행동들은 환경변수SUNW_MP_THR_IDLE 를 설정함으로써 조정될 수 있습니다. 쓰레드가 작업을 끝내면 장벽 루틴 __mt_EndOfTask_Barrier_ 호출틀 통해서 마스터 쓰레드 및 다른 쓰레드와 동기화 합니다. 일반적인 slave_startup_function 의 로직은 Figure 5 에서 나타납니다.

OpenMP 는 PARALLEL 구역이 서로 중첩될 수 있도록 허용합니다. 런타임 라이브러리 libmtsk 는 중첩된 병렬화를 지원 합니다. 만약 중첩된 병렬화가 환경변수 OMP_NESTED 에 의해 활성화 되었거나 omp_set_nested 를 호출함으로써 활성화 되었다면 중첩된 PARALLEL 구역은 팀에 의해 하나 이상의 쓰레드에 의해 실행 됩니다.

추가적으로 런타임 라이브러리 libmtsk 는 복수유저 쓰레드를 지원합니다. 만약 유저 프로그램이 명시적으로 POSIX 쓰레드(libpthread)를 혹은 솔라리스 OS 쓰레드 라이브러리(libthread)를 호출 함으로써 쓰레드화 된다면 libmtsk 는 각 유저 프로그램 쓰레드들을 마스터 쓰레드로 취급하고 각각에 slave 쓰레드들을 제공합니다.

Figure 4


툴 지원

썬 스튜디오 어플리케이션 개발 스윗은 OpenMP 프로그래밍을 지원하고 용이하게 도와주는 다양한 툴들을 제공합니다. 이러한 툴들은 프로그래머가 OpenmP 를 이용해서 프로그램을 병렬화 하는데 도움을 주는 툴 뿐만 아니라 OpenMP 프로그램을 검사하고 디버깅하고 퍼포먼스 분석을 할 수 있는 툴들도 포함하고 있습니다. 아래에 이러한 툴들을 설명하고 있습니다.

변수의 자동 범위화

OpenMP 프로그램 작성시 변수의 범위를 직접적으로 지정하는 것은 지루하고 오류가 발생하기 쉬운 작업입니다. 생산성을 향상시키기 위해 자동범위화 기능이 썬스튜디오 컴파일러에 썬-특수한 OpenMP 확장으로 구현되어 있습니다. 썬 스튜디오 컴파일러는 현재 이러한 기능을 지원하는 유일한 상용 컴파일러 입니다.

자동범위화 기능은 Optimizer 의 분석 기능과 같이 사용되어 변수의 적절한 범위를 결정하게 됩니다. 프로그래머는 주어진 PARALLEL 구문에서 어떠한 변수가 자동으로 범위지정이 Optimizer 에 의해 되어야 할지 지정해 줘야 합니다. Optimizer 는 이러한 변수들의 적절한 범위를 프로그램을 분석함으로써 결정하고 자동범위 규칙을 적용합니다. 범위 결과는 소스코드에 컴파일러 주석 형태로 나타나게 됩니다. 이러한 자동 범위화 기능은 자동, 수동적 병렬화 사이에서 매우 매력적인 타협점을 제시 합니다.

더 자세한 정보는 참고자료[7]을 참고하시기 바랍니다.

정적인 에러 검사

컴파일러 옵션 -vpara  (포트란) 혹은 -xvpara (C) 를 통해서 컴파일러는 다양한 정적 에러를 체크할 수 있습니다. 이러한 작업은 부적절한 OpenMP 구문 중첩, 변수의 잘못된 범위화, race condition 등등을 포함합니다.

추가적으로 컴파일러 옵션 -XlistMP 를 통해 포트란 컴파일러는 프로그램을 글로벌(inter-procedural) 하게 분석하고 코드 내의 불완전하고 문제를 유발할 수 있는 부분을 보고해 줍니다. 프로그램 보고에는 잘못된 OpenMP 지시자 사용, 정렬 에러, 프로시저 매개변수의 갯수 불일치 혹은 타잎 불일치 등을 포함합니다.

런타임 에러 검사

만약 환경변수SUNW_MP_WARN 가 TRUE 로 설정되었다면 런타임 라이브러리 libmtsk 는 프로그램의 다양한 런타임 에러를 검사 합니다. 보고되는 문제들은 OpenMP 스펙을 위반하는 구문 에러, 잘못된 OpenMP 구문 중첩, OpenMP 지시자 사용의 불일치성, 잘못된 chunk 사이즈, 장벽에서의 데드락 등을 포함합니다.

OpenMP 디버깅

썬 스튜디오의 dbx 가 C, C++, 포트란 OpenMP 프로그램을 디버깅 하는데 사용될 수 있습니다. OpenMP 프로그램은 일단 -xopenmp=noopt -g 옵션에 의해 컴파일되어져서 dbx 에 의해 디버깅될 준비가 되어 있어야 합니다.

쓰레드에서 동작하는 dbx 의 모든 커맨드들은 OpenMP 디버깅에 사용될 수 있습니다 dbx 는 사용자에게 PARALLEL 구역에서 한단계식 검사 할 수 있고, OpenMP 구문내에 브레이크포인트를 설정할 수 있고 또한 SHARED, PRIVATE, THREADPRIVATE 의 값을 출력할 수 있고 주어진 쓰레드의 변수를 볼 수 있습니다.

퍼포먼스 분석

Collector 와 Performance Analyzer 참고자료[8] 은 썬 스튜디오의 툴로써 어플리케이션의 퍼포먼스 데이타를 수집하고 분석하는데 사용할 수 있습니다. 두개의 툴 모드 커맨드 라인 혹은 GUI 형태로 사용할 수 있습니다.

Collector 툴은 프로파일링이이라고 불리는 통계적인 방법과 함수의 호출을 통해서 퍼포먼스 데이타를 수집합니다.데이타는 콜-스택, 정밀(microstate) 계정 정보, 쓰레드 동기화 지연 데이타, 오버플로우 데이타의 하드웨어 카운터, 메모리 할당 데이타 그리고 운영체제와 프로세스의 요약정보등을 포함합니다.

Performance Analyzer 는 Collector 에 의해 저장된 데이타를 처리 하고 프로그램 수준, 함수 수준, 호출자-피호출자 수준, 소스-라인 수준 그리고 어셈블리 명령어 수준의 다양한 퍼포먼스 수치를 보여 줍니다. Performance Analyzer 는 또한 그래픽 포맷 형식으로 raw 데이타를 보여줄 수도 있습니다.

Performance Analyzer 는 OpenMP 프로그램의 퍼포먼스를 두개의 모드로 보여 줍니다: 유저 모드 혹은 머신 모드

유저모드에서 Performance Analyzer 는 사용자가 프로그램을 직관적으로 이해할 수 있도록 하는 프로파일 데이타를 제공 합니다. 이 모드에서 마스터 쓰레드와 slave 쓰레드 콜-스택은 서로 중재되고 OpenMP 런타임 라이브러리 특정 작업을 수행할때 콜스택에 인공적인 함수 형태의 이름이 추가됩니다.

머신 모드에서 Performance Analyzer 는 콜-스택을 어떠한 변환과 인공적인 함수 생성 없이 제공하고 따라서 런타임 라이브러리 libmtsk 의 런타임 상세 정보를 노출 시킵니다.

컴파일러 커멘터리

컴파일러 커멘터리는 사용자에게 컴파일러에 의해 소스코드에 적용된 다양한 최적화와 코드 변환에 대한 정보를 주석형태로 보여 줍니다. 컴파일러 커멘터리를 생성하려면 프로그램은 반드시 -g 로 컴파일 되어야 합니다. 컴파일러 커멘터리는 Performance Analyzer 혹은 커맨드라인 유틸리티 er_src 를 통해서 볼 수 있습니다.

OpenMP 퍼포먼스


SPEC OMP2001 는 소프트웨어 벤치마크 프로그램으로 Standard Performance Evaluation Corporation (SPEC) 의 High-Performance Group (HPG) 에서 만들었습니다. 벤치마크는 OpenMP 에 의해 병렬화된 실제 과학적이고 엔지니어링 적인 프로그램의 퍼포먼스를 측정하도록 디자인 되었습니다. 그리고 이러한 프로그램들은 각각 화학, 기계 공학, 날씨 예측, 그리고 물리등의 분야에서 대표적인 고성능 테크니컬 컴퓨팅 어플리케이션들입니다.

SPEC OMP2001 벤치마크는 두개의 스윗을 포함하고 있습니다. 첫번째 스윗은 SPEC OMPM2001 로 중간 크기의 데이타 셋을 사용하고 4개에서 32개의 프로세서를 가진 공유 메모리 시스템의 퍼포먼스를 측정할 수 있도록 디자인 되었습니다. 두번쨰 스윗은 SPEC OMPL2001 로 대용량의 데이타 셋을 사용하고 많은 수의 프로세서를 가진 시스템의 퍼포먼스를 측정할때 사용 됩니다.

Name Application Area Language
311.wupwise Quantum chromodynamics Fortran
313.swim Shallow water modeling Fortran
315.mgrid Multi-grid solver Fortran
317.applu Partial differential  equations Fortran
321.equake Earthquake modeling C
325.apsi Air pollutants Fortran
327.gafort Genetic algorithm Fortran
329.fma3d Crash simulation Fortran
331.art Neural network simulation C
318.galgel Fluid dynamics analysis Fortran
332.ammp Computational chemistry C

Table 1: Applications in the SPEC OMP2001 Benchmark


SPEC OMP2001 벤치마크는 썬 시스템의 우수한 확장성 및 퍼포먼스를 보여 줍니다. Figure 6 은 울트라SPARC III Cu 프로세서를 가지고 있는 썬 파이어 6800 에서 SPEC OMPL2001 스윗(기본 퍼포먼스) 의 확장성을 보여주고 있습니다. Figure 7 은 울트라SPARC III Cu 프로세서를 가지고 있는 썬 파이어 15K 에서 SPEC OMPL2001 스윗(기본 퍼포먼스)의 확장성을 보여주고 있습니다.

썬 마이크로시스템즈는 SPEC OMP2001 벤치마크 결과로 여러개의 퍼포먼스 세계 기록을 발표 하였습니다:
  • 2003년 6월 썬 마이크로시스템즈는 72개의 울트라SPARC III Cu 프로세서로 구성된 썬 파이어 15K 서버에서 SPEC OMPL 2001 스윗(peak 퍼포먼스) 세계 최고 기록을 발표 했습니다. 썬 파이어 15K 서버는 200,000 점을 넘은 최초의 서버 입니다.(213,466점 획득)
  • 2004년 2월 썬 마이크로시스템즈는 72개의 울트라SPARC IV 프로세서를 가진 썬 파이어 E25K 서버에서 SPEC OMPL2001 스윗(peak 퍼포먼스) 의 새로운 세계 기록 수립을 이루어 냈습니다. 썬 파이어 E25K 시스템은 SPEC OMPL2001 peak 퍼포먼스 에서 316,182 점을 기록했습니다.
  • 2005년 3월 썬 마이크로시스템즈는 2개, 4개 쓰레드 카테고리에서 각각 새로운 세계 기록을 수립했습니다. 4 CPU 를 가진 썬 파이어 V40z 에서의 peak 결과 스코어 12,434 점은 다른 상용 컴파일러의 성능을 43 퍼센트 이상 앞질렀습니다.
자세한 SPEC OMP2001 벤치마크 결과는 참고자료 [10] 을 참고하시기 바랍니다.

 Figure 6
Figure 6: Scaling of OMPL2001 (Base) on Sun Fire 6800

Figure 7
Figure 7: Scaling of OMPL2001 (Base) on Sun Fire 15K

향후 발전 방향


썬 마이크로시스템즈는 세계적인 수준의 고품질 OpenMP 지원을 컴파일러와 툴내에서 지원하도록 계속적으로 노력하고 있습니다. 현재 그리고 미래의 프로젝트는 다음을 포함합니다:
  • 새로운 OpenMP 기능. 썬은 OpenMP 스펙의 변화에 따르고 그 진화 과정에서 활동적인 역활을 담당하고 있습니다.
  • OpenMP-특수한 최적화를 통한 퍼포먼스 향상. 이것은 컴파일러 최적화, 즉 불필요한 장벽의 제거와 런타임 라이브러리의 최적화를 통한 병렬화 오버헤드 감소같은 작업을 뜻합니다.
  • 향상된 툴 지원.  썬 마이크로시스템즈는 프로그래머들이 OpenMP 프로그램을 작성하고 디버깅하고 퍼포먼스 분석을 할 수 있는 툴에 계속적으로 투자를 하고 있습니다. 이러한 툴들은 OpenMP 프로그램을 위한 향상된 자동 범위 계산, race condition 감지, 프로그래머가 어플리케이션을 병렬화 할때 도움을 주는 동적인 툴들을 포함하고 있습니다.
  • 아키텍쳐 지원. 썬은 OpenMP 구현의 퍼포먼스를 계속해서 향상시켜 나가고 있습니다. 이 분야의 작업은 Non-Uniform Memory Access (NUMA) 머신과 Chip Multi-threading(CMT) 아키텍쳐에서의 성능향상을 포함합니다.

참고자료


1. OpenMP Specification,  http://www.openmp.org/drupal/node/view/8
2. OpenMP Architecture Review Board, http://www.openmp.org/
3. Sun Studio Software, http://www.sun.com/software/products/studio/index.html
4. Sun Studio 11 OpenMP API User's Guide, http://docs.sun.com/doc/819-3694
5. Sun Fire E25K server, http://www.sun.com/servers/highend/sunf ··· ndex.xml
6. The SPEC OMP benchmark suite,  http://www.spec.org/omp
7. Yuan Lin, Christian Terboven, Dieter an Mey, and Nawal Copty, “Automatic Scoping of Variables in Parallel Regions of an OpenMP Program”, WOMPAT 2004. (PDF)
8.Sun Studio 11: Performance Analyzer, http:/docs.sun.com/app/docs/doc/819-3687
9. Myungho Lee, Brian Whitney, and Nawal Copty, “Performance and Scalability of OpenMP Programs on the Sun Fire E25K Throughput Computing Server”, WOMPAT 2004.
10. SPEC OMP2001 benchmarks results, http://www.spec.org/omp/results

부록 A.1: Parallel 지시자 예제


다음의 코드는 간단한 "Hello World " 프로그램에 PARALLEL 지시자를 쓴 예제 입니다.   사용될 쓰레드의 갯수는 OpenMP 런타임 라이브러리 루틴 omp_set_num_threads 호출을 통해 지정 됩니다. 동적인 쓰레드 갯수의 조정은 omp_set_dynamic 루틴에 의해 비활성화 되었습니다.

프로그램의 초기 쓰레드는 PARALLEL 구문을 만나기 전까지 순차적으로 실행 됩니다. PARALLEL 구문을 만나면 초기 쓰레드는 10개의 쓰레드로 이루어진 팀을 생성합니다. 팀은 초기 쓰레드 자신(마스터)과 9개의 다른 쓰레드(slave 쓰레드) 로 구성되어 집니다. 팀내의 모든 쓰레드들은 PARALLEL 구문에 의해 둘러 쌓여져 있는 코드들을 동시에 실행합니다. 쓰레드가 PARALLEL 구문의 마지막에 도착 하면 구문의 제일 마지막에 암시적으로 존재하는 장벽에서 대기하게 되빈다. 모든 쓰레드가 해당 장벽에 도달하게 되면 오직 마스터 쓰레드 만이 PARALLEL 구문 이후의 코드들을 계속해서 실행합니다.

포트란 – PARALLEL 지시자 예제:
       PROGRAM HELLO
USE OMP_LIB
INTEGER TID
CALL OMP_SET_DYNAMIC (.FALSE.)
CALL OMP_SET_NUM_THREADS (10)
!$OMP PARALLEL PRIVATE (TID)
! Obtain thread ID.
TID = OMP_GET_THREAD_NUM()
! Print thread ID.
PRINT *, 'Hello World from thread = ', TID
!$OMP END PARALLEL
END

C/C++ – PARALLEL 지시자 예제:
#include <stdio.h>
#include <omp.h>
int main(void)
{
int tid; omp_set_dynamic(0);
omp_set_num_threads(10);
#pragma omp parallel private(tid)
{
/* Obtain thread ID. */
tid = omp_get_thread_num();
/* Print thread ID. */
printf ("Hello World from thread = %d\n", tid);
}
}

부록 A.2: DO/for 지시자 예제


아래의 예제 프로그램은 DO/for 지시자를 사용한 예제 프로그램 입니다. 프로그램의 초기 쓰레드는 PARALLEL 구문을 만날때 까지 순차적으로 실행 됩니다. PARALLEL 구문을 만나면 초기 쓰레드는 20개의 쓰레드로 이루어진 팀을 생성합니다. 팀은 초기 쓰레드 자신(마스터)과 19개의 다른 쓰레드(slave 쓰레드) 로 이루어 집니다. 팀 내의 모든 쓰레드는 PARALLEL 구문으로 막혀진 코드를 동시에 실행 합니다.

팀내의 쓰레드가 DO/for 구문을 만나면 100 개의 루프가 각각 20개의 쓰레드에 나뉘어지게 됩니다. 그러므로 각 쓰레드는 5번의 루프 반복을 처리하게 됩니다. 쓰레드는 그들의 반복실행문을 서로 동시에 실행합니다. 쓰레드가 작업을 마치면 DO/for 루프 제일 마지막에 암묵적으로 존재하는 장벽에서 대기 하게 됩니다. 모든 쓰레드가 해당구역에 도달하면 쓰레드는 계속해서 PARALLEL 구역 코드를 실행하게 됩니다.

포트란 – DO 지시자 예제:
       PROGRAM VECTOR_ADD
USE OMP_LIB
PARAMETER (N=100)
INTEGER N, I
REAL A(N), B(N), C(N)
CALL OMP_SET_DYNAMIC (.FALSE.)
CALL OMP_SET_NUM_THREADS (20)
! Initialize arrays A and B.
DO I = 1, N
A(I) = I * 1.0
B(I) = I * 2.0
ENDDO
! Compute values of array C in parallel.
!$OMP PARALLEL SHARED(A, B, C), PRIVATE(I)
!$OMP DO
DO I = 1, N
C(I) = A(I) + B(I)
ENDDO
!$OMP END PARALLEL
PRINT *, C(10)
END

C/C++ – 지시자 예제:
#include <stdio.h>
#include <omp.h>
#define N 100
int main(void)
{
float a[N], b[N], c[N];
int i;
omp_set_dynamic(0);
omp_set_num_threads(20);
/* Initialize arrays a and b. */
for (i = 0; i < N; i++)
{
a[i] = i * 1.0;
b[i] = i * 2.0;
}
/* Compute values of array c in parallel. */
#pragma omp parallel shared(a, b, c) private(i)
{
#pragma omp for
for (i = 0; i < N; i++)
c[i] = a[i] + b[i];
}
printf ("%f\n", c[10]);
}

부록 A.3: Parallel Sections 예제


다음의 예제 프로그램에서 SECTIONS 는 3개의 코드에 적용 되었습니다. 프로그램의 초기 쓰레드는 PARALLEL 구문을 만날때 까지 순차적으로 실행을 진행합니다. PARALLEL 구문을 만나 게 되면 초기 쓰레드는 3개의 쓰레드를 갖는 팀을 생성합니다. 팀은 초기 쓰레드 자체(마스터 쓰레드) 와 2개의 다른 쓰레드(slave 쓰레드) 로 이루어지게 됩니다. 팀 내의 모든 쓰레드는 PARALLEL 구문 으로 막혀 있는 코드들을 동시에 실행 합니다.

팀내의 쓰레드가 SECTIONS 구문을 만나면 3개의 섹션은 3개의 쓰레드에 서로 나누어 집니다. 각 섹션은 오직 팀내에 하나의 쓰레드에 의해서만 실행 됩니다. 쓰레드가 작업을 마치면 SECTIONS 구문의 제일 마지막에 암시적으로 존재하는 장벽에서 대기 합니다. 모든 쓰레드가 장벽에 도달하면 쓰레드는 계속해서 PARALLEL 구역 코드를 실행하게 됩니다.

포트란 – SECTIONS 지시자 예제:
       PROGRAM SECTIONS
USE OMP_LIB
INTEGER SQUARE
INTEGER X, Y, Z, XS, YS, ZS
CALL OMP_SET_DYNAMIC (.FALSE.)
CALL OMP_SET_NUM_THREADS (3)
X = 2
Y = 3
Z = 5
!$OMP PARALLEL
!$OMP SECTIONS
!$OMP SECTION
XS = SQUARE(X)
PRINT *, "ID = ", OMP_GET_THREAD_NUM(), "XS =", XS
!$OMP SECTION
YS = SQUARE(Y)
PRINT *, "ID = ", OMP_GET_THREAD_NUM(), "YS =", YS
!$OMP SECTION
ZS = SQUARE(Z)
PRINT *, "ID = ", OMP_GET_THREAD_NUM(), "ZS =", ZS
!$OMP END SECTIONS
!$OMP END PARALLEL
END
INTEGER FUNCTION SQUARE(N)
INTEGER N
SQUARE = N*N
END

C/C++ – SECTIONS 지시자 예제:
#include <stdio.h>
#include <omp.h>
int square(int n);
int main(void)
{
int x, y, z, xs, ys, zs;
omp_set_dynamic(0);
omp_set_num_threads(3);
x = 2;
y = 3;
z = 5;
#pragma omp parallel
{
#pragma omp sections
{
#pragma omp section
{
xs = square(x);
printf ("id = %d, xs = %d\n", omp_get_thread_num(), xs);
}
#pragma omp section
{
ys = square(y);
printf ("id = %d, ys = %d\n", omp_get_thread_num(), ys);
}
#pragma omp section
{
zs = square(z);
printf ("id = %d, zs = %d\n", omp_get_thread_num(), zs);
}
}
}
}
int square(int n)
{
return n*n;
}









이 컨텐츠의 영문 원본 :
http://developers.sun.com/sunstudio/art ··· nmp.html










2007/08/20 10:17 2007/08/20 10:17

TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/417

  1. 썬스튜디오 컴파일러의 OpenMP 지원

    Tracked from ★ dingpong의 조그만 휴식 공간 ★  삭제

    썬스튜디오 컴파일러의 OpenMP 지원에 대한 내용입니다. OpenMP 에 대한 내용을 들은 적이 있습니다. 아직 일반 사람들에게는 잘 안알려진 내용인데 그것은 요즘 유행하는 듀얼 코어 이상의 CPU 에서 좀 더 효율적인 방법을 내는 프로그래밍 방법? 기법? 이라고 들었습니다. 자세한 내용은 몰랐는데 이렇게 강좌로 볼 수 있으니 좋은 것 같

    2007/09/19 23:59

댓글을 달아 주세요

  1. 한용현  수정/삭제  댓글쓰기

    좋은정보 감사해요...항상 고마워

    2007/09/06 09:48
  2. 김석원  수정/삭제  댓글쓰기

    조만간 Solaris로 작업할 일이 생겼는데 좋은 정보가 있었군요. 감사합니다~!

    2007/09/08 00:32
  3. 이상수  수정/삭제  댓글쓰기

    정보 감사합니다. 잘 보고 갑니다~

    2007/09/10 14:00
  4. 김문경  수정/삭제  댓글쓰기

    많이 배웠읍니다^^ 감사합니다

    2007/09/12 21:34
  5. 고진구  수정/삭제  댓글쓰기

    짬짬이 좋은 공부 하고 갑니다. 좋은 자료 많이 많이 올려주세요.

    2007/09/12 22:00
  6. 최하영  수정/삭제  댓글쓰기

    마침 필요한 내용이었는데 좋은 정보 감사합니다. ^^

    2007/09/13 10:50
  7. 권미자  수정/삭제  댓글쓰기

    하나하나 알아가는재미가 점점 생기네요..

    2007/09/15 19:05
  8. 고진구  수정/삭제  댓글쓰기

    항상 요긴한 정보로 도움을 많이 받고 있습니다. 자바 신기술 따라잡기에 썬 개발자 네트워크만큼 좋은 곳도 없나봅니다. 언제나 좋은 자료 감사합니다.

    2007/09/16 22:46
  9. 박정숙  수정/삭제  댓글쓰기

    좋은 정보 감사해요~

    2007/09/19 03:23
  10. 김덕경  수정/삭제  댓글쓰기

    좋은자료 많이 많이 올려주세요..감사

    2007/09/19 06:43
  11. 김광현  수정/삭제  댓글쓰기

    잘 활용할게요.
    항상 수고가 많으세요.

    2007/09/19 14:51
  12. 이종민  수정/삭제  댓글쓰기

    직접적인 개발자가 아니라서 정확한 세부사항까지 이해하기는 어려웠지만 나름 좋은 지식공유가 된것 같아서 기쁘네요... 앞으로도 좋은 지식발견이 되었으면 좋겠습니다. 감사합니다...!

    2007/09/19 21:09
  13. 진유라  수정/삭제  댓글쓰기

    유용한 정보 많네요.
    감사합니다.

    2007/09/19 22:38
  14. 최인균  수정/삭제  댓글쓰기

    OpenMP 에서 개발자 커뮤니티에서 언듯 들었던 기억이 나는데 여기에도 이렇게 있군요. 아직 널리 알려져 있지 않은 내용이라 사람들이 많이 모르고 있는 듯 싶습니다. 저도 잘 모르는데 열심히 공부해야겠습니다. 좀더 빠르고 효율적인 프로그램을 만들기 위해서^-^ 감사합니다.

    2007/09/20 00:00
[로그인][오픈아이디란?]

◀ Prev 1  ... 229 230 231 232 233 234 235 236 237  ... 626  Next ▶