17-2-R02

SMT 멀티 프로세서 시스템을 위한

적응형 실행 기법

(Adaptive Execution Techniques for SMT Multiprocessor Systems)

정창희+․이재진*

+한국전자통신연구원 임베디드 소프트웨어 연구단

chjung@etri.re.kr

*서울대학교 컴퓨터 공학부

jlee@cse.snu.ac.kr

요  약

Simultaneous multithreading(SMT) 멀티 프로세서에서 루프를 병렬 수행하기 위해서 사용 가능한 모든 쓰레드들을 사용하는 것이 항상 좋은 성능을 가져오는 것은 아니다. 이는 쓰레드들 사이의 간섭(interference)과 병렬 수행의 오버헤드가 존재하기 때문이며, SMT 멀티 프로세서의 성능을 극대화하기 위해서는 최적의 쓰레드 개수를 찾는 것이 매우 중요하다. 본 논문은 SMT 멀티 프로세서를 위한 최적의 수행 모드를 찾아내는 적응형 실행 기법을 제시한다. 컴파일러 전처리기(pre프로세서)는 수행 중에 루프를 실행하는 최적의 쓰레드 개수를 자동으로 결정하는 코드를 생성하며, 이러한 결정은 실행 중에 얻어지는 피드백에 근거한다. 실험을 위해 8개의 논리적인 프로세서를 지원하는 4개의 Intel Hyper-Threading Xeon 프로세서들로 구성된 SMP 시스템을 사용했으며, 본 논문이 제시하는 방법을 10개의 대표적인 과학 수치계산 병렬 벤치마크 프로그램에 적용한 결과, 생성된 코드는 4, 8 개의 논리적인 프로세서에서 수행되는 원래의 코드보다 각각 평균적으로 2배, 18배 빠른 성능을 보였다.

1. 서  론

SMT 멀티 프로세서 시스템을 위한 적응형 실행 기법

프로그래밍언어논문지 제 18권 제 3 호 (2004. 11)

Simultaneous multithreading(SMT)[9, 18] 기술은 superscalar 프로세서로 하여금 동시에 다수의 쓰레드 문맥을 유지 할 수 있게 할 뿐 아니라 서로 다른 쓰레드들의 명령어들이 병렬적으로 수행 되도록 한다. SMT 프로세서는  내부 자원의 이용률을 증가시킴으로써 병렬 프로그램들의 성능을 향상시킬 수 있다. 그러나  일반적인 루프 레벨 병렬 프로그램에 의해 생성된 각 쓰레드들의 동일한 명령어 수행은 SMT 프로세서 내부 자원의 혼잡으로 인해 저조한 명령어 레벨 병렬성을 야기하며, 결국 전체적인 시스템의 성능 저하를 가져온다. 여러 SMT 프로세서들로 이루어진 멀티 프로세서 시스템의 경우에 동기화 명령어의 빈번한 수행은 쓰레드들의 혼잡을 더욱 심각하게 만든다. 게다가 SMT 프로세서에서는 캐쉬가 다른 쓰레드들 사이에서 공유되기 때문에 충돌을 야기하기 쉬우며 결국 낮은 적중률을 보인다. 결국 SMT 멀티 프로세서 시스템으로부터 타당한 성능을 얻기 위해서는, 프로그래머가 병렬 프로그램을 신중하고 세밀하게 조정할 수 있어야 하며, 하부 시스템에 대한 자세한 지식이 요구된다.

고성능 최적화 병렬 컴파일러는 순차적인 프로그램과 병렬 프로그램의 성능을 향상시키기 위해 다양한 최적화기법을 적용한다[2]. 문제를 해결하기 위한 알고리즘의 성능은 입력 데이터 와 그를 수행하는 하드웨어 플랫폼에 의존적이다. 입력 데이터와 플랫폼에 대한 정보는 컴파일 시간에 얻기가 힘들며, 때로는 불가능하다. 따라서 프로그램의 수행 전에  실행할 플랫폼을 고려하여 최적화하는 것은 거의 불가능하다. 이러한 문제에 대한 인식으로, 입력 데이터와 하드웨어 플랫폼에 관한 완벽한 정보가 알려질 때, 즉 수행 시간에 미세한 조정을 수행하고 최적화를 수행하는 연구가 시도되고 있다[1, 8, 16, 21, 25, 26].

병렬 컴파일러는 사용자의 어떠한 간섭도 요구하지 않고 자동으로 순차적인 프로그램을 분석하고 병렬 프로그램으로 변환한다. 그러나 자동으로 혹은 수동으로 병렬화된 프로그램의 성능을 극대화 시키기 위해, 사용자는 반드시 하부의 SMT 멀티 프로세서 시스템과 관련된 여러 가지 요소들을 충분히 고려해야 한다. 이러한 요소들로 프로그램에 포함되어 있는 병렬성의 정도, 프로그램의 캐쉬 지역성, 캐쉬 일관성 유지 방법, 작업 및 데이터 분배 방법, 잘못된 공유(false sharing), 쓰레드들 사이의 통신 및 동기화, 캐쉬 충돌, 프로세서 내부의 자원 혼잡 등 이 있다. 각 요소들은 성능에 있어서 상호 의존적으로 드러나고, 프로그램이 수행되는 하드웨어 시스템마다 다른 효과를 미치기 때문에, 프로그래머가 직접 병렬 프로그램의 성능 병목을 찾기란 매우 지루하고, 힘든 작업이다. 결국 병렬 프로그램을 개발하고 유지하는 노력 외에도, 타당한 성능을 얻기 위해서 프로그래머가 부담해야 하는 노력이 더해진다.

본 논문에서는  SMT 멀티 프로세서 시스템에서 동작하는 병렬 프로그램의 성능 병목을 수동으로 찾아내는 것이 아니라, 수행 중에 병렬 루프의 성능 저하가 미리 정해진 임계값을 초과하게 되면, 해당 루프를 순차적으로 수행하거나  병렬화에 참여하는 쓰레드의 개수를 최적으로 변경하여 실행한다. 이때 병렬 프로그램에 대한 프로그래머의 어떠한 지식도 요구되지 않으며, 본 논문이 제시하는 적응형 실행 기법은 SMT 멀티 프로세서 시스템에서 동작하는 병렬 프로그램의 성능을 비약적으로 증가시킨다.  컴파일러 전처리기는 수행 중에 프로그램의 각 병렬 루프를 실행하는 최적의 쓰레드  개수를  자동으로 결정하는 코드를 생성하며, 이러한 결정은 실행 중에 시스템이 제공하는 performance counter를 통하여 얻어지는 피드백에 근거한다.

