Kodnos
AI & Data Science

LLM Inference Optimizasyonu: Üretim Ortamında Modeli Hızlandırma

Üretim ortamında LLM inference'a derinlemesine bakış — KV Cache, PagedAttention, continuous batching, quantization, paralellik stratejileri ve önemli metrikler.

A
admin
3 May 20269 dk okuma19 görüntülenme

Bir yapay zeka uygulaması geliştirmek kolay kısımdır. Onu ölçekte — hızlı, ucuz ve güvenilir şekilde — sunmak, gerçek mühendisliğin başladığı yerdir. Tek bir GPT-4 çağrısı saniyeler sürer ve kuruşlara mal olur. Bunu milyonlarca kullanıcıyla çarpın ve aynı anda bir gecikme sorununuz, bir maliyet sorununuz ve bir altyapı sorununuz olur.

Bu rehber, üretim ekiplerinin LLM inference'ı optimize etmek için kullandıkları teknikleri kapsar: KV Cache gibi temel kavramlardan prefill-decode ayrıştırma gibi gelişmiş stratejilere.

LLM Inference'ın Anatomisi

LLM inference, temelden farklı hesaplama karakteristiklerine sahip iki ayrı fazda gerçekleşir:

Prefill Fazı (Hesaplama Sınırlı)

Tüm giriş token'ları transformer katmanları boyunca paralel olarak işlenir. Bu faz, başlangıç KV Cache'ini — modelin şu ana kadarki konuşma "hafızasını" — oluşturur. Hesaplama ağırlıklıdır (matris çarpımları) ve GPU paralelliğinden faydalanır.

Decode Fazı (Bellek Sınırlı)

Token'lar birer birer üretilir. Her yeni token, GPU belleğinden tüm KV Cache'in okunmasını gerektirir. Bu faz, hesaplama değil bellek bant genişliği ile darboğazlanır. GPU, zamanının çoğunu HBM'den (Yüksek Bant Genişlikli Bellek) verinin gelmesini bekleyerek geçirir.

Temel içgörü (2025): Üretim inference süresinin büyük çoğunluğu decode fazında, bellek beklenerek geçirilir. Bu nedenle çoğu optimizasyon ham hesaplama değil, bellek yönetimini hedefler.

Temel Optimizasyon Teknikleri

| Teknik | Ne Yapar | Ne Zaman Kullanılır | |---|---|---| | KV Cache | Hesaplanan attention key-value çiftlerini saklar; yeniden hesaplamayı önler | Her zaman — temel çizgidir | | PagedAttention | KV Cache'i işletim sistemi sanal belleği gibi sayfalar halinde yönetir | Büyük batch boyutları | | Continuous Batching | Yeni istekleri çalışan inference'a enjekte eder; GPU asla boşta kalmaz | Yüksek eşzamanlı API'ler | | Speculative Decoding | Küçük taslak model token önerir, büyük model paralel doğrular | Chat / agentic uygulamalar | | Quantization | Hassasiyeti düşürür (FP32 → INT8/INT4); daha küçük model, daha hızlı inference | Maliyet optimizasyonu / edge | | FlashAttention | Attention hesaplamasını GPU SRAM'e sığdırır; bellek I/O'sunu azaltır | Uzun bağlamlı modeller |

Her birini detaylıca inceleyelim.

KV Cache: Temel

Her transformer katmanı, attention sırasında Key ve Value tensörleri hesaplar. Önbellek olmadan, N. token'ı üretmek önceki N-1 token için K ve V'yi yeniden hesaplamayı gerektirir — token başına O(N²) iş.

KV Cache bu tensörleri saklar, böylece her yeni token sadece kendi K/V çiftini hesaplayıp önbelleğe alınmış değerlere attend etmesi yeterlidir. Bu, token başına O(N²)'yi O(N)'ye dönüştürür.

Sorun: KV Cache, dizi uzunluğu ve batch boyutu ile doğrusal olarak büyür. 128K bağlamlı 70B parametreli bir model için KV Cache tek başına 40+ GB GPU belleği tüketebilir. Bu belleği yönetmek, sonraki birkaç optimizasyonun konusudur.

KV Cache Olmadan:  Token 1 → [1] için K,V hesapla
                   Token 2 → [1,2] için K,V hesapla
                   Token 3 → [1,2,3] için K,V hesapla
                   ...
                   Token N → [1..N] için K,V hesapla  ← toplam O(N²)

KV Cache İle: Token 1 → [1] için K,V hesapla, önbelleğe al Token 2 → [2] için K,V hesapla, önbelleğe attend et Token 3 → [3] için K,V hesapla, önbelleğe attend et ... Token N → [N] için K,V hesapla, önbelleğe attend et ← toplam O(N)

