r/LocalLLaMA: M1 Max에서 MLX와 llama.cpp의 실제 지연 시간 차이를 검증

최근 r/LocalLLaMA에서는 Apple Silicon에서 local LLM을 돌릴 때 흔히 반복되는 주장, 즉 MLX로 바꾸기만 하면 언제나 더 “빠르다”는 인식에 제동을 거는 벤치마크 글이 주목받았다. 이 글의 핵심은 MLX가 느리다는 것이 아니다. 대신 많은 비교가 generation tok/s만 보여주고, 실제 사용자 지연 시간의 상당 부분을 차지하는 prompt ingestion과 context 처리 비용은 가리고 있다는 점을 짚는다. coding agent, document classification, multi-turn RAG처럼 긴 context를 자주 다루는 workload라면 이 차이는 훨씬 중요해진다.

테스트 구성도 꽤 구체적이다. 작성자는 M1 Max 64GB 환경에서 LM Studio 0.4.5를 사용해 Qwen3.5-35B-A3B를 돌렸고, MLX 4-bit 경로와 llama.cpp 기반의 GGUF Q4_K_M 경로를 비교했다. 순수 generation 속도만 보면 MLX는 예상대로 앞선다. 수치는 대략 57 tok/s 대 29 tok/s였다. 하지만 prompt가 커지면 그림이 바뀐다. 약 655 token 수준의 짧은 prompt에서는 요청 시작부터 마지막 token까지의 effective throughput이 MLX 약 13 tok/s, llama.cpp 약 20 tok/s로 측정됐다. prompt가 약 8,496 token까지 커진 경우에는 두 경로 모두 end-to-end 기준 약 3 tok/s 수준으로 수렴했다.

핵심 원인은 prefill이다. 긴 context 사례에서 작성자는 MLX 실행의 전체 응답 시간 중 약 94%가 prefill에 쓰였다고 적었다. 즉 generation 단계의 높은 속도만으로는 사용자가 체감하는 총 대기 시간을 설명할 수 없다는 뜻이다. 그래서 결론도 “MLX가 나쁘다” 혹은 “llama.cpp가 무조건 낫다”가 아니라 더 현실적이다. 출력이 길고 prompt가 짧을 때는 MLX가 여전히 유리할 수 있다. 반대로 retrieval-heavy하거나 agentic해서 입력 context가 크게 늘어나는 workload에서는 광고되는 속도 우위가 빠르게 줄어든다. 댓글에서는 이번 모델인 Qwen3.5의 hybrid attention path가 현재는 llama.cpp에서 더 잘 지원될 수 있다는 지적도 나왔다.

실무적 교훈은 분명하다. local LLM 사용자는 단일 generation 숫자가 아니라 자신이 실제로 돌릴 workload를 기준으로 벤치마크해야 한다. 시스템이 대부분의 시간을 큰 context를 읽는 데 쓰면 prompt processing 효율이 raw decode speed보다 더 중요할 수 있다. 반대로 짧은 prompt에서 긴 출력을 스트리밍하는 경우에는 MLX가 여전히 가장 좋은 선택일 수 있다. 작성자가 공개한 재현 가능한 benchmark harness는 github.com/famstack-dev/local-llm-bench에 있다.