실험을 위해 8개의 하드웨어 문맥을 지원하는 SMT 멀티 프로세서 시스템[18]( 4개의 Intel Hyper-Threading Xeon MP 프로세서들로 구성된 대칭형 멀티 프로세서 시스템)을 사용했으며, 본 논문이 제시하는 방법을 10개의 과학 수치계산 병렬 벤치마크 프로그램에 적용한 결과,  생성된 코드는 4, 8 논리적인 프로세서(쓰레드)에서 수행되는 원래의 코드보다 각각 평균적으로 2배, 18배 빠른 성능을 보임을 알 수 있다.

본 논문의 구성은 다음과 같다. 2장에서는 실험에 사용된 시스템과 병렬 프로그래밍과 수행 모델에 대해 소개하며, 3장에서 적응형 실행 기법을 제시한다. 4장에서는 실험 환경을 소개하고 5장은 제안된 기법을 평가한다. 6장에서는 관련 연구들에 대해서 검토하며, 마지막으로 7장에서 결론을 맺는다.

(그림 1) 목표 SMT 멀티 프로세서 시스템

2. 실험 환경과 동작 원리

그림 1은 실험에서 사용되는 SMT 멀티 프로세서 시스템을 나타낸다. 이는 4개의 SMT 프로세서를 포함하며, 각각은 두 개의 구조적 상태(architectual states-LP0, LP1)를 갖는다. 이와 같이 시스템은 8개의 논리적인 프로세서를 소유하는 것처럼 보인다. 각 물리적인 프로세서에는 L1, L2, L3 데이터 캐쉬들이 존재하며, 한 물리적인 프로세서에 속하는 두개의 논리적인 프로세서들에 의해서 공유된다.

본 논문은 병렬 수행 모델로써,　OpenMP 병렬 프로그래밍 모델을 사용한다. 이는 master-slave 쓰레드 모델[20, 6, 12, 30]로, 각 쓰레드는 수행 중에 시스템의 한 논리적인 프로세서에 할당된다.  쓰레드-프로세서의 사상(mapping)을 나타내기 위해서 mPnL의 표시법을 사용하기로 한다. m과 n은 각각 물리적인 프로세서와 논리적인 프로세서의 개수를 나타낸다. 그 외에도 n은 사용되는 모든 쓰레드들의 개수를 나타내기도 한다. 일례로, 2P2L은 두 개의 쓰레드들이 2개의 물리적인 프로세서에 사상되고, 각 쓰레드는 각 물리적인 프로세서의 LP0에 할당됨을 의미한다. 2P4L은 네 개의 쓰레드들이 2개의 물리적인 프로세서에 할당되고, 두 물리적인 프로세서의 논리적인 프로세서들과 쓰레드들 사이의 일대일 대응 관계가 성립함을 의미한다.  4P1L 수행 모드에서는 오직 하나의 쓰레드가 시스템의 한 논리적인 프로세서에서 수행된다. 즉, 병렬 루프가 순차적으로 수행된다는 것을 의미한다.

병렬 루프를 위한 slave 쓰레드들을 생성하는 것과, 쓰레드들 사이에 루프의 iteration을 분배하는 것, 그리고 루프의 끝에서 쓰레드들을 동기화하는 것은 루프를 병렬적으로 수행함에 있어서 오버헤드를 야기한다. 게다가 한 물리적인 프로세서안의 두 논리적인 프로세서들은 전체 캐쉬 계층과 다른 프로세서 내부 자원들을 공유하기 때문에, 이들 두 논리적인 프로세서 사이에는 캐쉬 충돌과 프로세서 내부 자원들에 대한 간섭(interference)이 존재한다. 본 논문에서는 이들을 SMT 멀티 프로세서 시스템에서의 병렬 루프 오버헤드라고 부른다.

그림 2는 본 논문이 제안하는 기법의 기본적인 동작 원리를 나타낸다. 자동 혹은 수동으로 병렬화된 프로그램들이  컴파일러 전처리기의 입력으로 들어가고, 전처리기는 목표 시스템에 특화된 파라미터들을 사용하여 성능 예측과 적응형 실행 코드를 병렬 프로그램에 삽입한다. 전처리기의 출력으로 나오는 코드는 SMT 멀티 프로세서 시스템을 위한 코드를 생성하는 일반적인 컴파일러로 컴파일된다.

(그림 2) 동작 원리

전처리기는 각 병렬 루프에 instrumentation 코드를 삽입하며, 이는 수행 중에 루프의 한 invocation동안에 수행 시간, 실행된 명령어 개수, 캐쉬 미스 개수를 측정하기 위함이다. Instrumentation 코드는 목표 프로세서의 performance counter를 사용하며, performance counter값들이 얻어지는  invocation을 decision run이라 부른다. Decision run에서 측정된 결과를 바탕으로, 적응형 실행 코드는 루프의 수행 방법을 결정하며, 이는 다음 혹은 남아있는 invocation동안에 4P1L, 4P4L 혹은 4P8L 모드로 수행될 것이다.

전처리기는 하나의 병렬 루프에 대해서 두 가지 다른 버전을 생성한다. 첫 번째는 4P1L 모드를 위한 순차적인 루프이며, 다른 것은  4P4L과 4P8L 모드들을 위한 병렬 루프이다. 4P4L과 4P8L사이의 수행 모드 전환은 동작하는 쓰레드의 개수를 변경하고, 시스템 콜을 이용해서 논리적인 프로세서에 대한 쓰레드 사상 관계(affinity)를 제어함으로써 이루어진다.

과학 수치계산 프로그램들 중에서 대부분의 병렬 루프들이 여러 번 수행되기 때문에, decision run을 이용하는 적응형 실행 기법은 현실적으로 타당하며, 상당히 효율적이다. 제안된 적응형 실행 기법의 단점은 decision run과 수행 중에 일어나는 instrumentation때문에 약간의 성능 저하를 겪어야 한다는 것이다.

3. 적응형 실행 기법

