6GB 그래픽카드에 긴 문서 넣기: 8B는 답이 3분의 1로 느려지고, 4B는 4배 빨랐다
로컬 LLM에 긴 문서를 넣고 요약·질문을 하려면 두 가지 시간이 걸립니다. 문서를 읽는 시간(프롬프트 처리)과, 읽은 뒤 답을 쓰는 속도(생성)입니다. 짧은 질문으로 잰 "41 tok/s" 같은 숫자에는 둘 다 드러나지 않습니다. GTX 1660 SUPER 6GB에서 Qwen3 8B·4B-instruct(Q4_K_M)에 약 1천~8,700토큰 분량의 한국어 문서를 직접 넣어 봤습니다.
결론부터 정리하면 이렇습니다.
- 한국어 1만 2천 자(약 8,500토큰)를 8B가 읽는 데 110초가 넘게 걸렸습니다. Ollama의 읽기 속도는 초당 77~105토큰이었습니다.
- 문서가 길수록 답을 쓰는 속도도 떨어졌습니다. 약 1천 토큰 문서에서 34~38 tok/s이던 속도가 약 3,500토큰에서 22 tok/s, 약 8,500토큰에서 12 tok/s가 됐습니다.
- num_ctx가 문서보다 작으면 Ollama는 문서를 자릅니다. API 응답에는 오류도 경고도 없었고, 잘린 부분에 있던 숫자를 물으니 모델은 틀린 숫자를 답했습니다.
- 긴 문서에는 4B-instruct에
num_gpu 99를 넣은 조합이 가장 좋았습니다. 같은 1만 2천 자 문서를 약 55초에 읽고(8B의 약 2배), 초당 약 51토큰으로 답했습니다(8B의 약 4배). - llama.cpp Vulkan 빌드는 문서를 2.6~3.2배 빨리 읽었습니다. 대신 8K 토큰에서는 그래픽 메모리가 모자라 아예 실행되지 않았습니다.
한눈에 보는 결과
Ollama 0.34.4, num_gpu 99로 모든 층을 그래픽카드에 올린 Qwen3 8B, num_ctx 16384에서 잰 값입니다. 문서 길이마다 2번씩 쟀습니다.
| 문서 길이 (한국어) | 실제 토큰 수 | 읽는 시간 | 읽기 속도 | 답 쓰는 속도 | 숨긴 숫자 찾기 |
|---|---|---|---|---|---|
| 약 1,400자 | 983~1,045 | 9.3~12.1초 | 86~105 tok/s | 34.0~38.4 tok/s | 2/2 성공 |
| 약 4,800자 | 3,490~3,565 | 36.8~37.8초 | 94~95 tok/s | 21.9~22.2 tok/s | 2/2 성공 |
| 약 12,000자 | 8,524~8,672 | 110.4~113.1초 | 77 tok/s | 12.1~12.2 tok/s | 2/2 성공 |
| 약 12,000자, num_ctx 8192 | 4,098 (잘림) | 43.7초 | 94 tok/s | 20.5~24.9 tok/s | 0/2 (틀린 답) |
- 문서는 동네 소식 문장 25개 중에서 무작위로 뽑아 이어 붙이고, 문장 속 숫자를 무작위로 바꿔 만든 한국어 글입니다. 실행마다 다른 문서를 쓰고, 측정마다 모델을 내렸다가 다시 올려서 앞 실행의 계산을 재사용하지 못하게 했습니다. 설정을 바꿔 비교할 때는 같은 길이끼리 같은 문서를 썼습니다.
- 숨긴 숫자 찾기는 문서 한가운데에 "우체국 비밀 코드는 ○○○○이다"라는 문장을 하나 넣고(네 자리 숫자), 끝에서 "위 글에서 우체국 비밀 코드는? 숫자만 답하세요."라고 물은 결과입니다.
- 글자 수에는 공백과 줄바꿈이 포함됩니다. 이 문서에서 Qwen3는 토큰 하나에 1.34~1.41자를 담았습니다. 한국어 문서가 몇 토큰인지 어림할 때는 "글자 수 ÷ 1.4"로 보면 됩니다.
테스트 환경과 방법
- CPU: Intel Core i9-10900K, RAM: 32GB (3200MHz)
- 그래픽카드: NVIDIA GeForce GTX 1660 SUPER 6GB (6,144MB), 드라이버 591.86, Windows 11 Home
- 실행기: Ollama 0.34.4. 주 모델은
qwen3:8b(Q4_K_M)에PARAMETER num_gpu 99를 넣어 만든 모델이고, 비교용으로qwen3:8b기본 설정과qwen3:4b-instruct(Q4_K_M)를 썼습니다. - 비교용: llama.cpp CUDA 빌드 b11193, Vulkan 빌드 b11175(winget 설치본). Ollama가 받아 둔 모델 파일을 그대로 넣었습니다.
- 메모리 크기는
nvidia-smi와 같은 방식(MB = 1,048,576바이트)으로 적었습니다.
Ollama 측정은 API로 문서를 보내고, 응답에 들어 있는 prompt_eval_count(읽은 토큰 수), prompt_eval_duration(읽은 시간), eval_count·eval_duration(생성)으로 계산했습니다. 생각 기능은 끄고(think: false), temperature 0, 답은 최대 64토큰입니다. 모델을 불러오는 첫 실행은 뺐습니다. llama.cpp는 llama-bench로 쟀습니다. 읽기 속도는 -p 512,2048,4096,8192 -n 0 -r 2 -ngl 99, 채워진 문맥에서의 생성 속도는 -p 0 -n 64 -d 0,2048,4096,8192 -r 2 -ngl 99입니다(-d는 미리 채워 둔 토큰 수). 플래시 어텐션은 기본값, -fa 1, -fa 0 세 가지로 따로 쟀습니다. 비교할 때는 빌드, 설정, 문서 길이, 모델 중 한 가지만 다른 값끼리 비교했습니다.
긴 문서를 읽는 데 걸리는 시간
읽기 속도만 따로 떼어 llama.cpp로 재 보면 빌드에 따라 차이가 컸습니다.
| 프롬프트 길이 | CUDA (기본값) | CUDA, 플래시 어텐션 켜기 | CUDA, 플래시 어텐션 끄기 | Vulkan |
|---|---|---|---|---|
| 512토큰 | 137.0 tok/s | 137.9 tok/s | 122.5 tok/s | 359.3 tok/s |
| 2,048토큰 | 129.3 tok/s | 130.3 tok/s | 93.6 tok/s | 353.6 tok/s |
| 4,096토큰 | 101.6 tok/s | 100.4 tok/s | 52.7 tok/s | 327.9 tok/s |
| 8,192토큰 | 83.0 tok/s | 83.8 tok/s | 29.2 tok/s | 실행 실패 (메모리 부족) |
- Vulkan이 2.6~3.2배 빨랐습니다. 4,096토큰 문서라면 CUDA 약 40초, Vulkan 약 12.5초입니다.
- 플래시 어텐션은 켜져 있어야 합니다.
llama-bench의 기본값(auto)은 강제로 켠 것(-fa 1)과 차이가 1.1% 이내였고, 강제로 끄면(-fa 0) 문서가 길수록 크게 느려졌습니다. 8,192토큰에서는 83.0 → 29.2 tok/s였습니다. 기본값에서 이미 켜져 있었던 것으로 보입니다. - Ollama의 읽기 속도는 CUDA 빌드보다 조금 낮았습니다. 약 1천 토큰에서 86~105 tok/s(CUDA 빌드는 512~2,048토큰에서 129~137 tok/s), 약 8,500토큰에서 77 tok/s(CUDA 빌드 8,192토큰 83 tok/s)였습니다.
생성 속도는 반대로 CUDA 빌드가 빨랐습니다. CUDA·Vulkan 비교 글에서 256토큰 생성은 CUDA가 11~20%(Qwen3 8B는 17%) 빨랐고, 이번 측정에서도 문맥이 비어 있을 때 21%, 4,096토큰을 채웠을 때 5% 빨랐습니다. CUDA 빌드는 실행할 때마다 "텐서 코어가 없어 성능이 최적이 아니다"라는 경고를 냈습니다. GTX 1660 SUPER는 RTX가 아니라서 텐서 코어가 없습니다. 이 경고와 느린 읽기 속도가 관련 있는지는 확인하지 못했습니다.
Vulkan이 8,192토큰에서 실패한 것은 그래픽 메모리 할당 오류(ErrorOutOfDeviceMemory)였습니다. 마이크로배치를 256으로 줄여(-ub 256) 다시 해 봤지만 8,192토큰은 여전히 실패했고, 4,096토큰 읽기 속도는 32.1 tok/s로 오히려 크게 떨어졌습니다. 이유는 확인하지 못했습니다.
문서가 길수록 답이 느려지는 이유
llama.cpp로, 문맥을 미리 채워 둔 상태에서 64토큰을 생성해 봤습니다.
| 이미 채워진 토큰 | CUDA (기본값) | CUDA, 플래시 어텐션 켜기 | CUDA, 플래시 어텐션 끄기 | Vulkan |
|---|---|---|---|---|
| 0 | 47.1 tok/s | 46.4 tok/s | 41.5 tok/s | 38.8 tok/s |
| 2,048 | 40.1 tok/s | 39.8 tok/s | 21.4 tok/s | 36.7 tok/s |
| 4,096 | 36.1 tok/s | 35.8 tok/s | 6.2 tok/s | 34.5 tok/s |
| 8,192 | 13.2 tok/s | 13.2 tok/s | 2.2 tok/s | 실행 실패 (메모리 부족) |
기본값(플래시 어텐션이 켜진 것으로 보이는 상태)에서는 4,096토큰까지 조금씩 느려지다가 8,192토큰에서 갑자기 약 3분의 1로 떨어집니다. Vulkan은 바로 그 지점에서 메모리 부족으로 멈췄습니다.
플래시 어텐션을 끄면 훨씬 일찍, 훨씬 크게 느려졌습니다. 4,096토큰에서 6.2 tok/s, 8,192토큰에서 2.2 tok/s입니다. 2,048토큰 값(21.4 tok/s)은 두 번 측정의 표준편차가 6.0 tok/s로 커서 참고만 해 주세요. 다만 이 측정(-fa 0) 때는 시작할 때 그래픽 메모리 사용량이 632~830MB로 앞 측정(약 480~510MB)보다 많았고, 플래시 어텐션을 끄면 계산용 작업 공간도 더 필요합니다. 그래서 순수한 플래시 어텐션 효과에 메모리 부족 효과가 섞였을 수 있습니다.
그래픽 메모리 계산이 이 결과와 맞아떨어집니다. Qwen3 8B는 토큰 하나를 기억하는 데 144KB(147,456바이트)를 씁니다(36층 × KV 헤드 8개 × 128차원 × K·V 2개 × 2바이트, 모델 설정 기준). 8,192토큰이면 1,152MB입니다. 모델 파일(약 4,977MB, llama-bench 표시로 4.86GiB)에 이것을 더하면 약 6,129MB로, 카드 전체 6,144MB에 거의 닿습니다. 여기에 바탕화면이 쓰던 약 500MB와 계산용 작업 공간까지 더하면 넘칩니다. 4,096토큰(576MB)까지는 들어갑니다.
- Vulkan 빌드는 모자라면 바로 실패합니다.
- CUDA 빌드는 실패하지 않고 계속 돌았습니다. 윈도우의 NVIDIA 드라이버는 그래픽 메모리가 모자라면 시스템 메모리를 빌려 쓸 수 있고(NVIDIA 안내, NVIDIA 제어판의 "CUDA - Sysmem Fallback Policy" 설정), 이 방식은 훨씬 느립니다. 속도가 뚝 떨어진 이유는 이것일 가능성이 큽니다.
Ollama에서는 약 3,500토큰 문서에서 이미 22 tok/s로, 약 1천 토큰 문서(34~38 tok/s)보다 크게 느렸습니다. 측정 중 윈도우의 공유 GPU 메모리 사용량(작업 관리자에 나오는 값)도 함께 기록했는데, 그래픽 메모리가 5,822~5,902MB로 거의 가득 찬 상태에서 공유 GPU 메모리는 num_ctx 16384일 때 약 2,233MB, num_ctx 8192일 때 약 1,137MB였습니다. 위 계산의 16,384토큰 몫(2,304MB), 8,192토큰 몫(1,152MB)과 비슷합니다. 약 1천 토큰짜리 짧은 문서에서도 같은 양이었으니, 문서 길이가 아니라 num_ctx만큼 자리를 미리 잡는 것으로 보입니다. 문맥 저장 공간의 상당 부분이 시스템 메모리로 넘어갔을 가능성이 있습니다. 다만 아래 한계에 적었듯 이 해석과 맞지 않는 측정도 있어서, 원인을 확정하지는 못했습니다.
짧은 질문만 던져 보면 이 차이가 안 보입니다. 같은 모델에 num_ctx만 4K에서 32K로 바꾸며 짧은 질문을 던졌을 때는 42.6~43.3 tok/s에서 40.0~40.3 tok/s로 약 6~7%만 줄었습니다. ollama ps는 모델 크기를 5.6GB에서 9.8GB로 표시하면서도 계속 "100% GPU"라고 나왔습니다. "100% GPU"라는 표시와 짧은 질문 속도만 보고 긴 문서도 빠를 거라고 기대하면 안 됩니다.
num_ctx보다 긴 문서는 조용히 잘립니다
같은 1만 2천 자 문서를 num_ctx 8192로 넣었더니, Ollama가 읽은 토큰은 두 번 모두 정확히 4,098개였습니다. 같은 문서를 num_ctx 16384로 넣었을 때 8,524~8,672토큰이었으니 절반 넘게 버려진 셈입니다. num_ctx(8,192)만큼이 아니라 그 절반 정도만 남은 이유는 확인하지 못했습니다. API 응답에는 오류나 경고가 없었습니다(Ollama 서버 로그는 확인하지 않았습니다).
문서 한가운데 숨긴 숫자를 물었더니 두 번 모두 틀렸습니다. 한 번은 "425", 한 번은 "우체국 비밀 코드는 45입니다"라고 답했는데, 실제 코드는 네 자리 숫자였습니다. 질문이 "숫자만 답하세요"여서 모른다고 답하기 어려운 조건이긴 했지만, 오류 없이 그럴듯한 답이 나온다는 점이 문제입니다. num_ctx 16384에서는 같은 문서로 두 번 모두 맞혔습니다.
긴 문서를 넣을 때는 문서 토큰 수(한국어 글자 수 ÷ 1.4) + 답변 길이보다 num_ctx를 크게 잡아야 합니다. 결과가 이상하면 API 응답의 prompt_eval_count가 문서 길이만큼 나왔는지 확인해 보세요.
긴 문서가 필요하면: 세 가지 방법을 시험했습니다
① 모델을 4B로 줄이기, ② 모든 층을 그래픽카드에 올리는 설정(num_gpu 99) 빼기, ③ 문맥 저장 공간 압축(KV 캐시 q8_0) 세 가지를 하나씩 바꿔 봤습니다.
먼저 Ollama에 같은 1만 2천 자 문서(약 8,500토큰)를 num_ctx 16384로 넣은 결과입니다.
| 모델 · 설정 | CPU/GPU 분담 | 읽는 시간 | 답 쓰는 속도 | 숨긴 숫자 찾기 |
|---|---|---|---|---|
| 8B, num_gpu 99 | 100% GPU | 110.4~113.1초 | 12.1~12.2 tok/s | 2/2 성공 |
| 8B, 기본 설정 | 46% / 54% | 87.4~90.1초 | 6.4~6.6 tok/s | 2/2 성공 |
| 4B-instruct, 기본 설정 | 21% / 79% | 54.5~55.9초 | 17.5~17.9 tok/s | 2/2 성공 |
| 4B-instruct, num_gpu 99 | 100% GPU | 53.6~55.4초 | 50.9~51.0 tok/s | 2/2 성공 |
- 4B-instruct에
num_gpu 99를 넣은 조합이 가장 빨랐습니다. 8B(num_gpu 99)보다 읽기는 약 2배, 답은 약 4.2배 빨랐고, 숨긴 숫자도 두 번 모두 찾았습니다. - 4B-instruct도
num_ctx 16384에서는 Ollama가 모델의 21%를 CPU 쪽에 둡니다(ollama ps표시).num_gpu 99로 전부 그래픽카드에 올리니 답 쓰는 속도가 17.5~17.9에서 50.9~51.0 tok/s로 약 2.9배가 됐습니다. 이때 그래픽 메모리는 5,352MB, 공유 GPU 메모리는 436MB였습니다. - 8B에서
num_gpu 99를 빼면 Ollama가 모델의 46%를 CPU 쪽에 둡니다. 읽는 시간은 약 23초 줄었지만 답 쓰는 속도가 절반이 됐습니다. 긴 문서에서도 8B라면num_gpu 99를 넣는 쪽이 나았습니다.
다음은 llama.cpp CUDA 빌드로, 문맥을 미리 채운 상태의 생성 속도입니다.
| 이미 채워진 토큰 | 8B, 플래시 어텐션 켜기 | 8B, 플래시 어텐션 켜기 + KV 캐시 q8_0 | 4B-instruct 기본값 |
|---|---|---|---|
| 0 | 46.4 tok/s | 46.2 tok/s | 78.5 tok/s |
| 4,096 | 35.8 tok/s | 38.4 tok/s | 55.8 tok/s |
| 8,192 | 13.2 tok/s | 18.0 tok/s | 43.9 tok/s |
| 12,288 | — | 5.7 tok/s | — |
| 16,384 | — | — | 30.1 tok/s |
- 4B-instruct는 1만 6천 토큰을 채워도 30 tok/s였습니다. 토큰 하나를 기억하는 데 드는 공간은 8B와 같지만(36층 × KV 헤드 8개 × 128차원, 모델 설정 기준), 모델 파일이 2.32GiB로 8B(4.86GiB)의 절반이라 문맥을 담을 그래픽 메모리가 남습니다. 비교 기준인 8B 기본값(표 위쪽의 "CUDA (기본값)")은 같은 지점에서 47.1 / 36.1 / 13.2 tok/s였습니다.
- KV 캐시를 q8_0으로 압축하면 문맥 저장 공간이 약 절반(16비트 대비 53%)이 됩니다. 8,192토큰에서 18.0 tok/s로, 압축하지 않았을 때(13.2 tok/s)보다 36% 빨랐습니다. 하지만 12,288토큰에서는 5.7 tok/s까지 떨어져, 떨어지는 지점을 조금 뒤로 미루는 정도였습니다. V 캐시를 압축하려면 플래시 어텐션이 켜져 있어야 해서, 여기서는
-fa 1을 같이 줬습니다. - 이 표(llama-bench)와 위 Ollama 표는 측정 도구가 달라서, 숫자끼리 직접 비교하지는 마세요. 같은 도구 안에서의 차이만 보면 됩니다.
- Ollama FAQ에 따르면 Ollama는 호환되는 모델에서 플래시 어텐션을 자동으로 켜고, 서버 환경 변수
OLLAMA_KV_CACHE_TYPE=q8_0으로 같은 압축을 켤 수 있습니다(모든 모델에 한꺼번에 적용). 이번에는 llama.cpp에서만 시험했습니다.
6GB 그래픽카드로 긴 문서를 다룬다면
- 8B는 약 4,000토큰(한국어 약 5,600자)까지가 무난합니다. 8천 토큰대 문서면 읽는 데 약 2분, 답은 초당 12토큰 수준이었습니다.
- 그보다 긴 문서는 4B-instruct +
num_gpu 99가 낫습니다. 1만 2천 자 문서를 약 55초에 읽고 초당 약 51토큰으로 답했으며, 숨긴 숫자도 찾았습니다. 두 모델의 한국어 답변 품질은 짧은 과제 8개 기준 5점 만점에 8B 4.15점, 4B-instruct 4.10점으로 거의 같았습니다(한국어 LLM 비교 글). - num_ctx는 문서보다 넉넉하게, 하지만 필요 이상 크게 잡지는 마세요. 작으면 문서가 잘리고, 크면 짧은 문서에도 그만큼 자리를 미리 잡습니다.
- llama.cpp를 직접 쓴다면 플래시 어텐션을 끄지 마세요. 기본값(auto)이면 켜집니다. 끄고 쟀더니 8,192토큰 문맥에서 답이 초당 2.2토큰까지 느려졌습니다(메모리 부족 효과가 섞였을 수 있음).
- 문서를 많이 읽히는 작업이라면 llama.cpp Vulkan 빌드가 유리합니다. 4,096토큰까지는 읽기가 약 3배 빠릅니다. 다만 8K 토큰부터는 메모리 부족으로 실행되지 않았습니다.
- 긴 문서에서 느리다면 작업 관리자를 보세요. 성능 → GPU에서 전용 GPU 메모리가 가득 차 있고 공유 GPU 메모리가 올라가 있다면, 시스템 메모리로 넘어갔을 가능성을 의심해 볼 만합니다.
한계
- 그래픽카드 한 종류(GTX 1660 SUPER 6GB)와 Qwen3 8B·4B-instruct로만 측정했습니다. 그래픽 메모리가 8GB 이상인 카드에서는 속도가 떨어지는 지점이 더 뒤로 밀릴 것으로 예상되지만, 재 보지는 않았습니다.
- 문서는 같은 문장들을 섞어 만든 글이고, 품질은 "숨긴 숫자 하나 찾기"로만 봤습니다. 실제 긴 보고서를 요약하는 품질은 따로 봐야 합니다.
- 시스템 메모리로 넘어갔다는 설명은 속도가 떨어지는 지점, Vulkan의 메모리 부족 오류, 메모리 계산에서 추정한 것입니다. 드라이버 내부 동작을 직접 확인한 것은 아닙니다. 특히 Ollama의 공유 GPU 메모리 값은 해석이 어렵습니다. 8B 기본 설정에서는 그래픽 메모리가 4,650MB로 여유가 있었는데도 공유 GPU 메모리가 약 2,430MB였고, 4B-instruct(
num_gpu 99)는 같은num_ctx 16384에서 436MB였습니다. 이 값이 문맥 저장 공간만을 뜻하는지는 알 수 없습니다.