Published on

Ollama 로컬 LLM이 GPU를 안 쓰는 이유 9가지

Authors

서론

로컬에서 Ollama로 LLM을 돌리면 당연히 GPU가 붙을 거라고 기대하지만, 막상 nvidia-smi를 보면 사용률이 0%이거나, 추론 속도가 CPU 수준에서 벗어나지 못하는 경우가 많습니다. 이 문제는 단순히 “GPU가 느리게 잡혔다”가 아니라, 드라이버/런타임/백엔드(ggml/gguf)/빌드 플래그/모델 양자화/레이어 오프로딩 설정/권한/컨테이너 런타임 등 여러 층에서 발생합니다.

이 글에서는 “Ollama가 GPU를 안 쓰는” 상황을 9가지 대표 원인으로 분해하고, 각 원인별로 확인 명령어와 해결 방향을 함께 제공합니다. (NVIDIA 중심으로 설명하지만, AMD/Apple Silicon도 핵심 포인트는 유사합니다.)


1) GPU 자체가 OS에서 정상 인식되지 않음 (드라이버/커널 모듈 문제)

가장 기본인데도 의외로 자주 걸립니다. Ollama 이전에 OS 레벨에서 GPU가 정상 노출되어야 합니다.

체크

# GPU 존재/드라이버 로드 확인
lspci | grep -i nvidia

# NVIDIA 드라이버 동작 확인
nvidia-smi

# 커널 모듈 상태
lsmod | grep nvidia
  • nvidia-smi가 실패하면 Ollama는 GPU를 쓸 수 없습니다.
  • WSL2라면 Windows 드라이버 + WSL CUDA 스택이 맞아야 하고, 리눅스라면 커널/드라이버 버전 호환이 중요합니다.

해결 방향

  • 드라이버 재설치/업그레이드
  • Secure Boot 환경에서 커널 모듈 서명 문제 여부 확인
  • WSL2는 WSL용 NVIDIA 드라이버와 CUDA 호환 버전 확인

2) 컨테이너/원격 환경에서 GPU 패스스루가 안 됨 (Docker, Kubernetes)

Ollama를 Docker로 실행하거나 K8s에 올려 쓰는 경우, GPU는 호스트에 있는데 컨테이너 안에는 없는 상황이 흔합니다.

Docker 체크

docker run --rm --gpus all nvidia/cuda:12.3.2-base-ubuntu22.04 nvidia-smi
  • 위가 실패하면 nvidia-container-toolkit 또는 런타임 설정 문제입니다.

Kubernetes 체크

kubectl describe node <node-name> | grep -i nvidia -n
kubectl get pods -A | grep -i nvidia
  • NVIDIA Device Plugin이 없거나, Pod spec에 resources.limits: nvidia.com/gpu가 없으면 GPU를 못 씁니다.
  • K8s에서 LLM을 서비스로 운영할 때는 타임아웃/스트리밍 이슈도 같이 터지기 쉬운데, 인그레스/프록시 튜닝은 별도 체크리스트가 필요합니다. 관련해서는 Kubernetes LLM 서비스 502 504 간헐 장애와 스트리밍 끊김 튜닝도 참고할 만합니다.

3) Ollama가 GPU 백엔드를 포함한 빌드/패키지가 아님

Ollama는 내부적으로 llama.cpp 계열(ggml/gguf)을 사용하며, GPU 가속은 빌드 옵션과 배포 방식에 따라 달라집니다.

  • Linux에서 패키지/바이너리 설치 방식에 따라 CUDA 지원이 빠질 수 있습니다.
  • 소스 빌드 시에도 CUDA/cuBLAS/Metal/ROCm 관련 옵션이 제대로 들어가야 합니다.

체크 포인트

  • Ollama 로그에 “CUDA backend” 또는 유사한 GPU 초기화 로그가 있는지 확인
  • 실행 파일이 어떤 라이브러리에 링크되는지 확인
# Linux에서 바이너리 링크 확인(환경에 따라 경로/파일명 다름)
ldd $(which ollama) | egrep 'cuda|cublas|nvidia' || true

해결 방향

  • 공식 설치 가이드에 맞는 바이너리 사용
  • GPU 지원이 포함된 릴리스/패키지인지 확인
  • 필요 시 GPU 지원 옵션으로 재설치/재빌드

