LLM chậm và đắt vì hai thứ: vòng decode tuần tự và bộ nhớ GPU có hạn.LLMs are slow and expensive for two reasons: a sequential decode loop and finite GPU memory.
Mỗi kỹ thuật trong sáu kỹ thuật dưới đây tác động vào một điểm cụ thể trên vòng đời một request. Biết kỹ thuật tác động ở đâu là biết khi nào nên dùng.Each of the six techniques below acts on one specific point in a request’s lifecycle. Know where it acts, and you know when to use it.
Vòng đời một request. Mỗi nhãn màu là nơi một kỹ thuật can thiệp; các token xanh sáng lên theo cụm bốn, như speculative decoding chấp nhận nhiều token trong một lượt.A request’s lifecycle. Each colored label marks where a technique steps in; the teal tokens light up in groups of four, the way speculative decoding accepts several tokens per pass.
Câu hỏi đầu tiên không phải “kỹ thuật nào”, mà là “có cần kỹ thuật nào không”.The first question isn’t “which technique” but “do I need any at all”.
Thường là không. Gọi API thì bốn trong sáu kỹ thuật là việc của nhà cung cấp. Tự host bằng vLLM hay SGLang thì batching và paged KV đã bật sẵn. Trước khi tối ưu gì, hãy thử những cách rẻ nhất:
Usually not. If you call an API, four of the six are the provider’s job. If you self-host with vLLM or SGLang, batching and paged KV are already on. Before optimizing anything, try the cheapest moves:
Dùng model nhỏ hơn, nếu chất lượng vẫn đạt.
Giới hạn độ dài đầu ra: decode chiếm phần lớn thời gian.
Cắt prompt, bỏ few-shot và chunk RAG thừa.
Cache kết quả ở tầng ứng dụng; dùng batch API cho việc không gấp.
Use a smaller model, if quality still holds.
Cap output length: decode dominates wall time.
Trim the prompt; drop extra few-shot examples and RAG chunks.
Cache results at the app layer; use batch APIs for non-urgent work.
Bạn gọi APIYou call an API
Có người ngồi chờ câu trả lời trên màn hìnhSomeone is watching the screen for the answerStreaming
Các request lặp lại phần đầu promptRequests repeat the start of the promptPrompt caching
Ngoài hai việc này, phần còn lại không thuộc quyền bạn.Beyond these two, the rest isn’t yours to control.
Bạn tự host modelYou self-host the model
Mọi trường hợp: dùng vLLM, SGLang hoặc TensorRT-LLM thay vì tự viết serverAlways: use vLLM, SGLang or TensorRT-LLM instead of writing your own serverBatching + Paged KV
Model không vừa VRAM, hoặc muốn bớt GPUModel doesn’t fit in VRAM, or you want fewer GPUsQuantization
TTFT cao vì prompt dài lặp lạiHigh TTFT from long, repeated promptsPrefix caching
Chữ ra chậm, batch nhỏ, GPU còn dư sức tínhSlow tokens, small batches, spare GPU computeSpeculative
Có người ngồi chờ trước màn hìnhSomeone is waiting at the screenStreaming
Sáu kỹ thuật, theo thứ tự trên vòng đời requestSix techniques, in request-lifecycle order
Số thứ tự là vị trí trên timeline phía trên, không phải mức độ quan trọng.Numbers follow position on the timeline above, not importance.
01
Continuous batching
Tận dụng GPUGPU utilization
Tác động: hàng đợiActs on: the queue
Lập lịch ở từng bước decode: request nào xong thì rời batch ngay, request đang chờ vào thế chỗ ở bước kế tiếp.Schedules at every decode step: a finished request leaves at once and a waiting one takes its slot on the next step.
Dùng choUse for
API nhiều người dùng, độ dài câu trả lời chênh lệch lớn, offline batchMulti-user APIs, widely varying answer lengths, offline batch jobs
ĐượcGain
Thông lượng (throughput) tăng 2–4× hoặc hơn so với static batching; request ngắn không kẹt sau request dài2–4× or more throughput vs static batching; short requests stop waiting on long ones
MấtLose
TPOT hơi tăng; prompt dài chen vào gây khựng nếu thiếu chunked prefillTPOT rises slightly; long prompts stall others without chunked prefill
Chọn continuous batching là đổi độ trễ ổn định của từng request lấy tổng thông lượng của cả hệ thống.Choosing continuous batching trades stable per-request latency for total system throughput.
Dấu hiệu:Sign:hàng đợi dài nhưng GPU utilization vẫn thấp.a long queue while GPU utilization stays low.
02
Prefix caching
Tận dụng GPUGPU utilization
Tác động: prefill, kéo theo TTFTActs on: prefill, and therefore TTFT
Giữ KV cache của phần đầu prompt đã tính; request sau có cùng phần đầu thì bỏ qua prefill cho phần đó. Phần mới và giai đoạn decode vẫn chạy như thường.Keeps the KV cache for a prompt’s computed beginning; a later request with the same beginning skips prefill for it. The new part and decode still run as usual.
Dùng choUse for
Chat nhiều lượt, system prompt dài, hỏi đáp trên cùng tài liệu, agent có tool cố địnhMulti-turn chat, long system prompts, repeated Q&A over one document, agents with fixed tools
ĐượcGain
TTFT giảm vài giây với prompt dài; trên API, token đọc từ cache rẻ hơn nhiềuSeconds off TTFT for long prompts; on APIs, cached tokens cost far less
MấtLose
Chỉ khớp chính xác từng token từ đầu; chiếm bộ nhớ KV; nhiều replica cần routing riêngExact token match from the start only; uses KV memory; multiple replicas need routing
Chọn prefix caching là đổi sự tự do sắp xếp prompt lấy prefill gần như miễn phí cho phần lặp lại.Choosing prefix caching trades freedom in prompt ordering for nearly free prefill on the repeated part.
Dấu hiệu:Sign:hơn một nửa token đầu vào giống hệt nhau giữa các request.over half of input tokens are identical across requests.
03
Streaming
Độ trễLatency
Tác động: token đầu tiênActs on: the first token
Đẩy từng token về client ngay khi sinh ra. Thời gian chờ cảm nhận chuyển từ tổng thời gian sang TTFT; tổng thời gian và chi phí không đổi.Pushes each token to the client as it’s generated. Perceived wait shifts from total time to TTFT; total time and cost stay the same.
Dùng choUse for
Giao diện chat, trợ lý code trong IDE, trợ lý giọng nói, agent hiển thị tiến trìnhChat UIs, IDE coding assistants, voice assistants, agents showing progress
ĐượcGain
Chờ cảm nhận từ vài giây xuống vài trăm ms; không tốn thêm GPU; người dùng dừng sớm đượcPerceived wait from seconds to a few hundred ms; zero extra GPU; users can stop early
MấtLose
JSON dở dang khó parse; kiểm duyệt phải chạy trên luồng streaming; lỗi giữa chừng sau HTTP 200Partial JSON won’t parse; moderation on the stream; errors after HTTP 200
Chọn streaming là đổi sự đơn giản của request–response lấy cảm giác phản hồi tức thì.Choosing streaming trades request–response simplicity for the feel of an instant reply.
Dấu hiệu:Sign:có người chờ một câu trả lời dài hơn khoảng hai giây.someone waits on an answer longer than about two seconds.
04
Speculative decoding
Độ trễLatency
Tác động: decodeActs on: decode
Model nhỏ đoán trước vài token, model lớn kiểm tất cả trong một lượt forward, giữ phần đúng và tự sửa token sai đầu tiên. Đầu ra giống hệt model lớn chạy một mình.A small model guesses a few tokens ahead; the large model checks them all in one forward pass, keeps the right ones and fixes the first wrong one. Output matches the large model exactly.
Dùng choUse for
Chat độ trễ thấp ở tải vừa, sửa code và viết lại văn bản, trích xuất có cấu trúcLow-latency chat at moderate load, code edits and rewrites, structured extraction
ĐượcGain
Sinh token nhanh 2–3× khi điều kiện thuận lợi; không ảnh hưởng chất lượng2–3× faster token generation in good conditions; no quality loss
MấtLose
Tốn compute cho token bị loại; có thể giảm thông lượng ở batch lớn; thêm một model để vận hànhCompute spent on rejected tokens; can cut throughput at large batch; one more model to run
Chọn speculative decoding là đổi phần compute đang bỏ không lấy độ trễ mỗi token thấp hơn.Choosing speculative decoding trades idle compute for lower per-token latency.
Dấu hiệu:Sign:batch nhỏ, GPU còn dư sức, người dùng chê chữ ra chậm.small batches, spare GPU, users say text appears slowly.
05
Quantization
Bộ nhớMemory
Tác động: trọng số, có thể cả KV cacheActs on: weights, optionally the KV cache
Lưu trọng số bằng ít bit hơn: BF16 (2 byte) xuống FP8 (1 byte) hoặc INT4 (0,5 byte). Decode bị chặn bởi băng thông, nên đọc ít byte hơn là nhanh hơn ở batch nhỏ.Stores weights in fewer bits: BF16 (2 bytes) down to FP8 (1 byte) or INT4 (0.5 bytes). Decode is bandwidth-bound, so fewer bytes means faster at small batch.
Dùng choUse for
Model không vừa GPU, bớt GPU mỗi replica, chạy local, nhường VRAM cho KV cacheModels that don’t fit, fewer GPUs per replica, local use, more VRAM for KV cache
ĐượcGain
FP8 giảm nửa bộ nhớ trọng số, INT4 giảm khoảng 4×; FP8 trên H100 gấp đôi sức tính BF16FP8 halves weight memory, INT4 cuts ~4×; FP8 on H100 doubles BF16 compute
MấtLose
Chất lượng sụt không đều, rõ nhất ở model nhỏ, toán, code, tiếng Việt; phụ thuộc phần cứngUneven quality loss, worst for small models, math, code, Vietnamese; hardware-dependent
Chọn quantization là đổi một phần độ chính xác, thứ khó đo cho hết, lấy bộ nhớ và chi phí phần cứng.Choosing quantization trades some hard-to-measure accuracy for memory and hardware cost.
Dấu hiệu:Sign:bạn trả tiền GPU thứ hai chỉ để chứa trọng số.you pay for a second GPU just to hold the weights.
06
Paged KV cache
Bộ nhớMemory
Tác động: KV cache, suốt vòng đời requestActs on: the KV cache, throughout the request
Chia KV cache thành block nhỏ, cấp dần khi cần như bộ nhớ ảo của hệ điều hành. Không còn giữ sẵn vùng liền khối cho độ dài tối đa của mỗi request.Splits the KV cache into small blocks allocated on demand, like OS virtual memory. No more reserving a contiguous region for each request’s maximum length.
Dùng choUse for
Nhiều người dùng đồng thời, context dài, sinh nhiều đáp án, beam searchMany concurrent users, long contexts, multiple samples, beam search
ĐượcGain
Lãng phí KV từ 60–80% xuống dưới 4%; batch lớn hơn, thông lượng tăng 2–4×KV waste from 60–80% down to under 4%; bigger batches, 2–4× throughput
MấtLose
Kernel phức tạp hơn; hết block thì phải preempt request, khiến độ trễ tăng vọtMore complex kernels; running out of blocks forces preemption and latency spikes
Chọn paged KV cache là đổi sự đơn giản của bộ nhớ liền khối lấy khả năng dùng gần hết VRAM cho KV cache.Choosing paged KV cache trades the simplicity of contiguous memory for using nearly all VRAM on KV cache.
Dấu hiệu:Sign:hay OOM hoặc batch nhỏ dù trọng số chỉ chiếm nửa VRAM.frequent OOMs or small batches though weights use half the VRAM.
Bảng đánh đổiTrade-off table
Độ trễ và thông lượng thường kéo ngược nhau. Không kỹ thuật nào thắng ở mọi cột.Latency and throughput usually pull against each other. No technique wins every column.
Kỹ thuậtTechnique
TTFT
Tốc độ sinh tokenToken speed
Thông lượng / chi phíThroughput / cost
Chất lượngQuality
Ai làmWho does it
Độ khóDifficulty
Continuous batching
Giảm khi tải caoLower under load
Hơi chậm điSlightly slower
Tăng mạnhMuch higher
Không đổiUnchanged
Engine
Thấp, mặc địnhLow, default
Prefix caching
Giảm mạnh khi trúngMuch lower on hit
—
TăngHigher
Không đổiUnchanged
Engine/API + bạn sắp promptEngine/API + your prompt order
Thấp–vừaLow–medium
Streaming
Giảm (cảm nhận)Lower (perceived)
—
—
Không đổiUnchanged
Ứng dụng của bạnYour app
ThấpLow
Speculative decoding
—
2–3×
Có thể giảm ở batch lớnCan drop at large batch
Không đổiUnchanged
Engine + bạn chọn draftEngine + your draft
CaoHigh
Quantization
Hơi giảmSlightly lower
Nhanh hơn ở batch nhỏFaster at small batch
Tăng mạnh, ít GPU hơnMuch higher, fewer GPUs
Có thể giảmCan degrade
Bạn chọn checkpointYou pick the checkpoint
VừaMedium
Paged KV cache
—
—
Tăng mạnhMuch higher
Không đổiUnchanged
Engine
Thấp, mặc địnhLow, default
Sai lầm thường gặpCommon mistakes
Sai lầmMistake
Vì sao saiWhy it’s wrong
Sửa thế nàoFix
Tự viết server production quanh model.generate()Building a production server around model.generate()
Không có batching hay paged KV, thông lượng thấp hơn hàng chục lầnNo batching or paged KV; throughput tens of times lower
Dùng vLLM, SGLang, TGI hoặc TensorRT-LLMUse vLLM, SGLang, TGI or TensorRT-LLM
Chèn ngày giờ hoặc user ID ở đầu system promptPutting the date or user ID at the top of the system prompt
Mỗi request một tiền tố khác, cache không bao giờ trúngEvery request gets a new prefix; the cache never hits
Đưa phần động xuống cuối promptMove dynamic content to the end
Quantize INT4 rồi chỉ chạy MMLUQuantizing to INT4 and only running MMLU
Benchmark tiếng Anh tổng quát che giấu sụt giảm ở domain và tiếng ViệtGeneric English benchmarks hide domain and Vietnamese regressions
Đánh giá trên dữ liệu thật, so từng cặp câu trả lờiEvaluate on real data; compare answers pairwise
Bật speculative decoding cho hệ thống batch lớnSpeculative decoding on a large-batch system
GPU đã bão hoà, token bị loại là compute bỏ điThe GPU is saturated; rejected tokens are wasted work
Đo thông lượng trước và sau; chỉ dùng ở batch nhỏMeasure throughput before and after; use at small batch
Bật streaming nhưng proxy vẫn bufferStreaming while the proxy still buffers
Người dùng vẫn đợi trọn câu trả lờiUsers still wait for the full answer
Tắt buffering, đo TTFT ở phía clientDisable buffering; measure TTFT on the client
Client ngắt mà server vẫn sinh tiếpClient disconnects, server keeps generating
Đốt GPU cho câu trả lời không ai đọcBurns GPU on answers nobody reads
Truyền tín hiệu huỷ xuống enginePropagate cancellation to the engine
Chỉ nhìn độ trễ trung bìnhWatching only mean latency
Batching và preemption kéo dài phần đuôi mà trung bình không thấyBatching and preemption stretch the tail without moving the mean
Theo dõi p95/p99 cho TTFT và TPOTTrack p95/p99 for TTFT and TPOT
Chia tải round-robin giữa nhiều replicaRound-robin across replicas
Cùng một tiền tố bị cache rải rác khắp máy, hit rate thấpThe same prefix is cached everywhere; low hit rate
Định tuyến theo prefix hoặc theo sessionRoute by prefix or session
Ba câu cần nhớThree things to remember
Decode là vòng lặp tuần tự bị chặn bởi băng thông bộ nhớ; phần lớn các kỹ thuật này là cách nhồi thêm việc có ích vào mỗi lần đọc trọng số.Decode is a sequential loop bound by memory bandwidth; most of these techniques pack more useful work into each read of the weights.
Nếu bạn gọi API, chỉ có hai việc thuộc về bạn: trả kết quả theo kiểu streaming và sắp xếp prompt để cache trúng.If you call an API, only two things are yours: stream the output and order the prompt so the cache hits.
Mọi tối ưu phải đo trên traffic thật: độ trễ đuôi, cache hit rate, tỷ lệ chấp nhận và chất lượng sau quantize đều không đoán được từ benchmark.Measure every optimization on real traffic: tail latency, cache hit rate, acceptance rate and post-quantization quality can’t be predicted from benchmarks.