이 글은 소비자용 GPU 한 장으로 거대 모델을 자체 서빙할지 저울질하는 엔지니어, 그리고 “24GB로 120B를 돌린다”는 요즘 트윗을 어디까지 믿어야 할지 판단해야 하는 인프라 담당자를 위해 썼습니다. 결론부터 말하면, 난징대학교 연구진이 공개한 ATSInfer(arXiv:2607.10183)의 핵심 아이디어는 단순하면서도 설득력이 있습니다. 지금까지의 오프로딩이 “레이어” 또는 “전문가(expert)” 단위로 뭉텅이째 CPU와 GPU를 오갔다면, ATSInfer는 그 단위를 텐서 하나하나까지 쪼갭니다. 다만 화제가 된 “최대 3.29배”라는 숫자는 몇 가지 전제 위에 서 있고, 아직 코드가 공개되지 않았다는 점도 함께 짚겠습니다. 저희는 RTX 4090과 120B급 모델을 이 자리에서 재현하지는 못했으므로, 이 글의 모든 수치는 논문이 보고한 값임을 먼저 분명히 해 둡니다.

개요

로컬 LLM을 돌려 본 사람이라면 한 번쯤 마주치는 벽이 있습니다. 모델 가중치가 GPU 메모리보다 크면, 남는 부분은 CPU 메모리로 내려야 합니다. llama.cpp의 -ngl(GPU에 올릴 레이어 수) 플래그가 바로 그 일을 합니다. 문제는 이 방식이 레이어 단위로만 자른다는 점입니다. 한 레이어 안에는 어텐션 가중치, FFN 가중치, 정규화 파라미터처럼 성격이 전혀 다른 텐서들이 섞여 있는데, 이들을 통째로 “GPU에 올리거나 / CPU에 두거나” 둘 중 하나로만 처리합니다.

이 뭉텅이 배치가 왜 손해인지는 간단합니다. 같은 1GB를 VRAM에 올려도, 어떤 텐서는 GPU에서 10배 빨라지고 어떤 텐서는 2배밖에 안 빨라집니다. VRAM은 희소 자원인데, 뭉텅이로 자르면 “GB당 이득이 큰 텐서”를 골라 담을 수가 없습니다. ATSInfer는 이 지점을 정확히 겨냥합니다. 텐서마다 CPU와 GPU에서의 성능을 프로파일링해, VRAM 1GB당 속도 이득이 가장 큰 텐서부터 채워 넣습니다. 최근 화제였던 ktransformers가 MoE 모델의 전문가를 CPU로 내리는 “전문가 단위” 트릭이었다면(관련 글: ktransformers의 28배를 재현해봤습니다), ATSInfer는 그보다 한 단계 더 잘게 쪼갠 “텐서 단위” 일반화라고 볼 수 있습니다. MoE뿐 아니라 밀집(dense) 모델에도 적용된다는 점이 특히 다릅니다.

이 기술은 무엇인가

ATSInfer는 llama.cpp를 약 1만 5천 줄의 C++로 확장한 하이브리드 CPU-GPU 추론 시스템입니다. 이름 그대로 “자동 텐서 스케줄링(Automated Tensor Scheduling)”이 핵심이며, 세 가지 메커니즘이 맞물려 돌아갑니다.

flowchart TB
    A["모델 가중치<br/>(RAM, VRAM 용량 초과)"] --> B["텐서별 성능 프로파일링<br/>GB당 속도 이득 측정"]
    B --> C{"정적 배치 결정<br/>이득 큰 텐서부터 VRAM에"}
    C -->|"고이득 텐서"| D["VRAM 상주"]
    C -->|"저이득 텐서"| E["RAM 상주"]
    D --> F["로드 인식 동적 전송<br/>런타임 부하 따라 승격·강등"]
    E --> F
    F --> G["비동기 CPU-GPU 조율<br/>연산·PCIe 전송 오버랩"]
    G --> H["토큰 출력<br/>prefill · decode"]

