LocalAI GPU Hızlandırma: CUDA ile Yüksek Performanslı AI Kurulumu

GPU’suz çalışan bir LocalAI kurulumu, özellikle büyük modellerde sabır testine dönüşüyor. 7B parametreli bir modelde basit bir prompt’a dakikalarca bekliyorsanız ve sunucunuzda bir NVIDIA kartı varsa, bu yazı tam size göre. CUDA entegrasyonu doğru yapılandırıldığında aynı model üzerinde 10x ile 30x arasında performans artışı görmek mümkün. Hadi bu işi düzgün yapalım.

CUDA Neden Bu Kadar Önemli?

LocalAI, arka planda llama.cpp, whisper.cpp ve benzeri kütüphaneleri kullanıyor. Bu kütüphaneler CPU üzerinde çalışabilir ama asıl güçleri GPU offloading’den geliyor. CUDA, NVIDIA’nın GPU’ları için geliştirdiği paralel hesaplama platformu. LLM inference sürecindeki matris çarpımları GPU’nun paralel işlem yetenekleri için biçilmiş kaftan.

Somut bir örnek verelim: Bir A100 GPU, 312 TFLOPS FP16 hesaplama gücü sunuyor. Buna karşılık modern bir sunucu CPU’su olan EPYC 7763, yaklaşık 2-3 TFLOPS civarında. Farkı görüyorsunuz. Elbette her ortamda A100 olmayacak, ama RTX 3090 veya A10 gibi kartlar bile CPU’ya kıyasla dramatik fark yaratıyor.

Ön Gereksinimler ve Ortam Kontrolü

Kuruluma geçmeden önce sisteminizi kontrol edelim. Yanlış CUDA sürümü, uyumsuz driver veya eksik kütüphane, saatlerinizi alabilir.

# NVIDIA driver kontrolü
nvidia-smi

# CUDA toolkit versiyon kontrolü
nvcc --version

# GPU bellek durumu
nvidia-smi --query-gpu=name,memory.total,memory.free --format=csv

# Kernel modülü yüklü mü?
lsmod | grep nvidia

nvidia-smi çıktısında şunu görmelisiniz:

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.105.17   Driver Version: 525.105.17   CUDA Version: 12.0    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  NVIDIA A10          Off  | 00000000:00:1E.0 Off |                  Off |
|  0%   35C    P0    56W / 150W |      0MiB / 23028MiB |      0%      Default |
+-----------------------------------------------------------------------------+

Eğer nvidia-smi komutu çalışmıyorsa, önce driver kurulumunu tamamlamanız gerekiyor:

# Ubuntu 22.04 için driver kurulumu
sudo apt update
sudo apt install -y nvidia-driver-525 nvidia-cuda-toolkit

# Sistem yeniden başlatması gerekebilir
sudo reboot

# Reboot sonrası kontrol
nvidia-smi

CUDA Toolkit sürümü ile driver sürümünün uyumlu olması kritik. NVIDIA’nın resmi uyumluluk tablosuna göre CUDA 12.0 için minimum driver 525.xx gerekiyor.

LocalAI’ı CUDA Desteğiyle Derleme

LocalAI’ı CUDA destekli çalıştırmanın iki yolu var: Docker imajı kullanmak veya kaynak koddan derlemek. Production ortamı için Docker şiddetle tavsiye edilir, ama bazen kaynak derleme daha fazla kontrol sağlıyor.

Docker ile CUDA Destekli Kurulum

Önce NVIDIA Container Toolkit kurulumu:

# NVIDIA Container Toolkit repository ekleme
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | 
  sudo tee /etc/apt/sources.list.d/nvidia-docker.list

sudo apt update
sudo apt install -y nvidia-container-toolkit

# Docker daemon'ı yeniden başlat
sudo systemctl restart docker

# Test
docker run --rm --gpus all nvidia/cuda:12.0-base-ubuntu22.04 nvidia-smi

Şimdi LocalAI’ı CUDA imajıyla çalıştıralım:

# Model dizini oluştur
mkdir -p /opt/localai/models
mkdir -p /opt/localai/config

# LocalAI CUDA imajını çalıştır
docker run -d 
  --name localai 
  --gpus all 
  -p 8080:8080 
  -v /opt/localai/models:/models 
  -v /opt/localai/config:/config 
  -e THREADS=4 
  -e CONTEXT_SIZE=4096 
  -e GPU_LAYERS=35 
  -e DEBUG=true 
  --restart unless-stopped 
  localai/localai:latest-aio-gpu-nvidia-cuda-12