4) 모델 포맷/양자화가 GPU 오프로딩에 불리하거나 제한됨

Ollama에서 자주 쓰는 모델은 GGUF 기반이고, 양자화 타입(Q4_K_M 등)에 따라 성능/메모리/가속 경로가 달라집니다.

  • 어떤 양자화는 GPU 오프로딩에서 효율이 떨어지거나, 특정 백엔드에서 최적화가 덜 되어 CPU에 더 의존하는 것처럼 보일 수 있습니다.
  • 특히 컨텍스트 길이가 길어질수록 KV 캐시가 커지고, VRAM 압박으로 인해 오프로딩이 줄거나 CPU fallback이 발생할 수 있습니다.

체크

  • 같은 모델을 다른 양자화로 바꿔 성능 비교
  • VRAM 사용량이 추론 중 급격히 늘었다가 GPU 사용이 꺼지는지 관찰
watch -n 0.5 nvidia-smi

해결 방향

  • VRAM이 충분하면 더 높은 정밀도/적절한 양자화 선택
  • 컨텍스트 길이/배치 크기 조정
  • 모델을 더 작은 파라미터로 변경

5) 레이어 오프로딩 설정이 0이거나 너무 낮음 (사실상 CPU 모드)

llama.cpp 계열은 보통 일부 레이어만 GPU로 보내는 방식(partial offload)을 씁니다. 오프로딩 레이어 수가 0이면 GPU는 안 씁니다.

Ollama는 내부 설정을 자동으로 잡는 편이지만, 환경/VRAM/모델에 따라 보수적으로 잡혀 CPU 위주로 동작할 수 있습니다.

체크 포인트

  • Ollama 로그에서 offload/layers 관련 메시지 확인
  • 실행 중 GPU 메모리 할당이 거의 없는지 확인

해결 방향

  • VRAM 여유를 확보(다른 프로세스 종료)
  • 더 작은 모델로 테스트해 오프로딩이 되는지 확인

6) VRAM 부족으로 GPU 초기화는 됐지만 곧 CPU fallback 발생

GPU를 “아예 안 쓰는” 것처럼 보이지만, 실제로는 잠깐 쓰다가 메모리 부족으로 내려오는 경우가 있습니다.

특히 다음이 겹치면 VRAM이 빠르게 소진됩니다.

  • 긴 컨텍스트(예: 8k~32k)
  • 큰 모델(예: 13B 이상)
  • 동시 요청(서빙)
  • 높은 배치/프리필(prefill) 부하

체크

# 추론 중 메모리 변동 관찰
nvidia-smi --query-gpu=timestamp,utilization.gpu,memory.used,memory.total --format=csv -l 1

해결 방향

  • 컨텍스트 길이 축소
  • 동시성 제한(큐잉)
  • 더 작은 모델/더 강한 양자화
  • GPU 메모리 점유 프로세스 정리

운영 환경에서 동시 요청을 늘리면 타임아웃/재시도 설계도 중요해집니다. 외부 API 얘기지만 패턴은 동일하므로 OpenAI Responses API 503 멈춤 - 재시도·폴백 설계의 접근을 로컬 서빙에도 그대로 적용할 수 있습니다.


7) 전력/클럭 제한 또는 PCIe 대역폭/링크 다운으로 GPU가 “놀고” 있음

GPU가 잡혀 있고 VRAM도 조금 쓰는데 utilization이 낮다면, 모델이 CPU에서 병목이거나, GPU가 저전력 상태로 고정되어 있을 수 있습니다.

체크

nvidia-smi -q -d POWER,CLOCK,PERFORMANCE

# PCIe 링크 상태(가능한 경우)
nvidia-smi -q | grep -i -E 'pcie|link' -n

해결 방향

  • 노트북/서버의 전력 정책 확인
  • pstate가 낮게 고정되는지 확인
  • PCIe 링크가 x16이 아닌 낮은 레인으로 협상되는지 점검(하드웨어/BIOS)

8) macOS/Apple Silicon에서 Metal 경로가 비활성화되었거나 모델/환경이 비호환