PagedAttention

Geleneksel KV Cache, istek başına bitişik bellek blokları ayırır. Bir istek 4K token'lık cache ayırır ama sadece 500 kullanırsa, geri kalanı israf olur. Çok sayıda eşzamanlı istekle bu parçalanma, GPU belleğinin %60-80'ini israf eder.

PagedAttention (vLLM tarafından tanıtıldı) işletim sistemi sanal bellek yönetiminden ödünç alır. KV Cache'i herhangi bir yere yerleştirilebilen sabit boyutlu sayfalara (bloklara) böler:

  • Ön ayırma israfı yok — sayfalar talep üzerine ayrılır
  • Parçalanma yok — sayfalar bellekte herhangi bir yere yerleştirilebilir
  • Bellek paylaşımı — ortak ön ekler (sistem prompt'ları gibi) istekler arasında sayfaları paylaşır
  • Bu tek optimizasyon, orijinal vLLM makalesinde naif uygulamalara kıyasla throughput'u 2-4 kat artırdı.

    Batching Stratejileri

    Batching, GPU kullanımını artırmak için en yüksek etkili ilk adımdır. Onsuz, tek bir istek GPU'nun paralel hesaplama kapasitesinin küçük bir bölümünü kullanır.

    Static Batching

    N istek toplayın, birlikte işleyin, tüm sonuçları bir kerede döndürün. Basit ama israf — tüm istekler en uzun olanın bitmesini beklemelidir.

    En uygun: Offline iş yükleri, embedding üretimi, batch ETL.

    Dynamic Batching

    İstekleri bir zaman penceresi içinde (ör. 50ms) biriktirin, sonra batch'i işleyin. Static'ten daha iyi kullanım, ama yine de padding israfı var.

    En uygun: Orta trafikli yakın gerçek zamanlı API'ler.

    Continuous Batching

    En son teknoloji. Yeni istekler, mevcut istekler tamamlandıkça devam eden bir batch'e enjekte edilir:

    1. A, B, C istekleri birlikte başlar 2. A isteği biter (kısa yanıt) → slot serbest kalır 3. D isteği hemen A'nın slotunu doldurur, B ve C devam eder 4. GPU istekler arasında asla boşta kalmaz

    En uygun: Yüksek eşzamanlı chat API'leri, çok kiracılı sistemler.

    Python
    # vLLM continuous batching'i otomatik olarak yönetir
    from vllm import LLM, SamplingParams

    llm = LLM( model="meta-llama/Llama-3-8B-Instruct", max_num_batched_tokens=8192, max_num_seqs=64 # maks eşzamanlı diziler )

    params = SamplingParams(temperature=0.7, max_tokens=256)

    # Bunlar continuous batching ile otomatik olarak batch'lenir outputs = llm.generate([ "KV Cache'i bir paragrafta açıkla.", "PagedAttention nedir?", "Static ve dynamic batching'i karşılaştır." ], params)

    Speculative Decoding

    Decode fazı yavaştır çünkü token'lar sıralı olarak üretilir. Speculative decoding akıllı bir içgörüden yararlanır: doğrulama, üretmekten daha hızlıdır.

    1. Küçük bir taslak model (ör. 1B parametre) hızla K aday token üretir 2. Büyük hedef model tüm K token'ı tek bir ileri geçişte (paralel) doğrular 3. Kabul edilen token'lar tutulur; reddedilen token'lar hedef model tarafından yeniden üretilir

    Taslak modelin yüksek kabul oranı varsa (%70-90), yaklaşık 1-2 hedef model ileri geçişi maliyetiyle K token alırsınız. Etkili hızlanma: sıfır kalite kaybıyla 2-3 kat gecikme azalması.

    Paralellik Stratejileri

    Bir model tek GPU'ya sığmadığında veya daha fazla throughput'a ihtiyacınız olduğunda, iş yükünü dağıtırsınız:

    Tensor Parallelism (TP)

    Her transformer katmanı GPU'lara bölünür. Her GPU her katmanın bir dilimini tutar ve her işlemden sonra all-reduce ile iletişim kurarlar.

  • Gecikme: Düşük (tüm GPU'lar paralel çalışır)
  • İletişim: Yüksek (katman başına all-reduce)
  • En uygun: Gecikmeye duyarlı, tek düğümlü çok GPU'lu sistemler
  • Pipeline Parallelism (PP)

    Farklı katmanlar farklı GPU'lara gider. GPU 1 katman 1-20'yi, GPU 2 katman 21-40'ı işler vb. Micro-batching tüm aşamaları meşgul tutar.

  • Gecikme: Daha yüksek (sıralı pipeline)
  • İletişim: Düşük (sadece aşamalar arasında)
  • En uygun: Birden fazla düğüme yayılan çok büyük modeller
  • Data Parallelism (DP)

    Aynı model GPU'lara kopyalanır. Her GPU farklı istekleri bağımsız olarak işler.

  • Gecikme: Tek GPU ile aynı
  • İletişim: Inference sırasında yok
  • En uygun: Küçük modellerle throughput ölçeklendirme
  • Expert Parallelism (MoE)

    Mixture-of-Experts mimarileri için: farklı uzman alt ağları farklı GPU'larda çalışır. Her token, potansiyel olarak yüzlercesinden yalnızca 2-4 uzmana yönlendirilir, toplam model kapasitesini ölçeklendirirken token başına hesaplamayı sabit tutar.

    Prefill-Decode Ayrıştırma

    Önemli bir 2025 tekniği: prefill ve decode'u ayrı GPU havuzlarında çalıştırın.

    İçgörü, prefill ve decode'un zıt kaynak profillerine sahip olmasıdır:

    | Faz | Darboğaz | GPU Kullanımı | İdeal Donanım | |---|---|---|---| | Prefill | Hesaplama (FLOPs) | Yüksek | Yüksek hesaplamalı GPU'lar | | Decode | Bellek bant genişliği | Düşük | Yüksek bant genişlikli, bellek yoğun GPU'lar |

    Aynı GPU'da karıştırıldığında birbirlerini etkilerler: prefill patlamaları decode'un gecikmeye duyarlı token üretiminden hesaplama çalar. Ayrıştırma, her fazın kendi darboğazı için optimize edilmiş donanımda çalışmasını sağlar.

    Sonuçlar: Daha düşük P99 gecikme, daha iyi maliyet verimliliği ve her fazın daha kolay bağımsız ölçeklendirilmesi.

    Gerçek Zamanlı Sistemlerde Önbellek Yönetimi

    Prefix Caching

    Her istek aynı sistem prompt'uyla başlıyorsa (çok kiracılı API'lerde yaygın), aynı KV Cache ön ekini milyonlarca kez yeniden hesaplıyorsunuz. Prefix caching bunu bir kez hesaplar ve tüm istekler arasında paylaşır.

    Etkisi: Tekrarlanan sistem prompt'larında prefill fazında %30-50 gecikme azalması.

    KV Cache Offloading

    Uzun bağlamlı uygulamalar için (100K+ token), KV Cache GPU belleğine sığmayabilir. Offloading, eski cache segmentlerini CPU belleğine veya hatta SSD'ye taşır ve gerektiğinde geri getirir.

    Denge: Offload edilen segmentlere erişirken gecikme ekler, ama aksi hâlde imkansız olacak bağlam uzunluklarını mümkün kılar.

    Quantization: Hız/Kalite Dengesi

    Quantization, model ağırlıklarının sayısal hassasiyetini düşürerek model boyutunu küçültür ve inference'ı hızlandırır.

    INT8 Quantization

  • Bellek tasarrufu: ~%50 (FP16'ya kıyasla)
  • Kalite kaybı: Çoğu model için ihmal edilebilir
  • Hız artışı: 1.5-2 kat
  • En uygun: Kalitenin pazarlık konusu olmadığı üretim dağıtımları
  • INT4 Quantization (GPTQ, AWQ)

  • Bellek tasarrufu: ~%75
  • Kalite kaybı: Küçük ama ölçülebilir; modele göre değişir
  • Hız artışı: 2-3 kat
  • En uygun: Maliyetle sınırlı dağıtımlar, edge inference
  • Python
    # vLLM ile AWQ quantization
    from vllm import LLM, SamplingParams

    # Önceden quantize edilmiş modeli yükle llm = LLM( model="TheBloke/Llama-3-8B-Instruct-AWQ", quantization="awq", dtype="half" )

    params = SamplingParams(temperature=0.7, max_tokens=256) output = llm.generate("ML'de quantization'ı açıkla.", params)

    Kritik: Dağıtmadan önce, quantization etkisini temsili bir test setiyle kendi özel kullanım durumunuzda mutlaka ölçün. Bazı görevler (matematik, kod üretimi) hassasiyet kaybına diğerlerinden daha duyarlıdır.

    Inference Sunucuları

    | Sunucu | Temel Güçlü Yön | En Uygun | |---|---|---| | vLLM | PagedAttention + continuous batching; açık kaynak standardı | Genel üretim sunumu | | TGI (HuggingFace) | Kolay dağıtım, Flash Attention | Hızlı prototipten üretime | | TensorRT-LLM | Maksimum NVIDIA GPU optimizasyonu | Her milisaniyenin önemli olduğu durumlar | | Ollama | Basit yerel kurulum, tek komutla kurulum | Yerel geliştirme, edge |

    Sunucunuzu Seçmek

  • Yeni mi başlıyorsunuz? vLLM kullanın — performans ve kullanım kolaylığı arasında en iyi dengeye sahiptir.
  • Yalnızca NVIDIA altyapınız mı var? TensorRT-LLM her damla performansı sıkıştırır.
  • Hızlı göndermek mi lazım? HuggingFace modelleriyle TGI, üretime en hızlı yoldur.
  • Yerel geliştirme/test? Ollama sizi saniyeler içinde çalışır hale getirir.

Üretim Metrikleri

Ölçmediğiniz şeyi optimize edemezsiniz. Her LLM sunum sisteminin izlemesi gereken dört metrik:

| Metrik | Ne Ölçer | Alarm Eşiği | |---|---|---| | TTFT (İlk Token'a Kadar Süre) | Kullanıcının algıladığı gecikme | Chat için > 500ms | | TPS (Saniyede Token) | Sistem throughput'u | Yük altında düşüş | | Batch Kullanımı | GPU aktif süre yüzdesi | Sürekli < %60 | | Bellek Baskısı | KV Cache doluluk oranı | > %90 |

Performans Hata Ayıklama

TTFT yükseldiğinde veya sabit yük altında TPS düştüğünde, şu sırayla kontrol edin:

1. Bellek baskısı — KV Cache dolu mu? İstekler kuyrukta mı bekliyor? 2. Batch yapılandırması — Batch boyutu çok mu küçük (GPU az kullanılıyor) yoksa çok mu büyük (bellek çekişmesi)? 3. Cache kayıpları — Prefix caching çalışıyor mu? Sistem prompt'ları yeniden mi hesaplanıyor? 4. — Dağıtık kurulumlar için GPU'lar arası iletişim darboğaz mı?

Hepsini Bir Araya Koymak

2025'te üretim için optimize edilmiş bir LLM sunum yığını genellikle şöyle görünür:

İstek → Yük Dengeleyici
       → Prefix Cache Kontrolü
       → Prefill Havuzu (yüksek hesaplamalı GPU'lar)
       → KV Cache Transferi
       → Decode Havuzu (yüksek bant genişlikli GPU'lar)
       → Continuous Batching
       → Streaming Yanıt

Etki sırasına göre temel kararlar:

1. KV Cache'i etkinleştirin (her zaman) 2. Continuous batching kullanın (vLLM veya TGI) 3. INT8'e quantize edin (güvenli, büyük hızlanma) 4. Prefix caching ekleyin (sistem prompt'ları kullanıyorsanız) 5. Speculative decoding düşünün (gecikme kritik chat için) 6. Prefill/decode ayrıştırın (büyük ölçekli dağıtımlar için)

Sonuç

LLM inference optimizasyonu tek bir sihirli değnek değildir — birbirini tamamlayan teknikleri katmanlamaktır. Temellerle başlayın (KV Cache, batching, quantization), her şeyi ölçün ve karmaşıklığı yalnızca metrikler haklı çıkardığında ekleyin. Amaç mümkün olan en hızlı inference değildir; kendi özel kullanım durumunuz için gecikme, throughput, maliyet ve kalitenin doğru dengesidir.

Kaynaklar

1. Hivenet — Practical Guide to LLM Inference in Production (2025) 2. Daily Dose of DS — A Practical Deep Dive on LLM Inference (Mar 2026) 3. Mirantis — LLM Optimization: Techniques and Guide (Feb 2026) 4. BentoML — 6 Production-Tested Optimization Strategies for High-Performance LLM Inference 5. Redwerk — LLM Inference Optimization Techniques 6. mbrenndoerfer.com — Inference Scaling: Optimizing LLMs for Production Deployment (Oct 2025)

9 DkBu makaleyi paylaşın
Oğuzhan Berke Özdil
Yazar

Oğuzhan Berke Özdil

Çocukluğumdan beri bilgisayarlarla iç içeyim. Bu sitede, yazılımı daha sağlam temellerle öğrenme yolculuğumda edindiğim bilgi ve deneyimleri paylaşıyorum. AGH University of Krakow'da Bilgisayar Bilimleri lisansımı tamamladım ve şu anda aynı üniversitede AI & Data Analysis odaklı yüksek lisansıma devam ediyorum.

Yorumlar (