TROISINH
BreakthroughsKV Cache & Inference

Continuous Batching — Swap request vào/ra liên tục, GPU không bao giờ rảnh

Iteration-level scheduling giúp tăng 23x throughput bằng cách xóa bỏ khái niệm batch cố định, cho phép GPU xử lý prefill và decode đồng thời.

Tại sao GPU inference luôn kêu "hết VRAM" nhưng utilization lại chỉ 20%? Vì chúng ta ép GPU chờ đợi những request "chậm chân" trong khi có thể tranh thủ xử lý request mới. Continuous Batching là kỹ thuật cốt lõi giúp vLLM đạt throughput cao gấp 23 lần so với cách tiếp cận truyền thống — không phải bằng cách mua thêm GPU, mà bằng cách không để GPU nào ngồi chơi.

Vấn đề

Static Batching — cách phổ biến trong thư viện cũ như HuggingFace Transformers — gom nhiều request vào một "mẻ" cố định. Một request hỏi "Tóm tắt đoạn văn này" (output 20 tokens) và một request viết "Code Python đọc file CSV" (output 200 tokens) bị nhốt chung vào cùng một batch. Kết quả: GPU phải đợi cả hai request hoàn thành mới trả về kết quả, dù request ngắn đã xong từ lâu.

Đây là straggler effect. Với độ dài output biến động lớn (đặc trưng của chatbot), GPU có thể idle đến 80% thời gian chỉ để chờ request dài nhất trong batch hoàn thành. Bạn trả tiền cho 100% compute, nhưng chỉ dùng được 20%.

Ý tưởng cốt lõi

There is no such thing as a "batch" in transformers.

Trong neural network truyền thống, batch là một khối tensor cứng nhắc [batch_size, features]. Nhưng với transformer, attention mask là một ranh giới được định nghĩa bằng software. Nếu bạn đặt mask sao cho token 5 của Sequence A không nhìn thấy Sequence B, thì tính toán vật lý trên GPU giống hệt như xử lý chúng riêng lẻ. "Batch dimension" chỉ là một cách tổ chức dữ liệu tiện lợi, không phải quy luật vật lý.

Continuous Batching (còn gọi là Iteration-level Scheduling) khai thác điểm này. Thay vì chờ cả batch hoàn thành, scheduler swap request vào/ra ở mỗi bước sinh token (iteration). Request mới có thể bắt đầu prefill (xử lý input prompt) trong khi request cũ vẫn đang decode (sinh token output).

Cụ thể:

  • Xóa batch dimension: Thay vì tensor [batch, seq, hidden], flatten thành [total_tokens, hidden]. Mỗi dòng là một token từ bất kỳ sequence nào.
  • Attention masking: Dùng causal mask để ngăn token của sequence này "nhìn trộm" token của sequence khác, dù chúng nằm chung trong một ma trận lớn.
  • Mixing phases: Một request đang ở phase prefill (tính KV cache cho 1000 token prompt) có thể nằm cạnh một request đang decode (sinh token thứ 50), trong cùng một forward pass.

That's it. Bạn không cần đợi cả đoàn tàu dài mới mở cửa. Mỗi toa (request) đến và đi độc lập, GPU liên tục có việc để làm.

Tại sao nó hoạt động

Memory-IO là kẻ thù, không phải FLOPs. LLM inference bị giới hạn bởi băng thông VRAM (memory-bound), không phải sức mạnh tính toán. Mỗi lần sinh token, bạn phải load toàn bộ KV cache từ HBM lên SRAM. Continuous batching không giảm số phép tính, nhưng nó giúp GPU luôn có dữ liệu để nhồi vào pipeline, tránh "đói" dữ liệu.

Selective Batching (từ Orca): Không phải tất cả operations đều cần mask. FFN và LayerNorm là token-independent — bạn có thể batch chúng qua tất cả token thuộc mọi sequence. Chỉ attention cần biết "token này thuộc về ai". FlashAttention và PagedAttention giúp fuse các phép tính attention rời rạc này thành một kernel duy nhất.

Paged KV-Cache: Để swap request liên tục, bạn không thể cấp phát bộ nhớ liên tục (contiguous) cho mỗi sequence. PagedAttention chia KV cache thành các block 16-token, cấp phát động như virtual memory của OS. Khi request mới đến, hệ thống chỉ cần gán các block trống rải, không cần "dọn dẹp" bộ nhớ.

Ý nghĩa thực tế

Throughput thực tế:

  • 23× so với HuggingFace Transformers (Anyscale/vLLM benchmarks trên ShareGPT workload).
  • so với naive batching dùng Ray Serve hay TGI.
  • 30× speedup trên A100 với model 34B (cộng đồng LocalLLaMA báo cáo).

Trade-offs:

  • Không giảm latency per token: Mỗi token vẫn mất cùng thời gian tính toán. Tốc độ cải thiện đến từ việc GPU không bao giờ nghỉ, không phải từ việc tính nhanh hơn.
  • TTFT (Time To First Token): Có thể tăng nhẹ dưới load nặng, vì prefill của request mới phải xen kẽ với decode của request cũ.
  • Memory management phức tạp: Cần xử lý fragmentation, preemption (swap cache ra CPU khi hết VRAM), và starvation (prefill dài chiếm quá nhiều slot).

Ai đang dùng:

  • vLLM, HuggingFace TGI, TensorRT-LLM, NVIDIA Triton In-Flight Batcher, Ray Serve.
  • Production systems: Claude, GPT-4, LMSYS Chatbot Arena — bất kỳ hệ thống nào cần throughput cao đều dùng continuous batching.

Các giới hạn:

  • Vẫn chịu giới hạn bởi memory bandwidth; lợi ích giảm nếu model nhỏ đã fit trong L2 cache (hiếm gặp với LLM).
  • Prefill-heavy workload (prompt dài) có thể "bóp nghẹt" decode nếu không dùng chunked prefill để chia nhỏ.

Đào sâu hơn

Paper gốc:

Bài liên quan TroiSinh:

Cùng cụm (KV Cache & Inference):

  • KV Cache — Đừng tính lại cái đã tính, cache K và V.
  • PagedAttention — Virtual memory cho AI, waste giảm từ 70% → 4%.
  • Prefix Caching — System prompt giống nhau? Tính 1 lần, dùng ngàn lần.
  • Speculative Decoding — Model nhỏ draft, model lớn verify song song.
  • Beam Search — Giữ N candidate thay vì greedy, tìm output tốt hơn.
  • Constrained Decoding — Ép output theo grammar, JSON luôn valid.

Đọc tiếp:

External resources:

On this page