Fəsil 07 · 8 dəq oxu

Inference: generasiyadan serving-ə

Inference: generasiyadan serving-ə

Training model-in bir dəfə ödənilən qiymətidir. isə hər gün, hər istifadəçi sorğusunda ödənilir. etdiyiniz model nə qədər yaxşı olsa da, onu lazımi və qiymətlə serve edə bilmirsinizsə, o model production-da yoxdur. Bu fəsil generasiyanın hardware səviyyəsində necə işlədiyini, darboğazların harada olduğunu və onları aradan qaldıran texnikaları izah edir. Məqsəd hər hansı serving engine-in arxasında baş verənləri oxuya bilməkdir.

İki mərhələ: prefill və decode

Fəsil 3-də gördük ki, autoregressive model hər addımda bir yaradır və əvvəlki key və value vektorlarını KV saxlayır. Bir sorğunun icrası iki fərqli mərhələdən keçir.

Prefill. bütün paralel emal olunur. Model hər layer üçün onların K və V vektorlarını hesablayıb yazır və ilk çıxış verir. Bu mərhələ böyük matrix multiplication-lardan ibarətdir, GPU-nun hesablama gücündən tam istifadə edir və compute-bound-dur.

Decode. Bundan sonra hər addımda yalnız bir yeni emal olunur. Amma bu bir üçün model-in bütün yaddaşdan oxumaq və bütün KV etmək lazımdır. Hesablama azdır, oxunan data isə çoxdur. Decode memory-bandwidth-bound-dur.

Bu fərq mühəndisliyinin ən vacib faktıdır. Kobud hesab belədir:

decode sürətinin yuxarı həddi (batch=1) ≈ memory bandwidth / weight-lərin ölçüsü

H100: ~3.35 TB/s,  8B model bf16-da: ~16 GB
3350 / 16 ≈ 200 token/s  (praktikada daha az)

Yəni tək istifadəçi üçün GPU-nun hesablama gücünün böyük hissəsi boş qalır. Aşağıdakı optimizasiyaların demək olar hamısı bu boşluğu doldurmağa xidmət edir: ya oxunan baytları azaltmaq (quantization), ya da bir oxunuşla daha çox iş görmək (batching, speculative decoding).

Sampling: paylanmadan token seçmək

Model hər addımda vocabulary üzərində logit-lər qaytarır. Növbəti necə seçiləcəyini strategiyası müəyyən edir.

  • . Həmişə ən yüksək ehtimallı seçilir. Deterministikdir, amma uzun mətnlərdə təkrarlara və darıxdırıcı nəticələrə meyllidir.
  • . Logit-lər softmax-dan əvvəl T-yə bölünür. T < 1 paylanmanı kəskinləşdirir, T > 1 düzləşdirir. T → 0 yaxınlaşır.
  • Top-k. Yalnız ən yüksək k saxlanılır, qalanları atılır. Sabit k bəzən çox dar, bəzən çox geniş olur.
  • Top-p (nucleus). Ehtimalların cəmi p-yə çatana qədər ən yüksək saxlanılır. Paylanma kəskin olanda az, düz olanda çox namizəd qalır.
  • Min-p. Ən yüksək ehtimalın müəyyən faizindən (məsələn 0.05 × p_max) aşağı olan atılır. Yüksək top-p-dən daha sabit davranır və son illərdə open-source alətlərdə geniş yayılıb.
def sample(logits, temperature=0.7, min_p=0.05):
    probs = softmax(logits / temperature)
    probs[probs < min_p * probs.max()] = 0
    return random_choice(probs / probs.sum())

Praktik qayda: extraction, və kod üçün aşağı , yaradıcı mətn üçün daha yüksək . Reasoning model-lərin çoxu isə provider-in tövsiyə etdiyi parametrlərlə train edilir və onlardan uzaqlaşmaq keyfiyyəti aşağı salır.

Structured və constrained decoding

Model-in çıxışı başqa proqram tərəfindən oxunacaqsa, "zəhmət olmasa JSON qaytar" demək kifayət deyil. Constrained decoding hər addımda qrammatikaya uyğun gəlməyən logit-lərini mənfi sonsuzluğa endirir. JSON schema, regex və ya context-free grammar sonlu avtomata çevrilir və decoder yalnız icazə verilən keçidləri seçə bilir. Nəticə sintaktik baxımdan həmişə etibarlıdır.

Bunun iki incəliyi var. Birincisi, sərhədləri qrammatika sərhədləri ilə üst-üstə düşmür, ona görə yaxşı implementasiyalar mask-ları vocabulary üzərində əvvəlcədən hesablayır ki, overhead az olsun. İkincisi, sintaktik düzgünlük semantik düzgünlük demək deyil. Model-i çox dar formata məcbur etmək, xüsusilə reasoning-dən əvvəl, keyfiyyəti aşağı sala bilər. Ona görə tez-tez əvvəl sərbəst düşünmə, sonra strukturlaşdırılmış cavab sxemi istifadə olunur.