Buradaki GPU_LAYERS parametresi kritik. Modelin kaç katmanının GPU’ya offload edileceğini belirliyor. 35 değeri Llama-2 7B için iyi bir başlangıç noktası, ama GPU belleğinize göre ayarlamanız gerekecek.

Docker Compose ile Kurulum

Production ortamı için Docker Compose daha yönetilebilir:

version: '3.8'

services:
  localai:
    image: localai/localai:latest-aio-gpu-nvidia-cuda-12
    container_name: localai
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - /opt/localai/models:/models
      - /opt/localai/config:/config
    environment:
      - THREADS=8
      - CONTEXT_SIZE=4096
      - GPU_LAYERS=40
      - NVIDIA_VISIBLE_DEVICES=all
      - NVIDIA_DRIVER_CAPABILITIES=compute,utility
      - DEBUG=false
      - GALLERIES=[{"name":"model-gallery","url":"github:go-skynet/model-gallery/index.yaml"}]
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/readyz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
# Servisi başlat
cd /opt/localai
docker compose up -d

# Log takibi
docker compose logs -f localai

# GPU kullanımını izle
watch -n 1 nvidia-smi

GPU Layers Optimizasyonu

GPU_LAYERS değeri en çok sorgulanan parametre. Yanlış ayarlandığında ya VRAM taşması yaşarsınız ya da GPU’yu verimli kullanamaz, CPU’ya düşersiniz.

Pratik bir formül:

  • GPU VRAM (GB) x 1000 değerini modelin katman başına VRAM tüketimiyle bölün
  • Llama-2 7B Q4 için katman başına yaklaşık 80-100 MB
  • RTX 3090 (24 GB) için maksimum 35 katman güvenli kullanım

Bunu dinamik olarak test etmek için:

# GPU kullanımını monitöre alın
nvidia-smi dmon -s mu -d 1 &

# Test isteği gönderin
curl -s http://localhost:8080/v1/chat/completions 
  -H "Content-Type: application/json" 
  -d '{
    "model": "llama-2-7b-chat",
    "messages": [
      {"role": "user", "content": "Türkiye hakkında 3 paragraf yaz"}
    ],
    "max_tokens": 500
  }' | jq .

# nvidia-smi çıktısında GPU memory kullanımını takip edin

GPU bellek kullanımı VRAM’in %90’ını geçiyorsa GPU_LAYERS değerini azaltın. Eğer GPU kullanımı çok düşükse artırın.

Model Konfigürasyon Dosyaları

LocalAI, model bazında YAML konfigürasyon dosyalarını destekliyor. Bu sayede her model için farklı GPU ayarları yapabilirsiniz:

# /opt/localai/config/llama-2-7b-chat.yaml
name: llama-2-7b-chat
backend: llama
parameters:
  model: llama-2-7b-chat.Q4_K_M.gguf
  context_size: 4096
  threads: 4
  gpu_layers: 35
  f16: true
  mmap: true
  mlock: false

template:
  chat_message: |
    [INST] {{.Input}} [/INST]
  chat: |
    {{.Input}}

stopwords:
  - "[INST]"
  - "[/INST]"
# /opt/localai/config/mistral-7b.yaml
name: mistral-7b
backend: llama
parameters:
  model: mistral-7b-instruct-v0.2.Q5_K_M.gguf
  context_size: 8192
  threads: 6
  gpu_layers: 40
  f16: true
  mmap: true
  numa: false
  
# Mistral için özel template
template:
  chat_message: |
    <s>[INST] {{.Input}} [/INST]
  chat: |
    {{.Input}}

F16 modu, GPU hesaplamalarını 32-bit yerine 16-bit floating point kullanarak yapıyor. Bu hem bellek kullanımını yarıya indiriyor hem de modern GPU’larda tensor core’ları devreye alarak performansı artırıyor.

Çoklu GPU Konfigürasyonu

Birden fazla GPU varsa bunu doğru yönetmek gerekiyor. LocalAI, llama.cpp üzerinden tensor parallelism destekliyor:

# Mevcut GPU'ları listele
nvidia-smi -L

