|
Visual Studio 2005에는 Profile-guided optimization(PGO)이라는 기능이 추가되었다. 우리말로 의역을 하자면 "프로그램 실제 실행 결과를 이용한 최적화" 정도가 될 것이다.
컴퓨터 공학자들의 목표 중 가장 큰 것은 더 빠른 컴퓨터를 만드는 것. 그 중에서도 가장 밑 바닥에서 고생하는 사람들이 CPU와 컴파일러를 연구하는 사람들일 것이다. 프로그래머가 짠 코드를 그 원래 의도를 해치지 않는 범위 안에서 CPU와 컴파일러는 온갖 기교를 이용하여 속도 향상을 꾀한다. 프로그램 최적화는 CPU (동적) 그리고 컴파일러 (정적) 두 군데서 이루어진다. (1) CPU: 주어진 프로그램을 순서대로 차곡차곡 실행하는 (학부 컴퓨터 구조 시간에 배우는) CPU는 이제 박물관에서나 구경할 수 있다 (Itanium 같은 VLIW/EPIC CPU들은 순차적으로 수행을 하기도 함). 파이프라인으로 속도를 높이지만 여전히 in-order 즉, 순서대로 처리한다. 최근 CPU는 미리 수십개 혹은 백여개의 명령어를 미리 가져온 뒤, 그 안에서 최대한의 병렬성을 찾는다. 그런 뒤 이들을 최대한 동시에 실행을 시킨다. 수퍼스케일러, 하이퍼스레딩 같은 기술은 최대한 CPU의 각종 자원들을 놀리지 않고 바쁘게 돌려서 성능 향상을 꾀한다. (2) 컴파일러: 컴파일러 본연의 임무인 번역 외에 최근 컴파일러는 무척이나 많은 최적화를 수행한다. switch 문은 점프 테이블을 만들기도 하고, 사용하지 않는 변수는 알아서 다 제거, inline을 굳이 쓰지 않아도 코드의 양이 작다면 바로 inline을 해버리기도 하고, 함수 호출 관계를 그래프로 그려 더 고차원적인 최적화를 수행하기도 한다. CPU는 실시간으로 명령들을 수행하기 때문에 프로그램의 동적인 상태를 자연스럽게 알 수 있다. 어떤 프로그램은 입력 값에 따라 그 작동 상태가 사뭇 다를 수가 있다. 그러나 컴파일러는 단순히 소스 코드만 가지고 분석을 해야하기 때문에 이런 동적인 변수를 고려할 수 없다. 한편, CPU는 매우 짧은 시간에 매우 한정된 자원을 이용하여 최적화를 수행해야하지만 컴파일러는 그렇지 않다. 코드 전체를 다 볼 수도 있고 훨씬 긴 시간을 이용하여 정교한 알고리즘을 이용할 수 있다. 기존의 컴파일러 최적화가 정적인 분석을 하였다면, PGO를 지원하는 컴파일러는 실제 수행 결과를 기반으로 보다 더 풍부한 최적화를 할 수 있다. MS 홈페이지의 광고를 보면 아래와 같이 PGO 기능을 자랑하고 있다. ![]() 이 기능의 사용 방법은 MSDN을 참고하면 된다. 실제 사용법에 대해서 쓰려니 너무 길어질 것 같아서 간략하게 PGO가 가지는 의미만 이 포스팅에서 쓴다. 대략적인 원리는 특정 옵션을 켠 뒤 빌드를 새롭게 한다. 이 과정을 instrumentation라고 부르는데, 프로파일 정보를 얻기 위해 컴파일러가 부가적인 코드를 집어넣는 것을 뜻한다. 그리고 실제로 프로그램을 돌리면 .pgd 파일이 생성된다. 그리고 이제 이 파일을 가지고 컴파일러가 최적화를 할 수 있도록 다시 빌드를 한다. 이렇게 PGO를 이용하면 실제 실행 정보를 바탕으로 즉, 동적인 정보도 이용하여 보다 최적화된 코드를 만들 수 있다. MSVC 컴파일러가 .pgd를 가지고 수행하는 최적화 중 몇 개를 소개하면: (1) Virtual Call Speculation: 가상 함수 호출은 생각보다 비용이 비싸다. 왜냐면 어떤 주소로 점프를 해야할지 미리 알 수가 없다. 이 주소가 계산될 때 까지 일반적인 CPU는 일을 할 수 없다. 어디로 가야할지 모르기 때문이다. 일반적인 if/while 같은 분기문의 경우, 분기 예측으로 예측 실행을 할 수 있지만, 가상 함수와 같은 indirect branch는 branch table buffer를 이용하여 목적지까지 예측을 해야한다. 그런데, 만약 특정 가상 함수가 아주 많은 빈도로 불린다면? PGO는 이 정보를 얻어서, 자주 불리는 가상 함수가 바로 호출되도록 코드를 수정한다. 물론 아닐 경우는 다시 복구가 되도록 한다. 그래서 가상 함수 호출 비용을 줄일 수 있다. (2) Basic Block Optimization: 캐쉬 효율성을 높이기 위해 자주 실행되는 기본 블럭을 인접하게끔 배치되게 한다. 멀리 떨어져있는 코드가 빈번히 실행된다면 cache miss가 많이 발생되고 성능은 당연히 하락될 것이다. 실제 캐쉬 미스가 갑자기 증가하면 성능 하락은 상당히 심각하게 발생한다. 데이터를 배치할 때도, 자주 사용하는 자료구조는 같은 캐쉬 라인에 들어가게끔하는 것이 좋다. (물론 멀티 프로세서 환경에서는 false sharing이라는 골치아픈 경우가 벌어지기도 한다.) ... 쓰고보니 그냥 MSDN을 해석한 수준 밖에 되지 않군요. 아무쪼록 조금이라도 성능을 더 높이고 싶다면 PGO 기능을 적극 사용해보심이 어떨런지요.
최근 등록된 덧글
개발자 입장에서의 수많은 ..
by Jiyoon at 02/04 저도 아들 돌잔치때 돌잡이 .. by 박상욱 at 01/18 미국 대학원 원서 작성중에 p.. by 태클사이야 at 01/13 TO: 박PD 로그인 하지 않아.. by 박응용 at 01/10 http://gigglehd.com/zbx.. by dhunter at 12/28 우와.. 좋네요. 태반이 .. by 윤광배 at 12/17 항상 좋은 글 잘 보고 있습니.. by y2k at 11/23 글이 좋아서 제 블로그에 담.. by 쏭섭 at 11/23 최근 등록된 트랙백
메뉴릿
이글루 파인더
|