첫째, 정적 텐서 배치(static placement)입니다. 모델을 올리기 전에, 벤치마크로 각 텐서가 GPU에서 얼마나 빨라지는지를 미리 측정합니다. 그리고 “VRAM 1GB를 썼을 때 가장 많은 속도를 돌려주는” 텐서 순으로 GPU에 배치합니다. 이는 배낭 문제(knapsack)에 가까운 최적화로, 뭉텅이 배치가 놓치던 텐서 간 이질성을 정면으로 활용합니다.

둘째, 로드 인식 동적 전송(load-aware dynamic transfer)입니다. 정적 배치만으로는 부족합니다. 실제 추론 중에는 배치 크기, 컨텍스트 길이, 동시 요청 수에 따라 부하가 시시각각 변합니다. ATSInfer는 런타임 상황을 보고 특정 텐서를 RAM에서 GPU로 승격하거나 반대로 강등합니다. 정적 배치가 “출발선”이라면, 동적 전송은 “주행 중 차선 변경”에 해당합니다.

셋째, 비동기 CPU-GPU 조율(asynchronous coordination)입니다. CPU 연산, GPU 연산, 그리고 둘을 잇는 PCIe 전송을 서로 겹쳐(overlap) 실행합니다. 순진하게 구현하면 GPU가 CPU의 계산이나 데이터 전송을 기다리며 노는 시간이 생기는데, 이 조율 계층이 그 유휴 시간을 메웁니다. 논문은 이 덕분에 GPU SM(스트리밍 멀티프로세서) 평균 활용도가 약 70% 올라갔다고 보고합니다.

논문이 보고한 실험 결과

다시 강조하지만, 아래 수치는 논문이 보고한 값이며 저희가 직접 재현한 것이 아닙니다. ATSInfer는 아직 코드가 공개되지 않았고(트윗에서도 “연구자들이 llama.cpp 팀에 코드를 공유해 주길”이라는 반응이 있었습니다), 120B급 모델과 RTX 4090은 이 글을 쓰는 샌드박스에서 재현하기 어렵습니다. 그래서 저희는 재현 대신 구조 분석과 함의 정리에 집중합니다.

논문의 헤드라인 수치는 다음과 같습니다. 기존 하이브리드 시스템(llama.cpp의 레이어 단위 오프로딩 포함) 대비, prefill(첫 토큰까지의 처리량)은 최대 1.94배, decode(초당 생성 토큰)는 최대 3.29배 빨라졌습니다.

ATSInfer가 논문에서 보고한 최대 속도 향상 비교

실험 환경은 RTX 4090(24GB) 및 RTX 3060 시스템에 64GB RAM 구성이며, 검증에 사용한 모델은 다음과 같습니다.

  • Llama 3.1-70B (INT4)
  • Qwen3-Next-80B-A3B (INT4)
  • Qwen3.5-122B-A10B (INT4)
  • GPT-OSS-120B (MXFP4)

즉 24GB 한 장으로 122B 파라미터 모델(A10B, 활성 파라미터 기준으로는 더 작은 MoE)까지 구동했다는 것이 핵심 주장입니다. 여기서 두 가지를 분리해 읽어야 합니다. 첫째, “3.29배”는 특정 조건에서의 최댓값이지 모든 모델·모든 배치에서 나오는 평균이 아닙니다. 둘째, 이 이득은 근본적으로 “GPU에 안 들어가던 것을 넣어 돌린다”가 아니라 “어차피 CPU-GPU를 오갈 수밖에 없는 상황에서, 오가는 방식을 더 똑똑하게 만든다”에서 옵니다. 병목이 PCIe 대역폭이라는 물리 법칙은 그대로이므로, ATSInfer의 기여는 그 대역폭을 낭비 없이 쓰고 GPU 유휴 시간을 줄인 데 있습니다.

ThakiCloud 제품 적용 시사점

ThakiCloud의 ai-platform은 Kubernetes와 Kueue 기반으로 다양한 고객 환경에서 모델을 서빙하는 AI/ML 인프라입니다. ATSInfer 같은 텐서 단위 스케줄링은 저희가 특히 주목하는 흐름과 맞닿아 있습니다.