# Output örneği:
# GPU 0: NVIDIA A10 (UUID: GPU-xxxx)
# GPU 1: NVIDIA A10 (UUID: GPU-yyyy)
# /opt/localai/config/llama-2-13b-multigpu.yaml
name: llama-2-13b
backend: llama
parameters:
  model: llama-2-13b-chat.Q4_K_M.gguf
  context_size: 4096
  threads: 8
  gpu_layers: 43
  f16: true
  tensor_split: "0.5,0.5"  # İki GPU'ya eşit dağıtım
  main_gpu: 0

Tensor split değerleri, modelin ağırlıklarının GPU’lar arasında nasıl dağıtılacağını belirliyor. “0.5,0.5” eşit dağılım anlamına geliyor. Eğer bir GPU daha güçlüyse “0.7,0.3” gibi asimetrik dağılım da yapılabilir.

Gerçek Dünya Senaryosu: RAG Pipeline Performansı

Bir müşteri için şirket içi döküman sorgulama sistemi kurduğumuzda yaşananları aktarayım. Başlangıçta CPU üzerinde çalışıyordu, 3000 token context ile bir sorguya 45 saniye bekliyorlardı.

Sunucuda A10 GPU vardı ama LocalAI CPU modunda çalışıyordu. Konfigürasyonu güncelledikten sonra:

# Performans testi scripti
#!/bin/bash

TEST_PROMPT="Şirketimizin 2024 yılı gelir raporu hakkında detaylı bir özet yaz ve önemli KPI'ları listele."

echo "Test başlıyor: $(date)"
START_TIME=$(date +%s%N)

RESPONSE=$(curl -s -X POST http://localhost:8080/v1/chat/completions 
  -H "Content-Type: application/json" 
  -d "{
    "model": "mistral-7b",
    "messages": [{"role": "user", "content": "$TEST_PROMPT"}],
    "max_tokens": 800,
    "temperature": 0.7
  }")

END_TIME=$(date +%s%N)
DURATION=$(( (END_TIME - START_TIME) / 1000000 ))

echo "Süre: ${DURATION}ms"
echo "Token sayısı: $(echo $RESPONSE | jq '.usage.completion_tokens')"
echo "Token/saniye: $(echo "scale=2; $(echo $RESPONSE | jq '.usage.completion_tokens') / ($DURATION / 1000)" | bc)"

CPU modunda ortalama 42 saniye ve saniyede 6 token. GPU modunda (35 layer offload) ortalama 3.8 saniye ve saniyede 67 token. 11x performans artışı.

CUDA Hata Ayıklama

Production’da sıkça karşılaşılan CUDA sorunları ve çözümleri:

# CUDA out of memory hatası loglarını kontrol et
docker logs localai 2>&1 | grep -i "cuda|gpu|memory|error"

# GPU bellek durumu anlık kontrol
nvidia-smi --query-gpu=memory.used,memory.free,memory.total 
  --format=csv --id=0

# CUDA context temizleme (servis restart gerektirmez)
# Önce modeli unload et
curl -X POST http://localhost:8080/v1/models/llama-2-7b-chat/unload

# Yeniden yükle
curl -X POST http://localhost:8080/v1/models/llama-2-7b-chat/load

CUDA_ERROR_OUT_OF_MEMORY: GPU_LAYERS değerini 5’er 5’er azaltın. Hangi değerde kararlı çalıştığını bulun.

CUDA_ERROR_ILLEGAL_ADDRESS: Genellikle uyumsuz CUDA toolkit ve driver versiyonu. nvcc --version ile nvidia-smi çıktısını karşılaştırın.

cublas not found: llama.cpp CUDA desteğiyle derlenmemiş. CUDA destekli Docker imajını kullandığınızdan emin olun.

# Container içinde CUDA kütüphanelerini kontrol et
docker exec localai ldconfig -p | grep cuda

# Çıktıda şunları görmelisiniz:
# libcuda.so.1
# libcublas.so.12
# libcudart.so.12

Monitoring ve Alerting

GPU’yu prod’da çalıştırıyorsanız monitoring şart:

# Prometheus için nvidia-smi exporter kurulumu
docker run -d 
  --name nvidia-smi-exporter 
  --gpus all 
  -p 9835:9835 
  --restart unless-stopped 
  nvcr.io/nvidia/k8s/dcgm-exporter:3.1.7-3.1.4-ubuntu20.04

