सेवा इंजन आंतरिक Paged ध्यान, निरंतर बैचिंग, टुकड़ा पूर्व भरने
code/main.pyजो कार्यक्रमों को prefill और decode vLLM की तरह करता है।Type: Learn
Languages: Python (stdlib, toy continuous batching scheduler)
Prerequisites: Phase 17 · 01 (Model Serving), Phase 11 (LLM Engineering)
Time: ~75 minutes
सीखने के लक्ष्य
- KV कैश आवंटनकर्ता के रूप में PagedAttention को समझाएंः ब्लॉक, ब्लॉक तालिकाएं, और उत्पादन लोड पर टुकड़ाकरण 4% से नीचे क्यों रहता है।
- पुनरावृत्ति स्तर पर निरंतर बैचिंग का आरेखः कैसे तैयार अनुक्रम बैच छोड़ते हैं और नए बिना खारिज किए जुड़ते हैं।
- एक वाक्य में टुकड़े टुकड़े पूर्व-पूर्ति का वर्णन करें और नाम दें कि यह किस लटेंसी मीट्रिक की रक्षा करता है (संकेतः यह TTFT पूंछ है, न कि औसत आउटपुट) ।
- एक बार में प्रत्येक अनुकूलन सक्षम करने से पहले अपने संस्करण के लिए संगतता मैट्रिक्स के साथ vLLM सुविधा संयोजन की जांच करें।
समस्या
एक साफ़ PyTorch सेवा लूप एक समय में एक अनुरोध चलाता हैः टोकन, prefill, decode करने के लिए EOS, लौटें. एक उपयोगकर्ता के लिए यह काम करता है। सौ पर, यह धैर्यवान लोगों की कतार है। स्पष्ट फिक्स स्थैतिक बैचिंग प्रत्येक अनुरोध को विंडो में सबसे लंबे समय तक भेजता है, प्रत्येक डिकोड को सबसे लंबे समय तक अपेक्षित आउटपुट तक पैड करता है, और पूरे बैच को सबसे धीमी अनुक्रम पर रोकता है। आप कभी इस्तेमाल नहीं करने वाले पैडिंग के लिए भुगतान करते हैं, और तेज अनुरोध धीमी मांगों के लिए इंतजार करते हैं।
vLLM एक ही समय में तीन समस्याओं को हल करता है। पेजडएटेंशन केवी कैश टुकड़े टुकड़े को रोकता है जीपीयू मेमोरी का 60-80% खपत करने के लिए क्लासिक आसन्न आवंटन के रूप में करता है। निरंतर बैचिंग अनुरोधों को प्रत्येक डिकोड पुनरावृत्ति के बीच बैच को जोड़ने और छोड़ने की अनुमति देता है, इसलिए बैच हमेशा वास्तविक काम से भरा होता है। टुकड़ा टुकड़ा प्रीफिल 32k टोकन संकेत को ~512 टोकन स्लाइस में तोड़ता है जो डिकोड के साथ हस्तक्षेप करता है, इसलिए एक लंबा संकेत GPU पर हर डिकोड टोकन को फ्रीज नहीं करता है।
2026 उत्पादन डिफ़ॉल्ट सभी तीनों पर है. आप यह समझने की जरूरत है कि प्रत्येक क्या करता है क्योंकि विफलता मोड सभी शेड्यूलर पर हैं, मॉडल नहीं.
अवधारणा
वर्चुअल मेमोरी सिस्टम के रूप में PagedAttention
एक KV कैश है num_layers × 2 × num_heads × head_dim × seq_len × bytes_per_elementLlama 3.3 70B के लिए 8192 टोकन पर, जो BF16 में लगभग 1.25 GB प्रति क्रम है। यदि आप प्रत्येक अनुरोध के लिए 8192 स्लॉट अग्रिम रूप से आरक्षित करते हैं लेकिन औसत अनुरोध केवल 1500 टोकन का उपयोग करता है, तो आप आरक्षित HBM के लगभग 82% बर्बाद करते हैं। क्लासिक बैचिंग इस अपशिष्ट का भुगतान करता है।
पेजडएटेंशन ने ओएस वर्चुअल मेमोरी से विचार उधार लिया है। केवी कैश प्रति अनुक्रम संरेखित नहीं है। यह निश्चित आकार के ब्लॉक (डिफ़ॉल्ट 16 टोकन) में आवंटित किया जाता है। प्रत्येक अनुक्रम में एक ब्लॉक तालिका होती है जो भौतिक ब्लॉक आईडी के लिए अपने तार्किक टोकन स्थानों का नक्शा बनाती है। जब एक अनुक्रम आवंटित ब्लॉक से परे बढ़ता है, तो एक और ब्लॉक जोड़ा जाता है। जब यह समाप्त होता है, तो उसके ब्लॉक पूल में लौटते हैं।
फ्रागमेंटेशन 60-80% (क्लासिक) से 4% से नीचे गिर जाता है (पेजडएटेंशन) आप एक ध्वज के साथ पेजडएटेंशन को सक्षम नहीं करते हैं यह एकमात्र आवंटनकर्ता vLLM जहाज है। बटन है --gpu-memory-utilization(पूर्वनिर्धारित 0.9), जो vLLM को बताता है कि भार भार और सक्रियण के बाद KV ब्लॉक के लिए कितना HBM आरक्षित करना है।
पुनरावृत्ति स्तर पर निरंतर बैचिंग
पुरानी "डायनामिक बैचिंग" ने एक बैच भरने के लिए एक विंडो (कहें 10 एमएस) का इंतजार किया, फिर प्रत्येक अनुक्रम समाप्त होने तक प्रीफिल + डिकोड + डिकोड + डिकोड चलाया। तेजी से अनुक्रम जल्दी छोड़ दिया और निष्क्रिय रहे जबकि GPU धीमी समाप्त हो गई।
प्रत्येक डिकोडिंग चरण के बीच निरंतर बैचिंग संचालित होती है। चल रहे अनुक्रमों के सेट को RUNNINGसूची. प्रत्येक पुनरावृत्ति परः
- किसी भी अनुक्रम में
RUNNINGजो सिर्फ EOS या max_tokens मारा है हटा दिया गया है. - अनुसूचक प्रतीक्षा कतार को देखता है। यदि कोई मुक्त KV ब्लॉक है, तो यह नए अनुक्रमों (पूर्व भरने या फिर से शुरू) को स्वीकार करता है।
- आगे की पास जो भी है पर चलता है अब में
RUNNING, प्रति अनुक्रम एक नया टोकन जारी करते हैं।
बैच आकार कभी भी एक निश्चित संख्या तक पैड नहीं किया जाता है। उनके आउटपुट में विभिन्न स्थानों पर अनुक्रम एक फ्यूज फॉरवर्ड साझा करते हैं। 2026 vLLM में इसे V1 scheduler. कुंजी अपरिवर्तनीयः अनुसूचक प्रति डिकोड पुनरावृत्ति एक बार चलाता है, प्रति अनुरोध नहीं।
टुकड़े टुकड़े प्रीफिल TTFT पूंछ की रक्षा करता है
प्रीफिल कम्प्यूटिंग-बाउंड है। Llama 3.3 70B पर 32k-token प्रॉम्प्ट एक H100 पर ~800 ms शुद्ध प्रीफिल लेता है। प्रीफिल रन होने पर, बैच प्रतीक्षा में प्रत्येक अन्य अनुक्रम के लिए टोकन को डिकोड करें। एक सेवा लूप में, एक लंबे प्रॉम्प्ट की पहली टोकन लटेंसी (TTFT) दर्जनों अन्य उपयोगकर्ताओं के लिए इंटर-टोकन लटेंसी (ITL) ब्लिप बन जाती है।
Chunked prefill फिक्स्ड-साइज के टुकड़ों (डिफ़ॉल्ट 512 टोकन) में प्रीफिल विभाजित करता है और प्रत्येक टुकड़े को इकाई के रूप में शेड्यूल करता है। टुकड़ों के बीच शेड्यूलर एक टोकन द्वारा डिकोड अनुक्रमों को आगे बढ़ा सकता है। आप एक छोटे से पूर्ण प्रीफिल लेटेन्सी हिट (प्रति टुकड़ा कुछ एमएस) को बहुत कम डिकोड-टाइम jitter के लिए आदान-प्रदान करते हैं। मिश्रित लोड के तहत पी 99 आईटीएल ~ 50 एमएस से ~ 15 एमएस तक गिरता है प्रकाशित बेंचमार्क में।
तीन डिफ़ॉल्ट बातचीत
सभी तीनों विशेषताएं एक-दूसरे को मानते हैं। पेजडएटेंशन अनुसूचक को व्यापार करने के लिए एक बारीक-अमल वाला KV संसाधन देता है। निरंतर बैचिंग की जरूरत है कि बारीक-अमल संसाधन इसलिए एक नई अनुक्रम को स्वीकार करने के लिए एक वैश्विक पुनर्व्यवस्थापन को मजबूर नहीं करता है। टुकड़ा पूर्वपूर्ति एक निर्णय है जो अनुसूचक उसी पर लेता है।RUNNINGसूची यह एक और शेड्यूलर नीति है, एक अलग प्रणाली नहीं।
आपको हर झंडे को जानने की जरूरत नहीं है। आपको यह जानने की आवश्यकता है कि शेड्यूलर क्या अनुकूलित करता हैः KV-ब्लॉक बजट के तहत अच्छा उत्पादन, टुकड़े टुकड़े पूर्व भरने के लिए स्लाइसिंग के अधीन।
संगतता मैट्रिक्स की जांच करें
एक ही बार में सभी को सक्षम करने से पहले अपने सटीक vLLM संस्करण के लिए संगतता मैट्रिक्स के साथ प्रत्येक सुविधा संयोजन की जांच करें, क्योंकि रिलीज़ के बीच जो बदलाव होता है वह बदलता है। v0.18.0 में फीचर मैट्रिक्स स्पेक्लूटिव डिकोडिंग को कश्मीरी प्रीफिल और प्रीफिक्स कैशिंग के साथ संगत के रूप में चिह्नित करता है, और स्पेक्लूटिव-डिकोडिंग पृष्ठ में दो ज्ञात असंगतताओं की सूची दी गई हैः v0.15.0 के माध्यम से पाइपलाइन समानांतरता, और v0.10.0 के माध्यम से ड्राफ्ट-मॉडल अटकलें। प्रारूप विधि के लिए, 2026 डिफ़ॉल्ट अक्सर EAGLE-3 ("method": "eagle3"), जो कि 17 · 05 चरण में शामिल है।
संख्याओं को याद रखना चाहिए
- Llama 3.3 70B FP8, H100 SXM5, 128 समवर्ती, सभी तीनों परः 2,200-2,400 tok/s.
- समान मॉडल, डिफ़ॉल्ट vLLM (कोई टुकड़ा पूर्व-पूर्ति नहीं): ~1,800 tok/s।
- एक ही मॉडल, साफ़ PyTorch आगे लूपः ~ 600 tok / s.
- उत्पादन भार पर PagedAttention के अंतर्गत KV विखंडन कचराः < 4%
- मिश्रित भार के तहत P99 ITL: ~15 ms टुकड़े टुकड़े पूर्व भरने के साथ, ~50 ms बिना।
अनुसूचक कैसा दिखता है
while True:
finished = [s for s in RUNNING if s.is_done()]
for s in finished: release_blocks(s); RUNNING.remove(s)
while WAITING and have_free_blocks_for(WAITING[0]):
s = WAITING.pop(0)
allocate_initial_blocks(s)
RUNNING.append(s)
# schedule prefill chunks + decode in one batch
batch = []
for s in RUNNING:
if s.in_prefill:
batch.append(next_prefill_chunk(s)) # e.g. 512 tokens
else:
batch.append(decode_one_token(s)) # 1 token
run_forward(batch) # one fused GPU callcode/main.pyयह सही है कि इस लूप में stdlib पायथन के साथ नकली टोकन गिनती और नकली आगे विलंबता. इसे चलाने से पता चलता है कि कैसे टुकड़ा पूर्व भरने के दौरान जीवित डीकोडिंग अनुक्रमों लंबे पूर्व भरने के दौरान रखता है.
इसका प्रयोग करें
code/main.pyस्विच करने योग्य सुविधाओं के साथ vLLM शैली के शेड्यूलर का अनुकरण करता है। इसे देखने के लिए चलाएंः
NAIVEमोडः एक बार में एक अनुरोध, बैचिंग नहीं।STATICमोडः पैड और प्रतीक्षा, क्लासिक बैचिंग।CONTINUOUSमोडः पुनरावृत्ति स्तर पर प्रवेश और रिलीज़।CONTINUOUS + CHUNKEDमोडः डिकोड के साथ इंटरलेटेड प्रीफिल स्लाइस।
आउटपुट कुल आउटपुट (वर्चुअल सेकंड प्रति टोकन), TTFT औसत और P99 ITL दिखाता है।CONTINUOUS + CHUNKEDमिश्रित यातायात पर पंक्ति का वर्चस्व होना चाहिए।
इसे भेजें
यह सबक हमें फल देता हैoutputs/skill-vllm-scheduler-reader.md. एक सेवा कॉन्फ़िग (बैच आकार, KV मेमोरी उपयोग, टुकड़े टुकड़े प्रीफिल आकार, अटकल कॉन्फ़िग) को देखते हुए, यह एक शेड्यूलर निदान उत्पन्न करता है जो तीन डिफ़ॉल्ट में से कौन सा फ्लैग है और क्या ट्यून करना है।
व्यायाम
- दौड़ें
code/main.py. तुलना करेंSTATICCONTINUOUSप्रीफिल दक्षता, डिकोडिंग दक्षता या टेल लेटेंसी से आउटपुट अंतर कहां से आता है? - जोड़ने के लिए खिलौना अनुसूचक को संशोधित करें
--max-num-batched-tokens. Llama 3.3 70B FP8 चलाने वाले H100 के लिए सही मूल्य क्या है? (संकेतः यह KV ब्लॉक आकार और मुक्त ब्लॉक की संख्या का कार्य है, कच्चे HBM नहीं) । - vLLM v0.18.0 रिलीज नोट्स को फिर से पढ़ें. कौन से ध्वज संयोजन परस्पर बहिष्कृत हैं? उन्हें सूचीबद्ध करें।
- क.वी. कैश खंडन कचरे की गणना 1,000 अनुरोधों के लिए करें, जिनमें औसतन 1,500 आउटपुट टोकन, std 600 टोकन हैं, (क) प्रति अनुरोध आवंटन 8192 पर अधिकतम, (ख) 16 टोकन ब्लॉकों के साथ पेजडएटेंशन के तहत।
- एक पैराग्राफ में समझाएं कि क्यों टुकड़े टुकड़े प्रीफिल पी 99 आईटीएल को मदद करता है लेकिन अलग से आउटपुट नहीं।
प्रमुख शर्तें
| Term | What people say | What it actually means |
|---|---|---|
| PagedAttention | "the KV trick" | Fixed-size block allocator for KV cache; fragmentation <4% |
| Block table | "the page table" | Per-sequence map from logical token position to physical KV block |
| Continuous batching | "dynamic batching, but right" | Admit/release decisions made every decode iteration |
| Chunked prefill | "prefill splitting" | Break long prefill into 512-token slices interleaved with decode |
| TTFT | "first token time" | Prefill + queue + network; dominated by prefill at long prompts |
| ITL | "inter-token latency" | Time between consecutive decode tokens; dominated by batch size |
| Goodput | "throughput that meets SLO" | Tokens/sec where every request still hit TTFT and ITL targets |
| V1 scheduler | "the new scheduler" | vLLM's 2026 scheduler; runs continuous batching with chunked prefill |
--gpu-memory-utilization | "the memory knob" | Fraction of HBM reserved for KV blocks after weights and activations |
आगे पढ़ना
- vLLM documentation — Speculative Decoding टुकड़े-टुकड़े पूर्व-पूर्ति और अनुमानित-डिकोडिंग संगतता पर आधिकारिक स्रोत।
- vLLM Release Notes (NVIDIA) 2026 रिलीज कैडेन्स और संस्करण-विशिष्ट व्यवहार।
- vLLM Blog — PagedAttention मूल लेखन जो अभी भी परिभाषित करता है कि कैसे आवंटन के बारे में सोचने के लिए।
- PagedAttention paper (arXiv:2309.06180) विखंडन विश्लेषण और अनुसूचक डिजाइन।
- Aleksa Gordic — Inside vLLM फ्लेम ग्राफ के साथ विस्तृत V1 शेड्यूलर चलना।
This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.
Browse the complete course catalog or open this lesson on GitHub.