맥에서 로컬 LLM 속도 미리 가늠하기: 메모리 대역폭과 투기적 디코딩
- 로컬 모델이 답을 만드는 속도는 칩의 연산 성능보다 메모리 대역폭이 정한다. 토큰 하나를 만들 때마다 모델 전체를 메모리에서 한 번 읽기 때문이다.
- 투기적 디코딩은 여기에 배수를 곱하는 기술이다. 같은 모델에서 대략 2~3배 빨라졌다. 다만 곱해지는 기본 속도가 느리면 결과도 느리다.
- 남이 올린 벤치마크를 볼 때는 투기적 디코딩을 끈 기본 속도를 찾아 비교한다. 최종 숫자만 보면 칩 차이와 기술 차이가 섞인다.
- 벤치마크는 대개 짧은 질문으로 잰다. 입력이 수만 토큰이면 첫 글자가 나오기까지 몇 분이 걸리고 생성도 느려진다. 실제로 보낼 길이로 다시 잰다.
32GB 메모리의 맥 미니(M6)에서 Qwen3.8-27B 모델을 돌렸다. 서버는 애플의 머신러닝 프레임워크 MLX 위에서 도는 오픈소스 추론 서버 MTPLX다. Ollama, LM Studio, llama.cpp 같은 다른 서버도 원리는 같지만 설정 이름과 기본값은 다르다.
- 가중치: 모델이 학습한 숫자들로, 모델 파일의 대부분이다. 4bit로 줄였다(양자화)는 숫자 하나를 4비트로 저장했다는 뜻이다.
- 기본 속도: 투기적 디코딩 없이 한 토큰씩 차례로 만드는 방식(autoregressive, AR)의 속도.
- 문맥 캐시(KV 캐시): 요청의 앞 내용을 기억해 두는 메모리.
1.로컬 모델의 속도는 무엇이 정하나
맥에 27B 정도의 모델을 올려 쓰고 싶다. 대화하듯 쓸 만한 속도가 나올지 사기 전에 알고 싶다. 보통은 누군가 올린 "초당 토큰 수"를 찾는다. 그 숫자가 내 기계에서도 나올지는 무엇이 속도를 정하는지 알아야 판단할 수 있다.
모델이 답을 쓰는 과정은 한 번에 한 토큰씩이다. 그리고 토큰 하나를 만들 때마다 모델의 가중치 전체를 메모리에서 한 번 읽는다. 4bit로 줄인 27B 모델이면 약 20GB다(4bit만으로 계산하면 13.5GB지만, 품질에 민감한 층은 더 높은 정밀도로 남겨 두어 커진다). 계산 자체보다 이 읽기가 더 오래 걸리기 때문에, 답을 쓰는 속도는 메모리를 얼마나 빨리 읽을 수 있느냐, 즉 메모리 대역폭을 따라간다.
초당 토큰 수 (상한) ≈ 메모리 대역폭 ÷ 모델 크기
# 예: 대역폭이 초당 200GB이고 모델이 20GB라면, 많아야 초당 10토큰 정도
그래서 같은 모델이라도 칩에 따라 속도가 크게 다르다. 칩 이름의 "Max", "Pro" 같은 등급이 대역폭을 크게 바꾸므로, 다른 사람의 결과를 가져올 때는 그 칩과 내 칩의 대역폭 비율만큼 줄이거나 늘려서 본다.
2.투기적 디코딩은 무엇을 빠르게 하나
요즘 로컬 추론 도구 상당수가 투기적 디코딩(speculative decoding)을 쓴다. 작은 예측기가 다음 토큰 몇 개를 먼저 추측하고, 큰 모델은 그 추측이 맞는지를 한 번에 검사한다. 모델 전체를 한 번 읽는 비용으로 토큰을 여러 개 확정할 수 있으니 빨라진다. 검사 규칙을 제대로 따르면 결과는 큰 모델 혼자 쓴 것과 같은 분포다 (Leviathan 외, 2023).
흔히 "3개를 추측하면 최대 4배"라고 생각한다. 실제로는 그보다 작다. 추측이 늘 맞지는 않고, 한 번에 여러 개를 검사하는 단계가 보통 한 토큰 만드는 것보다 조금 더 비싸기 때문이다.
빨라지는 배수 = 한 번에 확정되는 평균 토큰 수 ÷ 검사 한 번의 상대 비용
└ 글의 종류가 정한다 └ 기계가 정한다
코드처럼 다음 말이 뻔한 글은 추측이 잘 맞고, 자유로운 대화는 덜 맞는다. 그러니 발표된 배수는 참고만 하고, 자기가 쓰는 종류의 글로 다시 재 봐야 한다.
짧은 질문에 600토큰을 쓰게 했을 때 기본 속도는 초당 약 7토큰, 투기적 디코딩을 켜면 약 19토큰이었다. 한 번에 3~4토큰씩 확정됐지만 검사가 일반 생성보다 조금 비싸서, 실제로는 약 2.6배 빨라졌다. M5 Max 값은 모델 제작자가 공개한 측정이다.
3.배수가 큰데도 느리게 느껴진다면
위 그림에서 M6 맥 미니는 오히려 배수가 조금 더 컸다. 그런데 사용자가 느끼는 것은 배수가 아니라 실제 속도다. 투기적 디코딩을 끄고 잰 기본 속도가 이미 3배 가까이 차이 났고, 그 차이가 그대로 남았다.
그래서 느리다고 느낄 때 먼저 할 일은 투기적 디코딩을 끄고 기본 속도를 재 보는 것이다.
- 기본 속도가 1절의 어림값 근처라면 하드웨어가 한계다. 설정으로 얻을 수 있는 것은 배수 정도다. 더 빠르려면 더 작은 모델이나 대역폭이 큰 기계가 필요하다.
- 기본 속도가 어림값보다 한참 낮다면 도구나 설정을 의심할 이유가 있다. 새 칩이 나온 직후에는 추론 도구가 그 칩을 아직 제대로 지원하지 않을 수도 있다.
4.실제 요청은 왜 벤치마크보다 느린가
벤치마크 숫자는 대개 한두 문장짜리 질문으로 잰다. 실제로 쓰는 요청은 다르다. 에이전트라면 지시문과 도구 설명만으로 수천~수만 토큰이 된다. 입력이 길면 두 군데서 느려진다.
- 첫 글자가 나오기까지. 모델은 답을 쓰기 전에 입력 전체를 먼저 읽는다. 입력이 길수록 이 대기 시간이 그대로 늘어난다.
- 답을 쓰는 속도. 앞 내용을 기억해 둔 문맥 캐시(KV 캐시)도 토큰마다 읽어야 해서, 입력이 길면 생성도 느려진다.
| 입력 길이 | 첫 글자까지 | 생성 속도 |
|---|---|---|
| 짧은 질문 | 거의 바로 | 초당 약 19토큰 |
| 약 1만 토큰 (도구 설명 포함) | 앞부분을 재사용하면 수 초 | 초당 12~20토큰 |
| 약 3만 토큰 | 약 2분 | (입력 처리만 잰 시험) |
| 약 6만 토큰 | 약 5분 | (입력 처리만 잰 시험) |
2만6천 토큰 정도의 입력에서는 생성 속도도 초당 6~8토큰으로, 짧은 질문의 기본 속도 수준까지 떨어졌다. 모델이 긴 입력을 받아 준다고 해서 그 길이가 쓸 만하다는 뜻은 아니다. 1만 토큰 요청이 수 초에 끝난 것은 매번 같은 앞부분을 서버가 기억해 두고 다시 쓴 덕분이다. 이 재사용이 안 되면 같은 요청도 첫 글자까지 수십 초가 걸린다.
추론형 모델은 답 앞에 생각하는 과정을 토큰으로 먼저 쓴다. 화면에 안 보여도 같은 속도로 하나씩 만들어진다. 초당 19토큰이면 생각 1,500토큰만으로 1분이 넘는다. 응답 시간을 어림할 때는 이 몫도 넣는다.
5.이 결론이 안 통하는 조건
- 여러 요청을 동시에 처리하는 서버. 한 번 읽은 가중치로 여러 요청의 토큰을 함께 만들면 병목이 대역폭에서 연산으로 옮겨 간다. 이 글은 요청을 하나씩 처리하는 개인용 구성을 전제한다.
- MoE(전문가 혼합) 모델. 토큰마다 모델 일부만 읽는다. 1절의 어림에서 "모델 크기" 대신 실제로 쓰이는 부분의 크기를 넣어야 한다.
- 별도의 작은 모델로 추측하는 방식. 추측용 모델도 메모리와 대역폭을 쓰므로 계산이 달라진다.
- 외장 GPU. 모델이 GPU 메모리에 다 들어가는지에 따라 전혀 다른 이야기가 된다.
6.정리
- 발표된 숫자에서 투기적 디코딩을 끈 기본 속도를 찾는다.
- 그 값을 내 칩과의 대역폭 비율로 옮긴다. 모델 크기가 같다면 대역폭이 곧 속도의 상한이다.
- 투기적 디코딩의 배수는 내가 쓸 종류의 글로 다시 잰다.
- 실제로 보낼 입력 길이로 잰다. 첫 글자까지의 대기와 생성 속도가 모두 달라진다.
- 느리면 투기적 디코딩을 끄고 기본 속도부터 본다. 하드웨어 한계인지 설정 문제인지가 거기서 갈린다.
투기적 디코딩은 잘 작동했다. 그래도 체감 속도를 정한 것은 칩이었다. 기술은 배수를 곱하고, 출발점은 하드웨어가 정한다.
'프로그래밍 > AI' 카테고리의 다른 글
| 로컬 LLM이 매번 입력을 처음부터 다시 읽을 때: prefix 캐시 확인하는 법 (0) | 2026.09.25 |
|---|---|
| 32GB 맥에서 큰 로컬 LLM 돌릴 때 메모리 나누는 법: GPU 한도와 서버 캐시 (0) | 2026.09.25 |
| AI가 만든 JSON이 계속 퇴짜맞을 때: LLM 호출을 75% 줄인 세 가지 처방 (0) | 2026.08.23 |
| 서브에이전트 위임의 기준 — 조직도가 아니라 작업 경계 (0) | 2026.07.20 |
| 하네스와 루프 — AI에게 일을 시키는 시스템 설계 (0) | 2026.07.20 |
댓글