본문으로 건너뛰기

© 2026 Molayo

Reddit요약2026. 05. 21. 14:53

Build 9254에서 TG 회귀 문제 해결 및 NVIDIA GPU용 PDL 추가

요약

llama.cpp의 Build 9254에서 발생하던 토큰 생성(TG) 성능 저하 문제가 해결되었으며, NVIDIA GPU를 위한 PDL(Programmatic Dependent Launch) 기능이 추가되었습니다. PDL은 최신 NVIDIA GPU에서 커널 실행을 중첩시켜 오버헤드를 줄임으로써 토큰 생성 속도를 향상시키는 최적화 기술입니다.

핵심 포인트

  • Build 9254에서 이전 빌드의 TG(Token Generation) 회귀 현상이 복구됨
  • NVIDIA GPU용 PDL(Programmatic Dependent Launch) 추가로 커널 실행 오버헤드 감소 및 성능 향상
  • PDL 적용 시 RTX PRO 6000에서 토큰 생성 속도가 약 10% 향상되는 효과 확인
  • PDL 구현을 위해 동기화 장벽(Synchronization Barrier)과 실행 신호(Launch Signal) 기능이 커널에 적용됨

최근 몇몇 빌드에서 mtp 및 non 모델 모두에서 TG (Token Generation) 회귀 현상이 발생하여 b9202로 되돌려야 했습니다. 하지만 방금 새로운 b9254를 실행해 보았는데, TG가 복구되었을 뿐만 아니라 tensor split을 사용한 2x5060ti 16gb 환경에서 약 5%의 추가 성능 향상(uplift)을 확인했습니다.

한번 시도해 보기 위해 PDL 플래그를 사용하여 cmake를 실행했습니다. 비교를 위해 곧 PDL 없이도 테스트해 볼 예정이지만, qwen3.6-35b-a3b-Q4_K_XL 모델에서 3.2k PP(Prompt Processing) 및 127 tg/s (token generation per second)라는 일관된 결과를 얻고 있습니다.

PDL이 제 결과의 원인이라고 단정 짓는 것은 아니지만, 적어도 이 빌드는 b9202만큼 혹은 그보다 더 잘 작동하고 있습니다. 시간만이 증명해 줄 것입니다.

대화

aendk3주 전에 댓글을 남김

개요

Programmatic Dependent Launch (PDL)은 최신 NVIDIA GPU (CC >= 90; Ada는 포함되지 않음)를 위한 CUDA 최적화 기술입니다.
이는 동일한 CUDA 스트림 내에서 CUDA 커널(kernel)의 실행을 중첩(overlapping)할 수 있게 해줍니다. CUDA graphs와 마찬가지로, 장치(device)에서의 커널 실행 오버헤드(kernel launch overhead)를 줄여줍니다. 두 기술의 이점은 상호 보완적입니다 (PDL + CG > CG > PDL).
이러한 효과는 단일 CUDA 스트림에 대한 다음 Nsight Systems 스크린샷에서 시각적으로 가장 잘 확인할 수 있습니다. 원래는 엄격하게 순차적으로 실행되어야 하는 커널들이 동시에 실행됩니다:

PDL은 이미 작년에 #15479에서 제안된 바 있습니다.
이번 PR은 CUDA graph 의미론(semantics)에 더 잘 통합되었으며, 훨씬 더 나은 성능을 제공합니다. RTX PRO 6000에서는 토큰 생성(token generation) 단계의 속도가 10% 향상되는 것이 드문 일이 아니며, DGX Spark에서는 4-5%의 개선을 확인했습니다 (모델에 따라 다름, 아래 상세 통계 참조).

완전한 PDL 성능을 구현하기 위해서는 커널(kernel)에 두 가지 새로운 기능이 갖춰져야 합니다: 동기화 장벽 (GGML_CUDA_PDL_SYNC)과 실행 신호 (GGML_CUDA_PDL_LC)입니다. 동기화 장벽 (synchronization barrier)은 커널 실행을 제한하여 이전 커널에 의해 기록된 데이터를 기다리게 함으로써, 경합 조건 (race conditions)이나 조기 데이터 접근 (premature data accesses)이 발생하지 않도록 합니다. 실행 신호 (launch signal)는 현재 커널이 다음 커널의 시작을 어느 시점에서 허용할 수 있는지를 나타냅니다. 또한, 커널은 새로운 ggml_cuda_kernel_launch() 함수를 통해 실행되어야 합니다.

동기화 장벽은 커널 코드를 주의 깊게 검토하여 커널 입력의 첫 번째 "실제" 데이터 접근(예: 포인터 연산 제외)을 식별함으로써 배치할 수 있습니다. 실행 신호의 배치는 약간의 수동 튜닝 (hand-tuning)과 벤치마킹 (benchmarking)이 필요합니다. 이번 초안 PR (draft PR)에서는 gpt-oss 20b, qwen3.5nemotron 120B Super에 사용되는 모든 커널을 등록했습니다. 이 커널들은 다른 모델들과 공유되기 때문에 더 많은 모델을 테스트했습니다. 그 결과, 프리필/컨텍스트 (prefill/context) 단계는 대부분 중립적이었으나, 토큰 생성 (token generation) 단계에서는 거의 모든 모델에서 속도 향상을 확인했습니다.