# Basit monitoring scripti
#!/bin/bash
# /usr/local/bin/gpu-monitor.sh

THRESHOLD=90
GPU_UTIL=$(nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits)
MEM_USED=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits)
MEM_TOTAL=$(nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits)
MEM_PCT=$((MEM_USED * 100 / MEM_TOTAL))

if [ $MEM_PCT -gt $THRESHOLD ]; then
  echo "UYARI: GPU bellek kullanımı %${MEM_PCT} seviyesinde!" | 
    mail -s "GPU Memory Alert" [email protected]
fi

echo "$(date): GPU Util: ${GPU_UTIL}%, Mem: ${MEM_USED}/${MEM_TOTAL}MB (%${MEM_PCT})"
# Crontab'a ekle
echo "*/5 * * * * /usr/local/bin/gpu-monitor.sh >> /var/log/gpu-monitor.log 2>&1" | 
  sudo crontab -

Performans İpuçları ve İnce Ayarlar

Birkaç küçük ama etkili optimizasyon:

NUMA Topology: Çok soketli sunucularda GPU hangi CPU soketine yakınsa, o core’ları kullanın.

# NUMA topology kontrolü
numactl --hardware

# GPU'nun NUMA node'unu bul
cat /sys/bus/pci/devices/$(nvidia-smi --query-gpu=pci.bus_id 
  --format=csv,noheader | head -1 | tr '[:upper:]' '[:lower:]' | 
  sed 's/0000://')/numa_node

Persistence Mode: GPU’nun düşük güç moduna girmesini engeller, ilk istek gecikmesini azaltır.

# Persistence mode aktif et
sudo nvidia-smi -pm 1

# Sistemd service olarak kalıcı hale getir
sudo tee /etc/systemd/system/nvidia-persistence.service << EOF
[Unit]
Description=NVIDIA Persistence Mode
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/bin/nvidia-smi -pm 1
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable nvidia-persistence.service
sudo systemctl start nvidia-persistence.service

Batch Size: Eş zamanlı istek varsa batch inference devreye giriyor. LocalAI konfigürasyonunda:

  • batch: Aynı anda işlenecek maksimum istek sayısı, GPU kullanımını optimize eder
  • f16: FP16 hesaplama, tensor core kullanımını sağlar
  • mmap: Model dosyasını memory-map ile yükler, RAM kullanımını azaltır
  • mlock: Model sayfalarını RAM’de kilitler, swap’e gitmesini engeller

Güvenlik Notları

GPU sunucusu dışarıya açılacaksa birkaç önlem:

# API key authentication için nginx reverse proxy
sudo apt install nginx

sudo tee /etc/nginx/sites-available/localai << 'EOF'
server {
    listen 443 ssl;
    server_name ai.sirket.com;
    
    ssl_certificate /etc/letsencrypt/live/ai.sirket.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ai.sirket.com/privkey.pem;
    
    location / {
        # API key kontrolü
        if ($http_authorization != "Bearer gizli-api-key-buraya") {
            return 401;
        }
        
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }
}
EOF

sudo ln -s /etc/nginx/sites-available/localai /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Sonuç

LocalAI ile GPU hızlandırma kurulumu ilk başta karmaşık görünse de adımları sırayla takip ettiğinizde oldukça sistematik bir süreç. Temel mesaj şu: doğru CUDA sürümü, doğru GPU_LAYERS değeri ve model bazında optimize YAML konfigürasyonları ile CPU’dan 10x’ten fazla performans artışı elde edebilirsiniz.

En çok dikkat edilmesi gereken nokta VRAM yönetimi. GPU_LAYERS’ı aşırı yükseğe ayarlayıp VRAM taşması yaşamak hem performansı mahveder hem de debug’laması zaman alır. Konservativ başlayıp yukarı doğru gitmek, tam tersi yapmaktan çok daha akıllıca.

Production’da mutlaka monitoring kurun, persistence mode aktif edin ve model konfigürasyonlarınızı versiyon kontrolüne alın. Yarın sunucuya bakan başka bir sysadmin ne yaptığınızı anlamalı, YAML dosyaları ve konfigürasyonlar bunu sağlıyor.

Bir sonraki adım olarak quantization seçimi konusuna bakmanızı öneririm. Q4_K_M ile Q8_0 arasındaki fark, hem kalite hem de VRAM kullanımı açısından GPU layer optimizasyonu kadar kritik.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir