
컨텍스트가 채워짐에 따라 로컬 LLM의 속도를 몰래 갉아먹는 것은 무엇인가 - 파트 1
요약
로컬 LLM 사용 시 컨텍스트 길이가 길어짐에 따라 발생하는 급격한 성능 저하 원인을 분석합니다. KV 캐시가 VRAM 용량을 초과하여 시스템 RAM으로 넘어가는 'Spilling' 현상이 주요 원인임을 설명합니다.
핵심 포인트
- 컨텍스트 증가에 따른 생성 및 프롬프트 처리 속도 저하 현상 분석
- KV 캐시가 VRAM 용량을 초과할 때 발생하는 Spilling 문제
- VRAM과 시스템 RAM 간의 데이터 이동이 성능에 미치는 영향
- 로컬 환경에서 최적의 컨텍스트 설정을 위한 메모리 관리의 중요성
모델을 로컬에서 사용하다가 갑자기 성능이 떨어지는 것을 경험해 본 적이 있나요?
오늘은 그 문제에 대해 이야기해보고자 합니다.
저는 주어진 사양의 컴퓨터에서 로컬 LLM(Large Language Model)을 위한 최적의 설정을 결정하는 데 도움을 주는 오픈 소스 도구를 만들고 있습니다. 이 문제는 단순해 보이지만 정말 까다로워서 저를 꽤나 고민하게 만들었습니다.
우선, 모델이 VRAM(Video RAM) 예산에서 차지하는 할당량을 결정해야 합니다. 설명을 쉽게 하기 위해, 제가 이 특정 문제를 테스트하기 위해 사용해 온 모델인 Qwen 3.5 9B Q4_K_M을 사용하겠습니다. 제 하드웨어 사양은 다음과 같습니다: 8GB VRAM을 탑재한 RTX 2070, 24GB RAM.
Qwen을 로드했습니다. 모델은 제 VRAM에 자리 잡았지만, 저는 16k에서 32k 사이의 매우 제한적인 최대 컨텍스트(Context)를 설정했고, 일부 메모리는 여유 공간으로 남겨두었습니다. 저는 스스로에게 물었습니다: 하지만 왜 이런 일이 발생하는 걸까요?
로컬 모델을 실행하기 위해 사용하는 이 앱들은 현재 컴퓨터의 조건에 맞춰 모델이
계산을 좀 해보자면, 8GB는 8192MB입니다. 배경에서 듣고 있는 유튜브 팟캐스트가 GPU의 500-800 MB를 사용하고 있다는 것을 알고 있다고 가정하고, 그것을 종료합니다.
시스템이 0.5에서 1GB를 예약합니다. 지금 윈도우(Windows)를 기준으로 이야기하고 있으니까요. 그래서 안전하게 계산하면... 7000MB를 사용할 수 있겠네요?
Qwen은 6.8GB를 사용하므로 괜찮습니다. 131k의 컨텍스트 (Context)를 로드하고 채팅 인터페이스를 사용하기 시작하면 모든 것이 정상적으로 작동합니다!
잘 작동합니다! 그 골치 아픈 문제를 우회했고, 이제 모델의 전체 컨텍스트를 사용할 수 있습니다.
본격적으로 사용하기 시작하면 컨텍스트가 30k, 40k, 50k로 올라갑니다. 어느 시점에 60k에 도달하면 조금 느려지는 것이 느껴지기 시작합니다. 70k가 되면 훨씬 더 느려지는데, 이는 일반적인 속도 저하가 아니라 생성 (Generation) 단계와 프롬프트 처리 (Prompt processing) 단계 모두에서 매우 강력한 성능 저하가 발생합니다. 90k에 도달하면 속도가 32 tok/sec에서 16 tok/sec로 떨어지며, 초기 488 tok/sec에서 41.01 tok/sec로 떨어진 것을 고려하면 프롬프트 처리는 훨씬 더 큰 타격을 입습니다. 새로운 채팅을 시작하면 다시 쾌적하게 느껴지지만, 80-90k에 도달하면 동일한 문제가 발생합니다. 무슨 일이 일어나고 있는 걸까요? 왜 작동하다가 어느 순간부터 안 되는 걸까요?
그것은 바로 KV 캐시 (KV cache)가 VRAM에서 RAM으로 넘쳐흐르는 (Spilling) 현상 때문입니다. 컨텍스트가 커지면, 어느 시점에서 프롬프트와 응답이 GPU에서 RAM으로 이동하게 됩니다. 이러한 문제를 완전히 피하기 위해 대부분의 애플리케이션은 제한된 컨텍스트를 사용합니다. 윈도우(Windows)는 가끔 마법 같아서 메모리 부족(Out of memory) 상태에 빠지지 않고, 공유 메모리 (Shared memory)를 사용하여 임계 상황을 관리합니다.
VRAM에 있는 첫 번째 메모리 영역은 매우 빠르게 응답하지만, 특정 양의 컨텍스트에 도달하는 순간 평가 (Eval) 속도가 급격히 떨어지며 결국 모델을 약 50% 더 느린 속도로 사용하게 됩니다.
다음 파트에서는 제가 이것을 어떻게 알아차리기 시작했는지, 무엇이 제대로 작동하지 않았는지 공유할 것이며, 파트 3에서는 이를 관리하기 위해 제가 적용한 해결책들을 공유하겠습니다.
위 차트를 만드는 데 사용된 실행 데이터들입니다.
Qwen 3.5 9B (131k 컨텍스트)
| 사용된 KV (Used KV) | 평가 t/s (Eval t/s) | 8k 대비 차이 (Delta from 8k) | 프롬프트 t/s (Prompt t/s) |
|---|---|---|---|
| 8k | 42.30 | 기준점 (Baseline) | 488.25 |
| ... | |||
| Qwen 3.5 2B (131k 컨텍스트) |
| 사용된 KV (Used KV) | 평가 t/s (Eval t/s) | 8k 대비 차이 (Delta from 8k) | 프롬프트 t/s (Prompt t/s) |
|---|---|---|---|
| 8k | 103.49 | 기준점 (Baseline) | 3902.12 |
| ... | |||
| _*이미지 속 데이터 - 차트의 녹색 선 - 는 동일한 컨텍스트에서 완전히 VRAM 내에 머무를 것임을 알고 있는 모델인 Qwen 3.5 2B Q4_K_M을 사용하여 생성 속도에 대해 수행한 대조 테스트 결과입니다._ |
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기