Llama.cpp, MTP(다중 토큰 예측) 베타 지원 공개
로컬 AI 추론 엔진인 Llama.cpp에 여러 개의 토큰을 동시에 예측하여 처리 속도를 비약적으로 높이는 MTP(다중 토큰 예측) 기능이 베타로 추가되었습니다. 개발자는 기존 GGUF 모델 파일 하나만으로 MTP 모델을 자동으로 불러와 별도의 추가 배포 없이도 추론 속도를 2배 이상 크게 향상시킬 수 있습니다. 이는 로컬 환경에서 구동되는 오픈소스 대형 언어 모델(LLM)의 실질적인 응답 성능을 개선하는 중요한 이정표입니다.
ggml-org / llama.cpp 공지 (알림 설정을 변경하려면 로그인해야 합니다.) Fork 17.7k Star 108k 대화 링크 복사 마크다운 복사
기여자 am17an이 2026년 5월 4일에 댓글을 남겼습니다 (수정됨)
개요 이 풀 리퀘스트(PR)는 MTP(Multi Token Prediction, 다중 토큰 예측) 헤드에 대한 지원을 추가합니다. 저는 Qwen3.6 27B 및 Qwen3.6 35BA3B 모델에서 이 기능을 테스트했지만, 원칙적으로는 모든 MTP 모델에서 작동해야 합니다. 아래에 자세한 결과를 게시했지만, 일반적으로 3개의 드래프트 토큰(draft tokens)을 사용할 때 약 75%의 안정적인 수용률(acceptance rate)을 확인했으며, 이는 기존 대비 2배 이상의 속도 향상을 의미합니다.
이 단계에 도달하기 위해 내린 설계 결정은 다음과 같습니다:
- MTP 모델은 동일한 GGUF 파일에서 로드되는 별도의 모델입니다. 즉, MTP가 자동으로 시작되어야 하므로 MTP용 GGUF를 별도로 배포할 필요가 없도록 설계했으며, 이를 위해 자체 컨텍스트 및 KV 캐시 등을 가집니다.
- [추론 디코딩(Speculative decoding)] 기능 개발 중 숨겨진 특징(hidden features)이 여러 마이크로 배치(ubatches)에 걸쳐 올바르게 전파되지 않는 문제(EAGLE3 추론 디코딩 지원 #18039)를 발견했습니다. 따라서 이 PR은 각 마이크로 배치 후에 MTP가 처리할 수 있도록 별도의 '훅(hook)'을 추가했습니다.
- MTP 추론 클래스(Speculative class)는 매우 단순합니다. (GDN 모델을 위한 부분적인 seq_rm 허용 기능 #22400에 의존하지만, 이 기능이 없어도 작동할 수는 있습니다.)
성능 다양한 프롬프트를 테스트하기 위한 간단한 벤치마크는 여기에서 확인할 수 있습니다: https://gist.github.com/am17an/228edfb84ed082aa88e3865d6fa27090 아래에 벤치마크 결과를 공유합니다:
DGX Spark 시스템에서의 성능 🧵
MTP 미사용 (기준 모드) 명령어: ./llama-server -m ../qwen3.6-q8_0.gguf -np 1 --chat-template-kwargs "{"preserve_thinking": true}"
- code_python: 예측(pred)= 192, 드래프트(draft)= 0, 수용(acc)= 0, 수용률(rate)= 해당 없음, 속도= 7.0 tok/s
- code_cpp: 예측= 192, 드래프트= 0, 수용= 0, 수용률= 해당 없음, 속도= 7.3 tok/s
- explain_concept: 예측= 192, 드래프트= 0, 수용= 0, 수용률= 해당 없음, 속도= 7.3 tok/s
- summarize: 예측= 53, 드래프트= 0, 수용= 0, 수용률= 해당 없음, 속도= 7.1 tok/s
- qa_factual: 예측= 177, 드래프트= 0, 수용= 0, 수용률= 해당 없음, 속도= 7.0 tok/s
- translation: 예측= 22, 드래프트= 0, 수용= 0, 수용률= 해당 없음, 속도= 7.7 tok/s
- creative_short: 예측= 192, 드래프트= 0, 수용= 0, 수용률= 해당 없음, 속도= 7.1 tok/s
- stepwise_math: 예측= 192, 드래프트= 0, 수용= 0, 수용률= 해당 없음, 속도= 7.2 tok/s
- long_code_review: 예측= 192, 드래프트= 0, 수용= 0, 수용률= 해당 없음, 속도= 7.0 tok/s
종합 결과: { "n_requests": 9, "total_predicted": 1404, "total_draft": 0, "total_draft_accepted": 0, "aggregate_accept_rate": null, "wall_s_total": 201.07 }
MTP 사용 (--spec-draft-max-n 3 모드) 명령어: ./llama-server -m ../qwen3.6-q8_0-mtp.gguf -np 1 --chat-template-kwargs "{"preserve_thinking": true}" --spec-type mtp --spec-draft-n-max 3
- code_python: 예측= 192, 드래프트= 153, 수용= 139, 수용률= 0.908, 속도= 21.6 tok/s
- code_cpp: 예측= 192, 드래프트= 176, 수용= 132, 수용률= 0.750, 속도= 18.7 tok/s
- explain_concept: 예측= 192, 드래프트= 191, 수용= 126, 수용률= 0.660, 속도= 16.3 tok/s
- summarize: 예측= 55, 드래프트= 51, 수용= 37, 수용률= 0.726, 속도= 17.9 tok/s
- qa_factual: 예측= 177, 드래프트= 174, 수용= 118, 수용률= 0.678, 속도= 16.5 tok/s
- translation: 예측= 22, 드래프트= 24, 수용= 13, 수용률= 0.542, 속도= 13.9 tok/s
- creative_short: 예측= 192, 드래프트= 200, 수용= 123, 수용률= 0.615, 속도= 15.8 tok/s
- stepwise_math: 예측= 192, 드래프트= 171, 수용= 133, 수용률= 0.778, 속도= 19.3 tok/s
- long_code_review: 예측= 192, 드래프트= 179, 수용= 131, 수용률= 0.732, 속도= 18.0 tok/s
종합 결과: { "n_requests": 9, "total_predicted": 1406, "total_draft": 1319, "total_draft_accepted": 952, "aggregate_accept_rate": 0.7218, "wall_s_total": 83.8 }
MTP 사용 (--spec-draft-max-n 2 모드) 명령어: ./llama-server -m ../qwen3.6-q8_0-mtp.gguf -np 1 --chat-template-kwargs "{"preserve_thinking": true}" --spec-type mtp --spec-draft-n-max 2
- code_python: 예측= 192, 드래프트= 134, 수용= 123, 수용률= 0.918, 속도= 17.4 tok/s
- code_cpp: 예측= 192, 드래프트= 145, 수용= 118, 수용률= 0.814, 속도= 16.5 tok/s
- explain_concept: 예측= 192, 드래프트= 148, 수용= 116, 수용률= 0.784, 속도= 16.1 tok/s
- summarize: 예측= 55, 드래프트= 44, 수용= 32, 수용률= 0.727, 속도= 15.6 tok/s
- qa_factual: 예측= 192, 드래프트= 132, 수용= 125, 수용률= 0.947, 속도= 18.2 tok/s
- translation: 예측= 22, 드래프트= 18, 수용= 12, 수용률= 0.667, 속도= 15.2 tok/s
- creative_short: 예측= 192, 드래프트= 149, 수용= 116, 수용률= 0.778, 속도= 16.1 tok/s
- stepwise_math: 예측= 192, 드래프트= 139, 수용= 121, 수용률= 0.871, 속도= 17.2 tok/s
- long_code_review: 예측= 192, 드래프트= 153, 수용= 114, 수용률= 0.745, 속도= 15.6 tok/s
종합 결과: { "n_requests": 9, "total_predicted": ...