본 논문이 제안하는 적응형 실행 기법은 그림 3에서와 같이, 여러 가지 필터링 과정들로 이루어져있다. 먼저 정적 필터는 병렬 루프 오버헤드보다 적은 양의 계산량을 가지는 루프들을 걸러내는 것으로, 비용 예측 모델을 사용하여 컴파일 시간에 이루어진다. 프로그램상의 병렬 루프가 1보다 큰 속도증가율(순차실행시간/병렬실행시간)을 가지면, 효율적인 병렬 루프이며, 그렇지 못하면 비효율적인 병렬 루프이다. 첫 번째 필터는 컴파일 시간에 특별하게 비효율적인 병렬 루프들을 걸러내며, 이러한 루프들은 4P1L 모드로 수행된다. 다음으로 남아있는 루프들 중에서 4P4L과 4P8L 모드에서 효율적인 루프 들이 선택되며,  그 다음에 4P4L과 4P1L의 모드전환을 수행하기에 적당한 루프들이 선택되게 된다. 최종적으로 남아있는 루프들은 수행 환경에 따라서, 4P4L과 4P8L의 모드전환을 거치며

(그림 3) 적응형 실행기법

수행된다. 4P4L과 4P8L의 모드 전환에 대한 다른 대안으로, 비용 모델을 이용해서 4P8L 모드로 수행하기에 적당한 루프 들을 찾아 수행시킬 수 있다. 이 때 남아있는 루프들은 4P4L 모드로 수행된다.

3.1. 컴파일 시간 비용 예측

컴파일 시간 비용 예측 모델은 루프의 불충분한 계산량으로 인해 특별히 비효율적인 병렬 루프들을 식별한다. 이러한 루프가 가지고 있는 계산량의 병렬 루프 오버헤드에 비해서 상당히 작기 때문에, 이를 병렬적으로 수행하는 것은 이롭지 못하다. 따라서 루프안의 계산량에 대한 임계값을 정하고, 계산량이 임계값보다 작은 루프들을 4P1L 모드로 수행한다. (즉, 이와 같은 방법으로 식별된 루프는 오직 하나의 논리적인 프로세서에서 동작한다.) 본 논문은 간단한 비용 모델을 제시하며, 여러 가지 시스템 요소들의 사용 횟수들로 구성된 비용함수를 통해서 루프가 갖는 계산량(W)을 예측할  수  있다.  각 함수의 요소들은

반복(n), 할당(n), 실수 덧셈(nf), 실수 곱셈(nf), 실수 뺄셈(nf), 실수 나눗셈(nf), intrinsic 함수호출(nf), 시스템 함수호출(nf), 사용자 정의 함수호출(nf)의 사용횟수를 고려한다. 결국 한 반복(iteration)에서의 예측된 계산량(W)은 다음과 같은 식으로 주어진다.

(그림 4) 컴파일 시간 비용 예측 모델에서의 임계값 결정

W=n․c+nf․cf+nf․cf             + nf․cf+nf․cf+nf․cf

+ nf․ cf+nf․cf
위의 식에서 c는 와 관련된 하나의   operation을 수행하는데 요구되는 비용을 의미하며, 루프의 한 invocation동안의 전체 예측 비용은 다음과 같다.

W(n)=n․W

일반적으로 컴파일 시간에 루프의 정확한 반복횟수를 알 수 없기 때문에, 위의 식에 n 가 첨가된 것이다. 분기(branch)를 가지고 있는 루프가 갖는 계산량을 예측할 때는 각 분기에 동동한 비중을 실어준다. 임계값은 경험적으로 결정하며, 먼저 여러 종류의 병렬 루프들을 포함하는 다수의 대표적인 벤치마크 프로그램들을 실행시킨다. 다음으로 4P1L 모드에서의 순차 수행 시간(sequential execution time)과 4P4L 모드에서의 병렬 수행 시간(parallel execution time)을 측정한 후,  각 루프의 속도증가율과 예측된 cost를 x, y축으로 갖는 그래프를 그린다. 이를 토대로 최소 예측 비용을 갖는 점(그림 4의 p)에서 속도증가율이 1보다 크면서 예측 비용이 가장 작은 지점(p)까지 선을 긋게 되며, 이 선과 속도증가율이 1.0인 수평선이 교차하는 지점(p)을 임계값으로 정한다.

(그림 5) MPI를 이용한 임계값 결정

루프가 여러 겹으로 중첩되면, 외부 루프를 실행하기 전에 내부 루프의 반복 횟수를 쉽게 알 수 없다. 이는 내부 루프 count의 최대․최소 한계 및 step이 외부 루프에서 변하지 않는다는 보장이 없기 때문이다. 즉, 비용함수에 외부 루프와 내부 루프의 반복 횟수를  적용하기는 힘들다.  구하기는 어렵다. 이때는 단순히 그러한 루프를  수행시간 비용예측 단계로 넘긴다.

3.2. 수행시간 비용예측

수행시간 비용예측 모델은 수행 중에 결정되는 파라미터들 때문에 컴파일 시간에 다룰 수 없는 비효율적인 루프들을 처리한다.

루프에서 실행되는 명령어들의 수는 그 안에 존재하는 계산량에 비례하기 때문에, 병렬 루프의 첫 invocation에 수행되는(실행된) 명령어의 개수를 사용한다. Main 쓰레드로부터의 실행된 명령어의 개수는 그 루프가 4P4L 모드에서 수행될 때의 예측을 위해 사용된다. 이러한 모델이 효과적이기 위해서는 병렬 루프가 프로그램에서 최소한 한번 이상 수행되어야 한다. 예측된 비용이 임계값보다 작다면, 남아 있는 invocation동안에 그 루프를 4P1L 모드로 수행시킨다. 임계값은 경험적으로 결정되며, 결정하는 방법은 컴파일 시간 비용 예측 모델에서의 방법과 유사하다. 이러한 과정을 거치고 남아있는 루프들은 다음의 수행 모드 전환 단계로 진행된다.

3.3. 4P4L 과 4P8L의 수행 모드 전환

실행된 명령어를 사용한 수행 시간 filtering을 거치고 남아있는 병렬 루프들은 논리적인 프로세서(쓰레드)들 사이의 간섭과 캐쉬 충돌에 상당한 영향을 받는다.