첫째, 온프레미스·소버린 환경의 경제성입니다. 국내 공공·금융 고객처럼 데이터를 외부로 내보낼 수 없는 환경에서는 자체 GPU로 모델을 돌려야 합니다. 이때 H100 8장짜리 랙 대신 소비자용 GPU 몇 장으로 중대형 모델을 감당할 수 있다면, 초기 CAPEX가 극적으로 낮아집니다. ATSInfer의 실험이 보여 주는 것은, “VRAM이 모자라면 무조건 GPU를 더 사야 한다”는 전제가 텐서 배치 최적화로 상당 부분 완화될 수 있다는 점입니다. 물론 그 대가는 처리량 감소이므로, 저지연이 필수인 워크로드에는 부적합합니다. 이 트레이드오프를 워크로드별로 판단하는 것이 저희 서빙 계층의 역할입니다.

둘째, 멀티테넌트 스케줄링과의 결합입니다. ATSInfer의 “로드 인식 동적 전송”은 단일 노드 안에서의 텐서 이동이지만, 그 발상은 클러스터 수준에서도 유효합니다. Kueue로 GPU 자원을 큐잉하고 할당할 때, 어떤 요청을 어떤 정밀도·어떤 오프로딩 프로파일로 처리할지를 부하에 따라 결정하는 정책은 저희가 이미 고민하는 영역입니다. 텐서 단위 프로파일링이 노드 안에서 자원 이득을 짜내듯, 클러스터 스케줄러는 노드 사이에서 같은 일을 합니다.

셋째, 비용-품질 곡선의 재정의입니다. 저희는 ktransformers 재현 글에서 “28배” 같은 화제 수치가 숨은 전제 위에 서 있음을 직접 측정으로 보였습니다. ATSInfer의 “3.29배”도 같은 렌즈로 봐야 합니다. 마케팅 수치가 아니라, 우리 고객의 실제 모델·실제 배치·실제 SLA에서 어떤 숫자가 나오는지를 검증하는 것이 저희가 제공하는 가치입니다. 낮은 서빙 비용에서의 경쟁력은 결국 이런 검증의 축적에서 나옵니다.

한계 및 반론

가장 큰 한계는 코드 미공개입니다. 논문의 수치가 재현 가능한지, 다른 하드웨어·다른 모델에서도 유지되는지는 코드가 나와야 검증할 수 있습니다. 15,000줄 규모의 C++ 확장이라면 유지보수와 llama.cpp 본류 병합도 만만치 않은 과제입니다. 병합되지 못한 포크는 시간이 지나면 상류 변경을 따라가지 못해 쓸모가 줄어듭니다.

둘째, 이득의 조건 의존성입니다. 텐서 단위 배치의 효과는 CPU 성능, RAM 대역폭, PCIe 세대에 크게 좌우됩니다. 논문의 실험은 64GB RAM을 전제하는데, RAM이 부족하면 텐서를 CPU에 둘 여유 자체가 없어집니다. PCIe 3.0 시스템에서는 전송이 병목이 되어 이득이 크게 줄어들 가능성이 높습니다([추정], 논문이 세대별 비교를 명시하지 않았습니다).

셋째, decode 최적화의 태생적 천장입니다. decode는 메모리 대역폭에 묶인(memory-bound) 작업입니다. 아무리 스케줄링을 잘해도 VRAM 밖에 있는 가중치는 매 토큰마다 어떤 식으로든 접근해야 하므로, 순수 VRAM 상주 대비 느릴 수밖에 없습니다. ATSInfer가 하는 일은 “느려지는 정도를 최소화”하는 것이지 “느려짐을 없애는” 것이 아닙니다. 반대편 논거를 세워 보면, 진짜 저지연·고처리량이 필요한 프로덕션 서빙이라면 여전히 모델 전체가 VRAM에 들어가는 GPU를 쓰는 편이 옳습니다. ATSInfer가 빛나는 지점은 “그 GPU를 살 여력이 없거나, 살 필요까지는 없는” 개발·평가·소규모 배치 구간입니다.

그럼에도 이 방향성은 분명한 가치가 있습니다. 하드웨어를 늘리지 않고 소프트웨어로 자원 활용을 짜내는 접근은, 온프렘·비용효율·self-hosting을 무기로 삼는 저희 같은 플랫폼에 특히 잘 맞습니다. 코드가 공개되면 저희 서빙 벤치마크에 편입해 실제 수치를 직접 측정할 계획입니다.

출처