
이 글은 PGO(프로파일 기반 최적화)가 학습 작업의 실행 데이터를 이용해 프로그램의 기계어 배치를 어떻게 바꾸는지 설명한다. 핵심은 학습에 사용한 데이터 자체가 아니라 어떤 분기와 함수가 자주 실행되는지다.
이 글은 PGO를 다루는 3부작의 두 번째 편이다. PGO란 무엇인가와 sysbench로 학습한 빌드가 성능에서 뒤지는 이유와 올바른 적용법도 함께 소개한다.
PGO는 두 차례 빌드한다. 첫 번째 빌드는 -fprofile-generate로 계측 코드를 넣어 기본 블록과 분기마다 실행 횟수를 센다. 이 바이너리로 학습 작업을 실행하면 카운터 값이 profraw 파일에 저장된다. 두 번째 빌드는 이 값을 사용해 인라이닝, 분기 배치, 핫·콜드 코드 분리, 함수 순서, 루프 펼치기, 간접 호출 최적화 등을 결정한다.
계측은 함수별 호출 횟수만 기록하는 것이 아니다. 제어 흐름 그래프의 각 경로에 카운터를 두어 분기나 반복문의 각 경로가 얼마나 자주 실행됐는지 수집한다. 예를 들어 특정 분기에서 왼쪽 경로는 95만 번, 오른쪽 경로는 50번 실행됐다는 정보가 최적화에 쓰인다.
컴파일러는 이 프로파일을 바탕으로 정적인 추정만으로는 인라인하기 어렵다고 판단했을 호출도 실행 빈도가 높으면 인라인할 수 있다. 반대로 인라인이 가능하더라도 거의 실행되지 않는 코드라면 바이너리 크기만 늘 수 있어 실제 호출로 남겨둘 수 있다.
분기에서는 자주 실행되는 경로를 다음 명령어로 자연스럽게 이어지는 위치에 배치하고, 드문 경로는 별도 위치로 옮긴다. 분기 예측이 빗나가면 CPU가 이미 가져온 작업을 버리고 다시 시작해야 하므로 지연이 생길 수 있다. 핫 경로를 연속된 명령어로 구성하면 이런 비용을 줄이는 데 도움이 된다. 소스 코드에서 if와 else의 순서를 바꾸는 것만으로는 보통 결과가 달라지지 않는다. 최적화 컴파일러는 프로파일이나 자체 추정에 따라 기계어 배치를 정한다.
같은 원리는 함수 내부에도 적용된다. 자주 실행되는 핵심 코드와 드물게 실행되는 오류 처리 코드를 나눠, 핫 코드는 .text.hot, 콜드 코드는 .text.unlikely에 둘 수 있다. 핫 코드가 더 조밀해져 명령어 캐시에 들어가기 쉬워지고, 거의 실행되지 않는 코드가 핫 코드와 함께 캐시 공간을 차지하는 일을 줄인다.
링크 단계에서는 자주 함께 호출되거나 핫 작업에서 연이어 실행되는 함수들을 실행 파일 안에서 가깝게 배치할 수 있다. MySQL의 PGO 빌드는 LTO(링크 타임 최적화)를 활성화하며, 글은 mysqld처럼 규모가 큰 프로그램에서 이런 함수 재배치가 주요 이점이 될 수 있다고 설명한다. 일반 빌드는 소스 파일의 컴파일 순서에 따라 함수가 배치될 수 있지만, 그 순서가 실제 실행 패턴과 일치하지 않을 수 있다는 설명이다.
프로파일은 간접 호출도 최적화하는 데 쓰인다. 가상 함수나 함수 포인터 호출이 대부분 같은 대상을 가리키면, 컴파일러가 해당 대상인지 확인한 뒤 직접 호출하고 그렇지 않으면 기존 간접 호출을 쓰는 코드를 넣을 수 있다. 직접 호출은 간접 점프보다 비용이 낮고 분기 예측에도 유리할 수 있다.
프로파일에 따라 핫 코드는 속도를 우선해 더 적극적으로 루프를 펼치고 레지스터를 배정할 수 있다. -fprofile-partial-training과 콜드 경로 처리를 적용할 경우, 콜드 코드는 크기를 줄이는 방향으로 컴파일될 수 있다. 거의 실행되지 않는 코드라도 바이너리와 캐시 공간을 차지하므로, 글은 콜드 코드를 별도 영역에 두는 이유도 여기에 있다고 설명한다. 여러 분기를 가진 switch 문도 어떤 경우가 실제로 자주 선택되는지에 따라 점프 테이블이나 비교 연쇄 중 적절한 방식으로 컴파일할 수 있다.
따라서 PGO는 학습 작업을 빠르게 만드는 데 그치지 않고, 실행 파일에서 명령어와 함수의 배치, 직접·간접 호출 방식 등을 프로파일에 맞춰 바꾼다. 학습 데이터가 실제 운영 데이터와 같을 필요는 없지만, 자주 실행되는 분기와 경로의 형태는 운영 환경과 비슷해야 한다는 설명이다. 글은 MTR이 TPCC와 다른 쿼리와 데이터를 사용하더라도 mysqld의 거의 모든 코드 경로를 폭넓게 실행하기 때문에, PGO에 필요한 제어 흐름 정보를 제공할 수 있다고 주장한다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요