이렇게 논리적인 프로세서들 사이의 캐쉬 충돌에 많은 영향을 받는 루프들을 식별하기 위해서, 캐쉬 미스 당 명령어 (MPI)를 기준으로 사용한다. 4P4L 모드에서 높은 MPI를 갖는 루프는 4P8L 모드에서도 높은 MPI를 갖기 쉬우며, 이는 4P8L 모드에서 각 쓰레드들이 갖게 되는 실제적인 캐쉬 용적이 4P4L에서의 반값이기 때문이다. 따라서 이러한 종류의 루프들을 4P8L 모드에서 수행시키는 것은 옳지 않다. 본 논문이 제안하는 기법은 먼저 각 루프의 첫 번째 invocation을 4P4L 모드로 수행하고  MPI를 측정한다. 측정된 MPI가 임계값보다 크면 남아있는 invocation동안에 4P4L 모드로 수행시킨다. 다시 임계값은 경험적으로 실행하는 것이다.

먼저 여러 종류의 병렬 루프들을 포함하는 다수의 대표적인 벤치마크 프로그램들을 실행시킨다. 벤치마크 프로그램의 각 루프들에 대해서, 4P4L과 4P8L 두 모드에서의 수행 시간과 캐쉬 미스 개수를 측정한 후, 각 루프의 속도증가율(4P4L실행시간/ 4P8L실행시간)과 측정된 MPI를 x, y축으로 갖는 그래프를 그린다. 이를 토대로 최소 속도증가율이 1.2보다 크면서 x축에서 가장 오른쪽에 있는 점(그림 5의 P)을 선택하며, 이 지점에서의 MPI 값이 임계값으로 사용된다. 곧  그림 5에서 P 의 오른쪽에 존재하는 루프들이 4P4L 모드의 후보가 된다.

그러나 이렇게 경험적 방법으로 결정된  루프들은 4P4L 모드에서 대부분 좋은 성능을 보이지만, 몇몇 루프들은 4P8L 모드에서 더 좋은 성능을 보이기도 한다. 이러한 루프들을 걸러내기 위해서  사이클 당 명령어(CPI)를 기준으로 사용한다. 4P8L 모드에서는 이미 언급한 것처럼 한 물리적인 프로세서 안에서 두 논리적인 프로세서가 동시에 각각의 명령어를 수행하기 때문에 발생하는 간섭이 존재한다. 따라서 CPI가 MPI와는 독립적인 요소일지라도, 이는 간섭의 좋은 척도가 된다. 즉, 논리적인 프로세서들 사이의 혼잡이 심할수록, 상대적으로 큰 CPI를 갖게 된다. 4P4L 모드에서  루프 의 CPI가 임계 CPI 값보다 작다면,  남아있는 invocation동안에 이를 4P8L 모드로 수행한다. 임계값을 얻는 방법은 MPI의 임계값을 결정하는 것과 유사하다.

이러한 과정을 거치고 남아있는 루프들은 다음의 적응형 실행 기법 단계로 진행되며, 이를 는 MRT(most recent with timing)라고 지칭한다.

3.4. Most Recent with Timing

(MRT)

병렬 루프는 첫 번째 invocation은 4P4L 모드로 수행되며, 이때에 실행된 명령어의 개수와 수행 시간이 측정된다. 실행된 명령어 개수에 따라 4P1L-4P4L MRT와 4P4L-4P8L MRT의 두 가지 적응형 실행 기법이 존재한다. 측정된 실행된 명령어의 개수가 이 임계값보다 작으면, 4P1L-4P4L MRT로 수행하고, 반대의 경우에는 4P4L-4P8L MRT로 수행한다. 임계값을 얻는 방법은 수행시간 비용예측 모델과 유사하며, 특히 워크로드가 루프의 각 invocation마다 변화하는 경우에 좋은 효과를 발휘한다. 이는 MRT 실행 기법이 미래의 행동을 예측하기 위해 가장 최근의 과거를 고려하기 때문으로, 루프의 워크로드가 점진적으로 변화한다면 이 방법은 효과적으로 동작하지만, 워크로드가 급작스럽게 변하는 루프의 경우에는 이 방법이 효과적이지 못하다. MRT 실행 기법의 단점은 각 루프의 decision run을 수행하기 위해 적어도 한번은 최적이 아닌 방법으로 실행해야 한다는 것이다.

3.4.1. 4P1L-4P4L MRT

이 적응형 실행 기법은 루프에 포함된 계산량은 작지만 순차적으로 실행해야 할 정도는 아닌 경우를 다룬다. 루프는 두 번째 invocation에서 순차적으로(4P1L) 수행되며,  다시 루프의 수행 시간이 측정된다.  측정된 두 결과 값들을 비교하여,  다음 invocation에 루프를 4P4L과 4P1L 중에서 어떠한 모드로 수행해야 할지를 결정한다. 이는 각 모드의 실행에서 측정되는 수행 시간에 근거하는 것으로, 이렇게 결정된 수행 모드가 남아있는 invocation동안에 고정되는 것이 아니다. 즉,  매번 루프가  실행 때마다 수행 시간을 측정하고 그를 가장 최근의 수행 시간과 비교한다. 이 때 측정한 값이 더 작다면  수행 모드를 바꾸게 된다.

3.4.2. 4P4L-4P8L MRT

이 경우에 우리는  루프가 충분한 양의 계산량을 갖고 있음을 알고 있지만, 4P8L 모드의 두 논리적인 프로세서들 사이에 존재하는 간섭의 정도는 알지 못한다. 이와 같이 루프는 두 번째 invocation에서 4P8L 모드로 수행되며, 다시 루프의 수행 시간이 측정된다. 측정된 두 결과 값들을 비교하여, 다음 invocation에 루프를  4P4L과 4P8L 중에서 어떠한 모드로 수행해야 할지를 결정한다. 이 후의 과정은 4P1L-4P4L MRT와 유사하다.

3.4.3. 4P8L 모드의 수행 시간 예측

병렬 루프의 수행 시간에 영향을 미치는 여러 가지 요소들이 존재한다. 이들 가운데서, 실행된 명령어s의 개수는 수행되는 동기화 명령어들에 비례한다. 이는 OpenMP가 삽입하는 암묵적인 barrier에서 busy waiting기반의 동기화가 이루어지기 때문이다. 즉, 실행된 명령어의 개수가 클수록, 수행된 동기화 명령어의 개수가 클 것이며, 결국 한 물리적인 프로세서 안에 존재하는 두 논리적인 프로세서들의 간섭은 더욱 심해진다. 게다가 L2 및 L3 캐쉬 미스는 4P8L 모드의 수행 시간에 상당한 영향을 끼치며, 이는 논리적인 프로세서들 사이에 발생하는 캐쉬 충돌에 기인한다. 그러므로 다음과 같은 식으로 병렬 루프의 수행 시간()을 예측할 수 있다.

