이번 주 개발자 커뮤니티에서는 nvtop(GPU 상태를 보여주는 간단한 도구)의 수치를 믿지 못하겠다는 불만이 터져 나왔다. GPU 사용률이 90%라고 뜨는데 왜 실제 성능은 기대만큼 나오지 않는지, 정작 어디가 막혀 있는지 알 길이 없다는 갈증이 컸다. 단순히 퍼센트 하나로 표현되는 사용률 지표가 GPU 내부의 복잡한 자원 흐름을 전혀 반영하지 못한다는 점이 논쟁의 중심이었다.

Compute와 Memory SOL %의 실시간 측정

Utilyze(오픈소스 GPU 모니터링 도구)는 NVIDIA의 Nsight Perf SDK(GPU 성능 데이터를 추출하는 개발 도구)를 기반으로 설계되었다. 이 도구는 Compute SOL %(연산 성능 달성률)와 Memory SOL %(메모리 대역폭 달성률)라는 두 가지 핵심 지표를 실시간으로 출력한다. 분자는 텐서 코어(행렬 연산을 가속하는 핵심 장치)나 FP32/FP64/INT32 파이프라인(다양한 정밀도의 연산 경로) 같은 연산 엔진과 HBM(고대역폭 메모리)이나 L1, L2 캐시(데이터 임시 저장소) 같은 메모리 서브시스템의 실제 측정값이다. 분모는 하드웨어의 이론적 최대치인 SOL(Speed-of-Light) 값이다.

개발자가 화면에서 보는 수치 중 Compute SOL %가 지배적이라면 해당 워크로드는 연산 제한 상태인 compute-bound 상황이다. 반대로 Memory SOL %가 더 높다면 메모리 대역폭이 발목을 잡는 memory-bound 상황이며, 이때는 데이터 이동 경로를 최적화하는 것이 정답이다. 특히 H100 같은 고성능 GPU에서 이론적 최대치인 2,000 TFLOPS(초당 2,000조 번의 부동소수점 연산)나 3.4 TB/s(초당 3.4테라바이트 전송)의 메모리 대역폭은 물리적 한계일 뿐 실제 AI 워크로드가 도달할 수 없는 수치다.

Utilyze는 이를 해결하기 위해 Attainable SOL %(달성 가능한 최대 성능치)라는 개념을 도입했다. 커널 런칭 오버헤드(명령어 실행 준비 시간)나 스레드 동기화(작업 순서 맞추기) 과정에서 발생하는 손실을 인정하고, 모델 구조와 하드웨어 조합에서 나올 수 있는 현실적인 천장을 설정한 것이다. 현재의 SOL %와 Attainable SOL % 사이의 간격이 바로 개발자가 최적화를 통해 회복할 수 있는 성능 예산이 된다.

Nsight Compute의 오버헤드를 극복한 샘플링 방식

예전에는 성능 병목을 잡으려면 Nsight Compute(커널 단위 정밀 분석 도구)로 워크로드를 수십 번 재실행하며 데이터를 모아야 했다. 이 도구는 각 커널을 여러 번 다시 실행하는 리플레이 방식을 사용하기 때문에 실행 속도가 평소보다 10배에서 100배까지 느려진다. 실시간 트래픽이 흐르는 운영 환경에 적용하는 것은 사실상 불가능했다. Nsight Systems(실행 타임라인 기록 도구)는 속도 저하 문제는 없었지만, 정작 중요한 처리량 수치를 알려주지 않고 어떤 일이 일어났는지만 기록하는 수준에 그쳤다.

Utilyze는 커널을 재실행하는 대신 시간 윈도우별로 성능 카운터를 순환하며 샘플을 수집하고 이를 합산하는 롤링 샘플링 방식을 택했다. 이 덕분에 오버헤드가 거의 없으며, 실제 서비스가 돌아가고 있는 프로덕션 환경에서도 연속적인 측정이 가능하다. 성능 엔지니어들이 오프라인 디버깅을 위해 ncu(Nsight Compute의 약칭)나 Omniperf(AMD GPU용 성능 분석 도구)를 붙잡고 씨름하던 시간을 실시간 대시보드 확인으로 바꾼 셈이다.

개발자가 바로 체감하는 변화는 인프라 증설과 코드 최적화 사이의 의사결정 속도다. 예를 들어 120B 파라미터(모델의 매개변수 규모) 추론 환경에서 Compute SOL %가 30%인데 Attainable SOL %가 35%라면, 더 이상 튜닝할 곳이 없으므로 하드웨어를 추가 구매해야 한다. 하지만 Attainable SOL %가 65%라면 하드웨어 구매가 아니라 코드 최적화가 정답이라는 사실을 즉각적으로 알 수 있다.