로컬 LLM 추론에 큰 진전이 있었습니다!
이 새로운 추론 엔진은 llama.cpp보다 4배 빠르게 LLM을 구동합니다:
저는 base M5 MacBook Pro에서 Qwen3.5 9B 모델을 세 가지 엔진으로 실행해 보았습니다:
- llama.cpp: 22.0 tokens/s
- MLX: 25.1 tokens/s
- uzu: 92.1 tokens/s
아래 비디오는 세 가지 실행 결과를 나란히 보여줍니다.
앞의 두 수치는 llama.cpp나 MLX가 제대로 작동하지 않는다는 의미는 아닙니다. 하지만 둘 다 로컬 디코딩의 하드 리미트(hard limit) 바로 아래에 위치합니다.
LLM이 텍스트를 생성할 때, 새로운 토큰 하나마다 모델을 한 번 완전히 통과해야 하며, 이 과정에서 모든 가중치(weights)가 메모리에서 읽힙니다.
base M5는 약 153 GB/s로 메모리를 읽습니다. 4비트 9B 모델은 약 5.2 GB의 크기를 가집니다.
따라서 토큰 하나당 한 번 통과할 경우, GPU가 아무리 빠르게 계산하더라도 이론적 상한선은 대략 153 ÷ 5.2 ≈ 29 tokens/s입니다.
uzu는 한 번에 여러 개의 토큰을 생성함으로써 이 상한선을 뛰어넘습니다:
↳ 작은 초안 작성기(DFlash)가 다음 16개 위치의 후보군을 한 번에 제안합니다.
↳ 아주 작은 어댑터(Weaver, 56.7M params)가 왼쪽에서 오른쪽으로 이들 중 선택하여 추측들이 일관성 있는 텍스트를 형성하게 하고, 몇 가지 대체 분기점들을 트리 형태로 유지합니다.
↳ 9B 모델은 전체 트리를 단일 통과(single pass)로 확인하고 동의하는 가장 긴 경로를 유지합니다. 주 모델이 여전히 출력에 포함되는 모든 토큰을 결정합니다.
GitHub 저장소: https://t.co/TKikR80qEA
(별표 표시 잊지 마세요 🌟)
제가 실행한 결과에서, 9B 모델의 각 통과는 평균적으로 7.5개의 토큰을 생성했습니다. 일반적인 디코딩은 정확히 1개만 생성합니다.
가중치와 커널 역시 이를 염두에 두고 설계되었습니다. uzu는 자체 4비트 체크포인트(checkpoints)를 제공하며, M5 칩에서는 GPU의 int8 행렬 경로에서 검증 단계를 실행합니다.
uzu는 Mirai Labs가 만든 오픈 소스 추론 엔진으로, Rust와 Metal 커널로 작성되었습니다. Swift, Python, TypeScript, 그리고 Rust 바인딩을 갖추고 있어 동일한 엔진이 Mac 또는 iOS 앱 내부에서도 작동할 수 있습니다.
위에 GitHub 저장소를 공유했습니다.
더 깊이 파고들고 싶다면, 제 공동 창업자가 로컬 추론이 왜 메모리 제한적인지(memory-bound) 그리고 uzu의 추측 디코딩(speculative decoding)이 어떻게 이를 극복하는지에 대한 상세한 분석 글을 작성했습니다.
아래에서 읽어보세요.