위의 식에서 a, b, c, d는 각 항의 상수 계수를 나타내며 ,,는 각각 4P8L 모드에서의 실행된 명령어와 L2 캐쉬 미스 및 L3 캐쉬 미스의 횟수를 나타낸다.

게다가 4P8L 모드에서의 실행된 명령어와 L2 캐쉬 미스, 그리고 L3 캐쉬 미스의 횟수는 4P4L 모드에서의 그것과 비례한다. 즉, 아래와 같은 식이 가능하다.

따라서,

이후의 장에서 다루게 될 평가 과정에서, 위의 사실이 입증될 것이며, 또한 실험 data를 토대로 한 회귀 분석의 결과를 이용해서 상수 계수 , , ,  의 값이 얻어질 것이다. 이러한 모델을 사용하면, 4P4L 모드에서 얻어지는 정보들을 바탕으로 4P8L 모드에서 병렬 루프의 수행 시간을 예측할 수 있다. 이 방법은 4P4L-4P8L MRT의 대안으로, 결국 MRT 적응형 실행 코드 방법으로 인해 발생되는 성능 저하를 감소시킬 것이다.

4. 실험 환경

Compiler. 3장에서 묘사된 적응형 실행 알고리즘은 본 연구를 위해 특별히 제작된 컴파일러 전처리기에 구현되어 있다. 전처리기는 Perl로 만들어졌으며, 프로그램에 존재하는 병렬 루프들을 식별하기 위해 Polaris 병렬 컴파일러[2]를 사용했다. 병렬화를 위한 정보(OpenMP directive)들과 원래의 프로그램은 컴파일러 전처리기로 입력되며, 전처리기는 적응형 실행 코

(표 1) 실험에 사용한 벤치마크 프로그램

(표 2) 목표 시스템의 파라미터

드와 목표 SMT 멀티 프로세서 시스템의 컴파일러를 안내하기 위한 적당한 directive를 원래의 프로그램에 삽입한다. 전처리기로부터 출력되는 적응형 병렬 프로그램은 실행 이미지를 만들기 위해 인텔의 윈도우즈용 포트란 컴파일러 8.0[12, 13]을 이용해서 컴파일된다.

Performance counter의 값을 얻기 위해 Microsoft Windows 시스템 call[14, 3]을 사용하여 독자적인 performance counter를 구현했으며, instrumentation을 위하여 메인 쓰레드의 performance counter가  사용되었다. 또한 각 쓰레드의 affinity를 특정 논리적인 프로세서에 할당하기 위해  Microsoft Windows 시스템 call을 사용했다.

Applications. 본 논문에서 제안된 방법은 Fortran77로 쓰인 scientific 프로그램들을 이용하여  평가되었으며, 상당히 병렬적인 프로그램들을 선택했다. 표 1은 실험에 사용된 프로그램들의 문제 크기와 반복 횟수를 나타낸다.

목표 시스템. 제안된 시스템을 이용하여 생성되는 코드는 4개의 Intel Hyper-Threading Xeon 프로세서들로 구성된  SMP 시스템을 목표로 한다. 표 2는 목표 시스템의 파라미터를 보여준다.

5. 실험 결과

제안된 적응형 실행 기법을 평가하기 전에, 먼저 병렬 루프 오버헤드를 조사하고, 실험에 사용된 프로그램들의 병렬 루프에 대한 성격을 을 살펴본다(5장 2절). 그다음에 제안된 기법을 평가하기로 한다(5장 4절).

5.1. 병렬 루프 오버헤드

표 3은 각 수행 모드에서의 병렬 루프 오버헤드를 나타낸다. 이는 다음의 코드를 1000번 수행시키고 수행 시간과 실행된 명령어의 평균을 구한 것이다.

실험을 통해 1P2L 모드에서의 실행된 명령어의 개수가 2P2L 모드의 그것보다 급격하게 증가함을 알 수 있었고, 2P4L과 4P4L 모드에서도 마찬가지였다. 이러한 사실은 각 쓰레드들이 프로세서의 내부 자원들을 소비하기 때문에, 1P2L과 2P4L, 그리고 4P8L 모드의  명령어들이 쓰레드들 사이에 일어나는 간섭을 더욱 악화시키고 있음을 보여준다. 결국 간섭으로 인하여, barrier에서 좀더 많은 시간을 기다리게 되고 의미 없는 계산(computation)을 하면서 자원을 소비하게 된다. 이와 같이, 성능을 최대화하기 위해서는 병렬 루프의 적당한 수행 모드를 결정하는 것이 중요하다.

5.2. 병렬 루프의 특성

표 4는 각 프로그램들의 특성을 보여준다. 이는 적응형 실행 기법에 대한 통찰을 제공하며,  표는 크게 세 가지 부분적인 표들로 이루어져 있다. 그 첫 번째는 모든 병렬 루프들을 위한 것이며, 두 번째는 비효율적인 병렬 루프들을 다루고, 마지막 것은 4P1L대신 4P4L과 비교했을 때 4P8L 모드에서 효율적인 병렬 루프들을 대상으로 한다.

(표 3) 병렬 루프 오버헤드

(표 4) 병렬 루프의 특성

첫 번째 표에서 첫 번째 행은 각 프로그램의 병렬 루프의 개수를 보이며, 전체 프로그램에의 순차 수행시간에서 차지하는 비율(%)을 제시하고, 각 프로그램의 평균 invocation 횟수가 두 번째 행에 나타나있다. 두 번째 표에서 첫 번째 행은 4P4L과 4P8L 모드에서의 비효율적인 병렬 루프들의 invocation 횟수를 제시한다. 또한 전체 프로그램의 순차 수행에서 차지하는 비율을 보이고, 다음으로 전체 프로그램의 병렬 수행 시간에서 차지하는 비율(%)을 보여준다.  그다음 행은 각 수행 모드에서의 비효율적인 병렬 루프들의 평균 invocation 횟수를 제시한다. 마지막 표는 4P8L 모드에서의 효율적인 병렬 루프들에 대한 통계를 보여준다. 이 때, 속도증가율은 4P4L 모드에서의 수행 시간을 4P8L 모드에서의 수행 시간으로 나눈 값이다.