VRAM hesabı: model GPU-ya sığırmı?

Serving üçün yaddaş iki əsas hissədən ibarətdir: və KV . Llama 3 8B tipli bir model götürək: 32 layer, GQA ilə 8 KV head, head_dim = 128.

Weight-lər (bf16): 8e9 parametr × 2 bayt ≈ 16 GB

KV cache bir token üçün:
  2 (K və V) × 32 layer × 8 KV head × 128 head_dim × 2 bayt
  = 131 072 bayt ≈ 128 KiB

8 192 token-lik bir sequence: 8192 × 128 KiB = 1 GiB
32 paralel sequence × 8K:      ≈ 32 GiB

Deməli, 80 GB-lıq GPU-da 16 GB sonra qalan yaddaş eyni anda neçə istifadəçiyə xidmət edə biləcəyinizi müəyyən edir. Buraya activation-lar və framework overhead-i üçün ehtiyat da əlavə olunmalıdır. GQA olmasaydı (32 KV head), KV dörd dəfə böyük olardı. Fəsil 3-dəki arxitektura qərarlarının serving qiymətinə birbaşa təsiri belədir. Uzun context-li tətbiqlərdə KV tez-tez də böyük olur.

Quantization

Quantization (bəzən activation-ları və KV də) daha az bitlə saxlamaqdır. Decode bandwidth-bound olduğu üçün baytları azaltmaq birbaşa sürət qazancıdır: int4 bf16-ya nisbətən təxminən dörd dəfə az oxunur.

  • int8 / fp8. Keyfiyyət itkisi adətən praktik olaraq hiss olunmur. Fəsil 5-də gördüyümüz fp8 müasir GPU-larda həm , həm activation üçün native dəstəklənir.
  • int4. 8B model ~4.5–5 GB-a enir və istehlakçı GPU-suna, hətta laptop-a sığır. İtki kiçik model-lərdə və riyaziyyat, kod kimi dəqiqlik tələb edən tapşırıqlarda daha çox hiss olunur.

Sadə rounding aşağı bitlərdə pis işləyir, çünki bəzi və activation kanalları outlier-dir. Əsas yanaşmaların intuisiyası belədir:

  • GPTQ layer-ləri bir-bir quantize edir və hər addımda yaranan xətanı hələ quantize olunmamış düzəltməklə kompensasiya edir. Bunun üçün kiçik dataset lazımdır.
  • AWQ activation-lara baxaraq hansı kanallarının vacib olduğunu tapır və onları quantization-dan əvvəl scale edərək qoruyur.
  • GGUF konkret alqoritm deyil, əsasən CPU və Apple Silicon üzərində lokal üçün geniş yayılmış fayl formatıdır. İçində müxtəlif block-wise quantization tipləri var (məsələn Q4_K_M, Q8_0) və hər block-un öz scale-i olur.

Qayda: quantize edilmiş model-i həmişə öz eval set-inizdə yoxlayın (Fəsil 8). Ümumi benchmark-da 1 bal itki sizin domain-də 10 bal ola bilər.

Batching: GPU-nu doldurmaq

Decode zamanı bir dəfə oxuyub bir neçə sorğu üçün istifadə etmək olar. Batch-dəki hər əlavə sequence demək olar pulsuz gəlir, ta ki iş compute-bound olana qədər. əsas mənbəyi budur.

Static batching batch-dəki ən uzun sorğunun bitməsini gözləyir. Qısa cavablar bitəndən sonra onların yeri boş qalır. Continuous batching isə qərarı hər decode addımında verir: bitmiş sequence çıxır, növbədəki yeni sorğu dərhal onun yerini tutur. Real trafikdə bu, bir neçə dəfə artırır.

Continuous batching-in qarşısındakı maneə KV yaddaşının fraqmentasiyasıdır. Hər sorğu üçün maksimal uzunluqda bitişik yaddaş ayırmaq israfdır. PagedAttention əməliyyat sistemindəki virtual yaddaş ideyasını tətbiq edir: KV sabit ölçülü block-lara bölünür və hər sequence-in block table-i olur. Yaddaş lazım olduqca ayrılır, israf demək olar sıfıra enir. Eyni paylaşan sorğular isə eyni block-ları paylaşa bilir (prefix ). və uzun tətbiqlərdə bu, prefill xərcini kəskin azaldır.

Böyük sistemlərdə növbəti addım prefill və decode-u ayrı GPU qruplarına bölməkdir (disaggregated serving), çünki onların hardware ehtiyacları fərqlidir.