Apple Silicon(M1/M2/M3)은 CUDA가 아니라 Metal 경로를 타야 합니다.

  • Rosetta로 x86 바이너리를 실행 중이면 성능/가속 경로가 꼬일 수 있습니다.
  • 모델/빌드가 Metal 최적화를 제대로 활용하지 못하면 “GPU를 안 쓰는 것처럼” 느릴 수 있습니다.

체크

# 실행 아키텍처 확인
uname -m

# Rosetta 여부 확인(대표적인 방법 중 하나)
sysctl -n sysctl.proc_translated 2>/dev/null || echo "not rosetta"

해결 방향

  • arm64 네이티브 환경 사용
  • Ollama/런타임이 Metal을 사용하는지 로그 확인

9) 프로세스 격리/권한 문제로 GPU 디바이스 파일 접근 불가

리눅스에서는 /dev/nvidia0, /dev/nvidiactl 같은 디바이스에 접근해야 합니다. 보안 설정이 강한 환경(특히 컨테이너, systemd sandbox, SELinux/AppArmor)에서는 권한 문제로 GPU가 막힐 수 있습니다.

체크

ls -l /dev/nvidia*

# 컨테이너 내부에서 디바이스가 보이는지
docker exec -it <container> ls -l /dev/nvidia* 2>/dev/null || true

해결 방향

  • Docker: --gpus all 및 nvidia runtime 설정
  • K8s: device plugin/런타임 클래스 설정, 보안 정책(PSA/SELinux) 확인

빠른 진단용 체크리스트(요약)

아래 순서대로 보면 대부분 10분 내 원인이 좁혀집니다.

  1. nvidia-smi가 호스트에서 되는가?
  2. 컨테이너/WSL/K8s라면 그 안에서 nvidia-smi가 되는가?
  3. Ollama 로그에 GPU 백엔드 초기화 흔적이 있는가?
  4. 추론 중 nvidia-smi에서 VRAM이 늘어나는가?
  5. VRAM이 부족해 fallback 되는 패턴이 있는가?
  6. 모델/양자화/컨텍스트/동시성으로 병목이 생기지 않는가?
  7. 전력/클럭/PCIe 링크가 비정상적으로 낮지 않은가?
  8. (macOS) arm64/Metal 경로가 맞는가?
  9. 디바이스 파일/보안 정책으로 접근이 막히지 않았는가?

로그/모니터링을 붙이면 원인 파악이 빨라진다

GPU 미사용 문제는 “설정 한 줄”로 끝나는 경우도 있지만, 운영 환경에서는 관측 가능성이 없으면 재발하기 쉽습니다. 최소한 아래 정도는 붙여두면 좋습니다.

GPU 사용률/메모리 수집 예시

# 1초마다 CSV로 기록
nvidia-smi --query-gpu=timestamp,utilization.gpu,utilization.memory,memory.used,power.draw --format=csv -l 1 | tee gpu_metrics.csv

(서빙 시) 요청 지연/TTFB 관측

로컬 LLM도 SSE 스트리밍을 붙이면 프록시/버퍼링/idle timeout에 의해 “GPU는 도는데 클라이언트는 끊기는” 문제가 발생할 수 있습니다. 이런 케이스는 인프라 레벨 튜닝이 필요하며, LLM SSE 스트리밍 499 502 급증과 프록시 튜닝 체크리스트를 함께 보면 원인 분리가 쉬워집니다.


결론

Ollama에서 GPU가 안 붙는 이유는 크게 (1) GPU가 OS/컨테이너에 노출되지 않음, (2) GPU 백엔드가 포함되지 않은 빌드/런타임, (3) VRAM/모델/컨텍스트/동시성에 따른 오프로딩 실패, (4) 전력/권한/플랫폼(Metal/ROCm) 이슈로 정리됩니다.

가장 빠른 접근은 “호스트 → 컨테이너 → Ollama 로그 → 추론 중 VRAM 변동” 순서로 관찰 포인트를 줄이는 것입니다. 이 글의 9가지 체크를 따라가면, GPU를 정말 못 쓰는 상태인지(환경 문제) 아니면 쓰긴 쓰는데 효율이 안 나오는 상태인지(모델/오프로딩/메모리 문제)까지 명확히 구분할 수 있습니다.