이를 통해 프로그램들이 상당히 병렬적이고, 각 병렬 루프들이 순차 수행 시간에서 평균 93.6%를 차지함을 알았다. APPLU, MGRID, HYDRO2D는 4P4L과 4P8L 모드에서 많은 비효율적인 병렬 루프들을 포함하며, 4P8L 모드에서 좀더 많은 비효율적인 병렬 루프가 존재한다. 이러한 루프들은 4P4L 모드에서 전체 병렬 수행 시간의 10%를 차지하고, 4P8L 모드에서는 30%를 차지한다. 그러나 이들의 순차 수행 시간에서의 비율은  기껏해야 8%를 넘지 못한다. 4P8L 모드로 수행될 때, 전체 프로그램의 병렬 수행 시간에서 비효율적인 병렬 루프가 차지하는 비율은 더욱 높아진다. 이러한 사실은 비효율적인 병렬 루프에 의해 발생하는 병렬 루프 오버헤드에 기인한다. 결국 비효율적인 병렬 루프들이 성능 최적화에 있어서의 좋은 목표가 됨을 확인할 수 있었다.

(표 5) 선형 회귀 분석의 결과

병렬 루프들의 평균 invocation 횟수는 71K로 여러 번 실행되고,  비효율적인 병렬 루프는 다른 병렬 루프들에 비해서 더욱더 많이 실행된다(4P4L과 4P8L에서 각각 132L, 97K). 이와 같이 decision run을 사용해서 이러한 루프들을 적응적으로 수행하는 것이 현실적으로 가능하며, 효과적이다.

병렬 루프의 약 20%는 4P4L 모드보다 4P8L 모드에서 보다 낳은 성능을 갖는다. 이와 같이 이러한 루프들을 걸러내고, 그들을 4P8L 모드에서 수행시키는 것은 가치 있는 일이며, 이는 4P4L 모드로부터 의 쓰레드 개수를 변경함에 의해서 이루어진다. 이 기법들은 3장 3절과 4절에서 언급되었다.

5.3. 회귀 분석

표 5는 3장 4절의 3번 째 섹션(3.4.3)에서 언급되었던 상수 계수를 보여주며, 실행된 명령어와 L2 및 L3 캐쉬 미스의 개수들 사이의 관계를 제시한다. 이들은 3.4.3에서의 4P1L-4P4L MRT 선택을 거친 후에, 남아 있는 루프들을 대상으로 회귀 분석을 통하여 실험적으로 얻어졌다. 이를 통해서 4P8L과 4P4L 모드에서의 실행된 명령어의 개수들 사이에 비례 관계가 성립함을 알았으며, 이는 L2 와 L3 캐쉬 미스에도 마찬가지이다. R 값이 1에 근접한다는 것은 제안된 4P8L 모드의 수행 시간 예측이 더욱 정확함을 의미한다. 이러한 예측은 4P4L 모드에서 얻어진 정보들을 바탕으로 하며 표 5의 마지막 행에 나타나있다.

5.4. 성능 평가

그림 6은 일련의 벤치마크 프로그램들에 본 논문이 제시한 기법들을 적용했을 때의 속도증가율(speedup)을 보여준다. 각 프로그램마다 7개의 막대가 존재한다. 가장 왼쪽의 막대(Sequential)는 프로그램이 4P1L 모드로 수행되는 경우를 의미한다. 두 번째(4P4L)와 세 번째(4P8L)는 각각 프로그램이 4P4L과 4P8L 모드로 수행되는 것을 경우를 의미하며,  네 번째(Static(4P4L))와 다섯 번째(Static(4P8L))는 컴파일 시간 비용예측 모델을 각각 4P4L과 4P8L 모드에서 적용한 경우를 나타낸다. 여섯 번째 막대(ADP)는 3장에서 제안된 적응형 실행 기법(그림 3에서 1,2,3,4,5,6의 과정)의 속도증가율을 나타내며, 마지막 막대(EST)는 3장에서 제안된 기법 중에서 4P8L 모드의 수행시간을 예측하는 기법(그림 3에서 1,2,3,4,5,6’의 과정)을 의미한다. 즉 이 기법은 MRT를 사용하는 것이 아니라, 4P4L 모드에서의 정보들을 토대로 4P8L 모드의 수행시간을 예측한다. 각각의 경우에서 속도증가율은 Sequential 모드의 수행 시간을 각 모드의 수행 시간으로 나눈 값이다. 이와 같이 높이가 큰 막대가 보다 좋은 성능을 갖는 것이다.

그림 6 Speedup

실험 결과를 통해서 4P4L의 성능이 4P8L을 월등히 능가함을 알았다. 이러한 사실은 SMT 멀티 프로세서 시스템에서 캐쉬 충돌 및 쓰레드들 사이에 발생하는 간섭이 성능 저하의 중요한 요소로 작용함을  시사한다. APPLU에는 계산량이 병렬 루프 오버헤드 보다 작은 루프들이 상당 수 존재하며, 결과적으로 4P4L과 4P8L에서 매우 저조한 성능을 보인다.

Static(4P4L)은 4P4L보다 좋은 성능을 보이며, Static(4P8L)은 APPLU, HYDRO2D, 그리고 MGRID에서 4P8L보다 좋은 성능을 보인다. 이러한 프로그램들은 계산량이 매우 작은 비효율적인 병렬 루프들을 포함하고 있으며, 따라서 우리의 병렬 루프 순차화 기법(컴파일 시간 비용 예측 모델)은 이들 프로그램에서 잘 동작한다. 그러나 이 기법은 남아있는 프로그램들에 대해서는 잘 동작하지 못하며, 이  때의 성능은 4P4L과 4P8L의 성능에 견줄만하다.

ADP와 EST는 모든 프로그램에서 4P4L과 4P8L을 능가하거나 그들과 비슷한 성능을 보인다. 이는 제안된 적응형 실행 기법들이 병렬 루프를 위한 최적의 수행 모드 결정에 있어서 잘 동작한다는 것을 의미한다.  EST는 HYDRO2D를 제외하고 대부분의 프로그램들에서 가장 좋은 성능을 보였다. HYDRO2D의 경우 ADP의 성능이 가장 좋은 성능을 보였다.  이는 EST에서의 Step 6’(그림 3참조)이 HYDRO2D에서는 정확하지 않기 때문이며, 이는 BT와 SP의 경우도 마찬가지다. Step 6’는 4P4L 모드에서의 decision run을 토대로 4P8L 모드에서의 성능을 예측한다.