Speculative decoding

Batch=1 halında da boş qalan compute-dan istifadə etmək olar. Kiçik və sürətli draft model növbəti k təxmin edir. Böyük model bu k bir forward pass-da, prefill kimi paralel yoxlayır. Qəbul edilən prefix saxlanılır, ilk rədd edilən sonra böyük model-in öz seçimi götürülür. Düzgün qurulmuş qəbul qaydası ilə çıxış paylanması böyük model-in paylanması ilə eyni qalır, yəni keyfiyyət itkisi yoxdur.

Qazanc draft-ın nə qədər tez-tez düz tapmasından asılıdır. Kod və strukturlaşdırılmış mətndə 2–3 dəfə sürətlənmə adi haldır. Ayrıca draft model əvəzinə əsas model-ə əlavə prediction head-lər qoşan variantlar da var (Medusa, EAGLE ailəsi).

Latency metrikləri

İstifadəçi təcrübəsi bir rəqəmlə ölçülmür.

  • TTFT (time to first ): sorğudan ilk qədər keçən vaxt. Növbədə gözləmə və prefill tərəfindən müəyyən olunur. Chat-də "cavab gəlir" hissi budur.
  • TPOT (time per output ) və ya inter-token : ilk sonra hər düşən vaxt. Decode sürətidir.
  • End-to-end ≈ TTFT + TPOT × çıxış sayı.
  • : sistemin saniyədə bütün istifadəçilər üçün yaratdığı sayı.

və bir-biri ilə ziddiyyət təşkil edir. Batch böyüdükcə artır, amma hər istifadəçi üçün TPOT pisləşir. Ölçərkən ortalamaya yox, p50 və baxın. da konkret yazın, məsələn " TTFT < 1 s, TPOT < 50 ms".

Serving engine seçimi

Bu texnikaları sıfırdan yazmağa ehtiyac yoxdur. Serving engine-lər bir neçə kateqoriyaya bölünür:

  • Yüksək GPU server-ləri. Continuous batching, PagedAttention, prefix , speculative decoding və tensor parallelism-i hazır verir. Production API-ləri üçün əsas seçimdir.
  • Vendor-optimallaşdırılmış runtime-lar. Konkret hardware üçün xüsusi kernel-lər yazılır. Maksimal performans verir, qarşılığında daha mürəkkəb build və daha az çeviklik gəlir.
  • Lokal/edge runtime-lar. CPU, Apple Silicon və istehlakçı GPU-ları üçündür, adətən GGUF kimi quantize edilmiş formatlarla işləyir. Prototip, offline və məxfi istifadə üçün yaxşıdır.

Seçim meyarları: dəstəklənən model arxitekturaları (yeni open model-lər çıxanda nə qədər tez dəstəklənir), quantization formatları, , LoRA adapter-lərini dinamik yükləmə (Hissə II-də vacib olacaq), metrik ixracı və OpenAI-uyğun API.

Token başına qiymət

Self-hosting-in iqtisadiyyatı sadə bir bölmədir:

GPU qiyməti: $2.5 / saat
Real ölçülmüş aggregate throughput: 2 500 token/s
Saatlıq token: 2500 × 3600 = 9 000 000

1M token-in qiyməti ≈ 2.5 / 9 ≈ $0.28

Tələ "real ölçülmüş" sözlərindədir. Bu rəqəm GPU tam yüklü olanda keçərlidir. Trafik gecə düşürsə və GPU 30% yüklüdürsə, faktiki qiymət üç dəfə artır. Input və output qiyməti də fərqlidir: prefill ucuzdur, decode bahadır. API provider-ləri də buna görə output daha yüksək qiymət qoyur. Self-hosting adətən sabit və yüksək trafikdə, data məxfiliyi tələb olunanda və ya edilmiş xüsusi model lazım olanda özünü doğruldur.

Tapşırıqlar

  1. Seçdiyiniz open model-in config faylından layer sayını, KV head sayını və head_dim-i götürün. bf16 və int4 üçün ölçüsünü, bir KV ölçüsünü hesablayın və 24 GB-lıq GPU-da 4K context ilə eyni anda neçə sequence serve edə biləcəyinizi tapın.
  2. Bir model-i lokal runtime-da bf16 (və ya int8) və int4 variantlarında işə salın. Eyni 50 sorğu üçün TTFT, TPOT və cavab keyfiyyətini müqayisə edin. Quantization keyfiyyəti harada pozdu?
  3. Sadə load test yazın: paralel istifadəçi sayını 1, 4, 16, 64 edin və hər səviyyədə ilə TPOT-u qeyd edin. Qrafikdə SLO-nuzu pozmadan əldə edilən maksimal tapın və ondan 1M qiymətini hesablayın.