적용된 휴리스틱 (Applied Heuristics):

  • 이번 초안에서는 동기화 장벽 (synchronization barrier) 배치와 관련하여, 각 커널의 첫 번째 "실제" 데이터 액세스를 입력 텐서 (input tensor)라고 가정했습니다. 만약 이전 커널이 스칼라 (scalar)를 출력하고 현재 커널이 GGML_CUDA_PDL_SYNC 이전에 이 스칼라를 읽는 경우가 있다면, 데이터 레이스 (data race)가 발생할 수 있습니다. 이 머지 (merge)를 준비 상태로 표시하기 전에 이 부분을 다시 한번 재검토하겠습니다. 리뷰 시 이 점을 유념해 주시기 바랍니다.
  • GGML_CUDA_PDL_LC의 올바른 배치에는 약간의 시행착오가 따릅니다. 이는 일부 커밋에서 최적화되지 않은 배치를 주석 처리한 일부 커널들에서 확인할 수 있습니다. 일부 커널에서는 GGML_CUDA_PDL_LC를 배치하는 것이 오히려 성능에 부정적인 영향을 미치기도 합니다 (특히 mul_mat_vec_q에서 두드러짐). 일반적으로 커널 내에서 신호 (signal)가 더 일찍 배치될수록 커널은 지연 시간 제한 (latency limited)을 더 많이 받으며, (후속 커널의 조기 실행으로 인한) 공유 자원 경합 (shared resource contention)을 더 많이 견딜 수 있습니다.

이 구현에 대한 추가 정보

  • 이 접근 방식은 그래프 내의 일부 커널이 PDL에 등록되어 있지 않더라도 사용할 수 있습니다. 두 개의 연속된 커널이 등록되어 있다면, 이들은 PDL을 활용합니다 (예: quantize_q8mul_mat_vec_q는 PDL에 등록되어 있으며 많은 모델에 존재합니다).
  • 커널은 하나씩 등록될 수 있습니다.
  • GGML_CUDA_PDL_LC 플래그의 배치 최적화는 약간의 시행착오가 필요하지만, 한 모델에 대한 좋은 배치는 다른 모델에도 유익한 것으로 보입니다. 내부 테스트 결과, 예를 들어 모델 A에는 유익하지만 모델 B의 성능에는 악영향을 미치는 설정은 발견되지 않았습니다.

알려진 문제/할 일 (Known issues/TODOs)

  • 현재 GGML_CUDA_PDL_SYNC가 잘못 배치된 경우의 레이스 컨디션 (race condition)을 식별할 수 있는 memcheck와 같은 도구가 없습니다.
  • 지원되지 않는 (NVIDIA) GPU에 대해 PDL을 자동으로 비활성화하는 방법을 찾아야 합니다. GGML_CUDA_CC_HOPPER에 대한 간단한 체크는 작동하지 않았습니다.
  • 더 많은 커널 (kernels)을 PDL로 이동할 수 있습니다 (다른 런치 (launch) + 동기화 장벽 (sync barrier)).
  • 주석 처리된 런치 시그널 (launch signal) 실험 코드를 제거해야 합니다.
  • CUDA 그래프 (CUDA graphs) 자체와 마찬가지로, 이 기능을 처음에는 토큰 생성 (token generation)에 대해서만 배포하는 것이 합리적일 수 있습니다. 이것이 실행 가능한지 확인이 필요합니다.

테스트 방법

최신 NVIDIA GPU (예: Blackwell)가 필요하며, -D GGML_CUDA_PDL=ON 옵션으로 컴파일해야 합니다.

다른 커널을 PDL에 등록하는 방법

  • 1단계: ggml_cuda_kernel_launch()를 사용하여 커널 런치 (kernel launch)를 수정하고 GGML_CUDA_PDL_SYNC()를 설정합니다. 동기화 장벽 (sync barrier)을 설정하지 않고 커널 런치를 수정하면 레이스 컨디션 (race condition)이 발생합니다.
  • 2단계: GGML_CUDA_PDL_LC()의 배치 위치를 반복적으로 시도합니다. 저의 느슨한 휴리스틱 (heuristic)은 함수의 시작 부분에 배치하여 성능을 측정하고, 커널 중간의 다른 위치에 대해 이 과정을 반복하는 것이었습니다. 그 후 가장 성능이 좋은 배치를 선택했습니다. 제 테스트 결과에 따르면, 커널의 하단 근처에 배치하는 것은 거의 항상 비효율적이었습니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Reddit AI Engineering의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0