1장에서 언급된 바와 같이, 프로그램 성능에 영향을 끼치는 요소들은 상호의존적이다. 3장에서 설명된 각 필터들은 각자의 고유한 기준에 따라서 조심스럽게(conservatively) 비효율적인 병렬 루프들을 걸러내며, 이때 남아있는 루프들은 다음의 필터로 넘겨지게 된다. 따라서 모든 필터들의 전체적인 성능은 상호의존적이다. 일례로 필터를 사용하지 않는 MRT의 성능은 필터를 사용한 경우보다 매우 저조한 성능을 보이며, 이러한 사실은 decision run의 오버헤드와 MRT 수행 기법에 불리한 워크로드 패턴에 기인한다. (그림 6에서 필터를 사용하지 않는 MRT의 성능을 보이지 않은 그의 성능이 매우 저조하기 때문이다.) 즉, 필터들은 MRT 수행에 적당한 루프들을 선택하며, ADP와 EST 성능의 발판이 된다.

Performance counter의 값을 읽기 위한 각 instrumentation 함수 호출에는 약 300 CPU cycle이 소요되며, 대부분 decision run에서 발생한다. 이러한 오버헤드는 우리의 적응형 실행 기법으로 인해 얻어지는 성능에 비교하면 거의 무시할 만 하다.

전체적으로 제안된 적응형 실행 코드는 평균적으로 4P4L과 4P8L 모드에서 수행되는 원래의 코드보다 각각 2배, 18배 빠른 결과를 보였다.

6. 관련 연구

최근에 여러 가지 적응형 최적화 기법들이 제안되었다. 몇몇 시도들[10, 23, 7, 22]은 코드가 수행 중에 재구성되도록 컴파일 시간의 변수화 기법(parameterization)을 사용했으며, 수행 중에 일어나는 루프 fusion과 루프 interchange 및 루프 reversal과 같은 루프의 변형 기법도 제안되었다[10]. 그리고 prefetching distance를 수행 중에 변경 할 수 있는 적응형 prefetching 알고리즘[23]이 소개되었으며, 이는 수행 중에 하드웨어 모니터를 이용해서 수집되는 간단한 performance data를 사용했다. 다른 적응형 최적화 기법은 객체 지향 프로그램에서의 객체 복사에 근거한다. 이 기법은 공유 객체에 대한 수정에 요구되는 동기화 오버헤드를 피하기 위해서 객체들이 적응적으로 복사된다[21]. 수행 시간 최적화를 위한 루프의 여러 가지 변형을 만드는 시도[4]가 있었으며, 현재의 컴파일러에서도 여전히 사용되는 기법이다. 이를 향상시키려는 다른 연구는 실행 중에 결정되는 피드백을 사용해서 객체 지향 프로그램을 위한 이상적인 동기화 최적화 정책을 자동으로 결정하기도 했다[8]. 또한 실행 중에 결정되는 타입 피드백 기법은 객체 지향 프로그램의 성능을 향상시켰으며, 수행 시간에 얻어지는 정보를 이용하여 주어진 환경에 동적으로 적응한다는 점에서 본 연구와 유사하다. 그러나 본 연구는 수행 중에 코드를 재구성 하거나 객체 지향 프로그램을 다루지 않으며, 루프 level parallelism을 가지는 공유 메모리 방식의 병렬 프로그램에 집중한다. 곧, SMT 멀티 프로세서 시스템에서의 성능을 향상을 위해, 본 논문에서는 실행 중에 얻어지는 피드백을 사용해서 각기 다른 적응형 실행 기법을 사용하며, 특별히 제안된 기법은 수행 중에 병렬화에 참여하는 쓰레드의 개수를 제어한다.

[15, 16]은 컴파일 시간 성능 예측과 몇 가지 경험적인 기준을 통해서, 작은 병렬 루프들을 순차적으로 수행시키는 기법을 제안했다. 그들은 또한 일반적인 SMP와 DSM(분산 공유 메모리) 시스템에서 수행되는 병렬 프로그램들을 위한 적응형 실행 기법을 제시했다. 그리고 stack distance[19]에 근거하는 복잡한 컴파일 시간 성능 예측 모델이 [5]에 정리되었다. 프로그램을 수행 중에 적응적으로 최적화하기 위하여, ADAPT라 불리는 컴파일러 frame계산량이 소개되었다. 사용자들은 최적화의  종류와 휴리스틱을 명시할 수 있으며, ADAPT 컴파일러는 명시된 휴리스틱을 읽어 들이고 그를 프로그램에 적용하는 방법으로 완벽한 수행 시간 시스템을 생성한다. [24]에서는 유익하지 않은 병렬 루프들을 식별하는 두 가지 수행 시간 테스트 방법이 제안되었다. 그들이 프로파일 기법과  병렬 루프의 첫 invocation에 측정되는 수행시간을 사용하기 때문에, 이 기법은 프로그램의 수행 동안에 부분적으로 적응적이다. 본 논문에서는 상대적으로 간단한 컴파일 시간(static) 성능 예측 모델을 사용했지만, 수행 시간 비용 모델은 static 모델의 부정확함을 보완하며, 제안된 기법은 프로그램이 실행하는 동안 완벽하게 적응적이다. 또한 본 논문이 제시하는 기법은 이종의 Processing-In-Memory 시스템을 위한 적응형 컴파일러와도 관련이 있으며, 이는 그러한 시스템을 구성하는 다른 종류의 구성 요소들이 적응적으로 이용되기 때문이다.

7. 결론

본 논문은 성능 예측 모델과 SMT 멀티 프로세서 시스템을 위한 적응형 실행 코드를 생성하는 기법을 제시했다. 적응형 실행 기법은 수행 중에 결정되는 피드백과  decision run을 이용해서 최적의 쓰레드 개수를 결정한다. 적응형 기법과 성능 예측 모델들은 코드상에 존재하게 되며, 컴파일러 전처리기에 의해서 원래의 병렬 프로그램으로 삽입된다. 실험을 위해 8개의 논리적인 프로세서를 지원하는 4개의 Intel Hyper-Threading Xeon 프로세서로 구성된 SMP 시스템을 사용했으며, 본 논문이 제안하는 방법을 10개의 과학 수치 계산 병렬 벤치마크 프로그램에 적용한 결과, 생성된 코드는 4, 8 개의 논리적인 프로세서에서 수행되는 원래의 코드보다 각각 평균적으로 2배, 18배 빠른 성능을 보임을 알 수 있었다. 이러한 결과는 제안된 적응형 실행 코드 생성 기법이, SMT 멀티 프로세서 시스템에서 수행되는 병렬 프로그램의 성능을 향상시키는데 있어서 충분히 효과적임을 말해준다.

