커뮤니티에서 “이 모델 토큰 속도 85 t/s 나왔어요”라는 글을 보면 솔깃해진다. 그런데 막상 동일한 모델을 내 맥북이나 서버에 올려보면 절반도 안 나오는 경우가 허다하다. 측정 방법이 잘못된 것도, 내 하드웨어가 고장난 것도 아니다. 벤치마크를 기록한 사람과 나의 실행 조건이 전혀 다른 것이다.
로컬 LLM 생태계가 빠르게 성장하면서 llama.cpp, Ollama, LM Studio, vLLM 같은 런타임이 저마다 벤치마크 수치를 내놓는다. GitHub 이슈, Reddit, 디스코드 서버에는 매일 새로운 측정 결과가 올라온다. 문제는 이 숫자들이 “어떤 조건에서” 나온 것인지 거의 표기되지 않는다는 점이다. 그냥 모델 이름과 tokens/s 숫자만 남는다. 결국 소비자 입장에서는 비교 불가능한 숫자들을 비교하는 셈이 된다.
GPU 오프로드 비율과 배치 크기가 숫자를 뒤바꾼다
가장 흔한 함정은 GPU 오프로드 비율을 명시하지 않는 것이다. llama.cpp의 --n-gpu-layers 옵션은 몇 개의 레이어를 GPU 메모리에 올릴지 결정한다. 70B 모델을 Q4_K_M으로 양자화해도 약 40GB가 필요한데, VRAM이 24GB밖에 없는 RTX 3090 사용자라면 절반 정도만 GPU에 올리고 나머지는 CPU에서 처리하게 된다. 이 상태에서 측정한 속도와 모든 레이어를 VRAM에 올린 A100 사용자의 속도를 같은 줄에 놓고 비교하는 것은 의미가 없다. 그런데 커뮤니티 벤치마크 대다수가 바로 이런 식으로 공유된다.
두 번째는 배치 크기(batch size) 문제다. 단일 사용자가 대화형으로 쓸 때는 배치 크기 1이 기본이 되지만, 팀 서버나 API 서비스로 여러 사용자 요청을 동시에 처리할 때는 배치 크기 8, 16, 32로 올라간다. 배치 크기가 커질수록 GPU 병렬 처리 효율이 높아져 총처리량(throughput)은 늘지만, 개별 요청의 첫 토큰까지 걸리는 시간(latency)은 늘어난다. 배치 1 기준으로 “초당 90토큰”이라고 발표한 벤치마크가 실제 멀티 유저 환경에서는 처리량 측면에서 훨씬 좋은 성능을 낼 수도 있고, 반대로 latency가 핵심인 서비스라면 수치가 크게 달라 보일 수도 있다. 어느 쪽으로 최적화된 숫자인지 모르면 둘 다 믿기 어렵다.
써멀 쓰로틀링과 측정 시점의 문제
맥북 M 시리즈 사용자라면 더 주의해야 한다. Apple Silicon은 냉각 설계의 한계상 지속적으로 고부하가 걸리면 클럭을 낮추는 써멀 쓰로틀링(thermal throttling)이 발생한다. 처음 실행 직후에는 풀 클럭으로 돌아가다가, 5~10분 후에는 20~30% 낮은 성능을 내는 경우가 흔하다. 만약 누군가가 모델을 막 올린 직후 첫 번째 측정값만 기록했다면, 지속 실행 환경에서의 실제 체감 성능보다 상당히 높게 나온다. 공정한 비교를 위해서는 모델이 완전히 로드된 뒤 일정 시간 워밍업을 거치고, 칩 온도가 안정화된 상태에서 여러 번 반복 측정한 평균을 써야 한다.
비슷한 맥락에서 프롬프트 캐싱(KV 캐시) 효과도 간과되기 쉽다. 동일한 시스템 프롬프트나 컨텍스트를 반복적으로 사용하는 경우, 두 번째 이후 실행은 캐시 히트로 처리 시간이 크게 줄어든다. 첫 번째 실행과 다섯 번째 실행의 속도는 같은 하드웨어, 같은 모델이라도 눈에 띄게 다를 수 있다. 벤치마크가 “콜드 스타트” 기준인지, “워밍업 후” 기준인지 밝히지 않으면 사실상 반쪽짜리 정보다.
양자화 레이블의 불일치, 그리고 컨텍스트 길이
“Q4_K_M”이라고 쓰여 있어도 안심할 수 없다. 양자화 명세는 커뮤니티 컨버터나 도구 버전에 따라 세부 구현이 다를 수 있고, 같은 레이블을 쓰더라도 실제 비트 할당 방식이나 블록 크기가 미묘하게 달라지는 경우가 있다. Hugging Face에 올라온 동일 이름의 파일도 업로더가 누구냐에 따라 결과물이 다를 수 있다. 특히 GGUF 포맷이 빠르게 진화하면서 llama.cpp의 오래된 빌드와 최신 빌드 사이에서 동일 파일의 처리 속도나 품질이 달라지는 현상도 보고된다.
이미지 출처: Unsplash
컨텍스트 길이도 흔히 빠지는 항목이다. 512토큰짜리 짧은 프롬프트로 측정한 속도와 4096토큰, 심지어 32K 토큰 컨텍스트에서 측정한 속도는 상당히 다르다. 어텐션 연산이 컨텍스트 길이의 제곱에 비례해 늘어나기 때문이다. 코드 리뷰나 긴 문서 요약처럼 실제로 긴 컨텍스트를 쓸 계획이라면, 512 토큰 기준 벤치마크는 거의 참고 가치가 없다. 그런데도 대부분의 커뮤니티 측정은 편의상 짧은 프롬프트를 쓴다.
그렇다면 어떻게 측정해야 할까
신뢰할 수 있는 수치를 얻으려면 몇 가지 원칙이 필요하다. 우선 조건을 투명하게 명시해야 한다. GPU 레이어 수, 배치 크기, 컨텍스트 길이, 양자화 방식과 도구 버전, 측정 횟수와 집계 방식(최솟값 제외 평균 등), 하드웨어 스펙을 모두 적어야 한다. 측정은 써멀이 안정된 상태에서 최소 5회 이상 반복하고 평균을 낸다. 첫 번째 실행은 KV 캐시 영향 분석 목적이 아니라면 버리는 것이 낫다.
어느 정도 신뢰도 있는 자료를 찾고 싶다면, llama.cpp 공식 저장소의 GitHub Discussions와 이슈 섹션에서 검색하면 측정 조건이 비교적 잘 기록된 토론을 찾을 수 있다. Simon Willison의 블로그(simonwillison.net)는 로컬 LLM 실험 결과를 조건과 함께 꼼꼼히 기록하는 편이다. elarson이 운영하는 local-llm-benchmark 류의 GitHub 레포들도 조건 명시 측면에서 커뮤니티 스레드보다 낫다. 다만 어떤 공개 벤치마크든 내 환경과 완전히 일치하지 않을 수 있다는 점은 전제로 깔아야 한다.
결국 로컬 LLM 벤치마크에서 숫자만 보는 습관을 버리는 것이 출발점이다. 앞으로 로컬 LLM 생태계가 성숙해지면서 조건 표준화를 위한 공개 벤치마크 프레임워크가 자리를 잡을 가능성은 있다. 실제로 MLCommons 같은 단체가 엣지·온디바이스 모델 평가 기준 마련에 관심을 보이고 있고, 런타임 간 재현 가능한 비교를 위한 도구도 조금씩 등장하고 있다. 그 시점이 오기 전까지는, 숫자보다 “어떤 조건에서 나온 숫자인가”를 먼저 확인하는 것이 훨씬 현명한 접근이다.
출처