참 고 문 헌

[1] Bowen Alpern et al. The Jalapeno Virtual system. IBM systems Journal, 39(1):211–238, February 2000.

[2] William Blume, Ramon Doallo, Rudolf Eigenmann, John Grout, Jay Hoeflinger, Thomas Lawrence, Jaejin Lee, David Padua, Yunheung Paek, Bill Pottenger, Lawrence Rauchwerger, and Peng Tu. Parallel programming with Polaris. IEEE Computer, 29(12):78-82, December 1996.

[3] John Borozan. Microsoft Windows-Based Servers and Intel Hyper-Threading Technology. Microsoft Corporation, April 2002.

[4] Mark Byler, James Davies, Christopher Huson, Bruce Leasure, and Michael Wolfe. Multiple Version loops. In Proceedings of the International Conference on Parallel Processing (ICPP), pages 312-318, August 1987.

[5] Calin Cascaval, Luise DeRose, David A. Padua, and Daniel Reed. Compile-Time Based Performance Prediction. In Proceedings of the 12th   workshop on Languages and Compilers for Parallel Computing (LCPC), pages 365-379, August 1999.

[6] Rohit Chandra, Leo Dagum, Dave Kohr, Dror Maydan, Jeff McDonald, and Ramesh Manon. Parallel Programming in OpenMP. Morgan Kaufmann Publisher, 2001.

[7] Alan L. Cox and Robert. J. Fowler. Adaptive cache Coherency for Detecting Migratory Shared Data. In Proceedings of the 20th International Symposium on Computer system, pages 98-108, May 1993.

[8] Pedro Diniz and Martin Rinard. Dynamic Feedback: An Effective Technique for Adaptive Computing. In Proceedings of the ACM SIGPLAN Conference on Program Language Design and Implementation, pages 71-84, June 1997.

[9] Susan J. Eggers, Joel S. Elmer, Henry M. Levy, Jack  L.  Lo, Rebecca  L.  Stamm,   and Dean M. Tullsen. Simultaneous multi-

Threading: A platform for next-generation processors. IEEE Micro, 17(5):12-19, September/October 1997.

[10] Rajiv Gupta and Rastislav Bodik. Adaptive loop Transformations for Scientific Programs. In Proceedings of the IEEE Symposium on Parallel and Distributed Processing, pages 368-375, October 1995.

[11] Urs Holzle and David Ungar. Optimizing Dynamically-Dispatched Calls with Run-Time Type Feedback. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation(PLDI), pages 326-336, June 1994.

[12] Intel. Intel Fortran Compiler User's Guide, 2002.

[13] Intel. Intel Fortran Programmer's Reference Manual, 2002.

[14] Intel. IA-32 Intel system                                      Software Developer's Manual, 2004.

[15] Jaejin Lee. Compilation Techniques for Explicitly Parallel Programs. PhD thesis, Department of Computer Science, University of Illinois at Urbana-Champaign, October 1999. Department of Computer Science Technical Report UIUCDCS-R-99-2112.

[16] Jaejin Lee and H. D. K. Moonesinghe. Adaptively Increasing Performance and Scalability of Automatically Parallelized Programs. In Proceedings of the 15th workshop on Languages and Compilers for Parallel Computing (LCPC), July 2002.

[17] Jaejin Lee, Yan Solihin, and Josep Torrellas. Automatically Mapping Code in an Intelligent Memory system. In Proceedings of the 7th International Symposium on High Performance Computer system (HPCA), pages 121-132, January 2001.

[18] Deborah T. Marr, Frank Binns, David L. Hill, Glenn Hinton, David A. Kaufaty, J. Alan Miller, and Michael Upton. Hyper-Threading Technology system and Microsystem. Intel Technology Journal, 6(1), February 2002.

[19] R. L. Mattson, J. Gecsei, D. Slutz, and I. Traiger. Evaluation Techniques for Storage Hierarchies. IBM systems Journal, 9(2):78-117, December 1970.

[20] OpenMP Standard Board. OpenMP Fortran Interpretations, April 1999. Version 1.0.

[21] Martin Rinard and Pedro Diniz. Eliminating Synchronization Bottlenecks in Object Based Programs Using Adaptive Replication. In Proceedings of the ACM Internationale Conference on Supercomputing (ICS), pages 83-92, June 1999.

[22] Theodore H. Romer, Dennis Lee, Brian N. Bershad, and Bradley Chen. Dynamic Page Mapping Policies for Cache Conflict Resolution on Standard Hardware. In Proceedings of the 1st USENIX Symposium on Operating systems Design and Implementation, pages 255-266, November 1994.

[23] Rafael H. Saavedra and Daeyeon Park. Improving the Effectiveness of Software Prefetching with Adaptive Execution. In Proceedings of the Conference on Parallel Algorithms and Compilation Techniques, October 1996.

[24] Michael J. Voss and Rudolf Eigenmann. Reducing Parallel Overheads through Dynamic Serialization. In Proceedings of the International Parallel Processing Symposium, pages 88-92, April 1999.

[25] Michael J. Voss and Rudolf Eigenmann. ADAPT: Automated De-Coupled Adaptive Program Transformation. In Proceedings of the International Conference on Parallel Processing (ICPP), page 163, August 2000.

[26] Michael J. Voss and Rudolf Eigenmann. High-level Adaptive Program Optimization with ADAPT. In Proceedings of the ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming, pages 93-102, June 2001.

정 창 희

1999년~2003년 충남대학교 컴퓨	터공학과(학사)

2003년~2005년 서울대학교 컴퓨	터공학과 석사

2005년 ~ 현재 한국전자통신연구원 연구원

관심분야 : 컴파일러, 컴퓨터 구조, 병렬 처리

이 재 진

1986년~1991년 서울대학교 물              리학과(학사)

1993년~1995년  Stanford

University(석              사)

1995년~1999년  Univ. of Illinois at

Urbaba-Chanpaign(박사)

2002년~  현재  서울대학교 컴퓨터공학부 교수

관심분야 :  컴파일러, 내장형 시스템, 프로그래밍 언       어