Continuous Batching
Batching liên tục tạo lại batch của máy chủ LLM ở mỗi bước giải mã, nhờ đó các yêu cầu đã hoàn tất được loại khỏi batch, yêu cầu mới được thêm vào và GPU luôn hoạt động.
Batching liên tục, còn gọi là lập lịch ở cấp độ vòng lặp hoặc batching trong lúc xử lý, là kỹ thuật lập lịch để phục vụ các model sinh, trong đó server xây dựng lại batch ở mỗi bước giải mã. Một chuỗi hoàn tất sẽ rời batch ngay lập tức và trả về kết quả, còn yêu cầu đang chờ sẽ thay thế chuỗi đó ở bước tiếp theo. Gyeong-In Yu cùng các đồng nghiệp tại Đại học Quốc gia Seoul và FriendliAI giới thiệu phương pháp này trong Orca tại OSDI 2022, báo cáo thông lượng cao hơn 36.9x so với NVIDIA FasterTransformer trên GPT-3 175B ở cùng độ trễ. Tên gọi batching liên tục phổ biến vào năm 2023 khi vLLM và Hugging Face Text Generation Inference áp dụng phương pháp này; hiện nay đây là bộ lập lịch mặc định trong các engine phục vụ đứng sau mô hình ngôn ngữ lớn (LLMs).
Vì sao Batching ở Cấp độ Yêu cầu Lãng phí GPU#
Sinh văn bản tạo ra một token trong mỗi lượt forward, và mỗi yêu cầu cần số lượt rất khác nhau: câu trả lời có hoặc không kết thúc sau vài token, trong khi một file code có thể kéo dài đến hàng nghìn token. Với batching tĩnh, một nhóm yêu cầu được giữ cùng nhau cho đến khi yêu cầu dài nhất hoàn tất. Các slot có chuỗi kết thúc sớm sẽ bị bỏ trống, còn yêu cầu mới phải chờ cả nhóm được xử lý xong, làm tăng độ trễ suy luận cho mọi yêu cầu ngắn đang xếp hàng phía sau yêu cầu dài.
Batching động, cơ chế ở cấp độ yêu cầu được dùng trong các server như NVIDIA Triton, thu thập các yêu cầu đến trong một khoảng thời gian ngắn và chạy chúng thành một batch cho đến khi hoàn tất. Cách này phù hợp với các model có chi phí cố định cho mỗi đầu vào, chẳng hạn như model phân loại ảnh hoặc model phát hiện đối tượng, vì mỗi đầu vào hoàn tất chỉ sau một lượt forward. Chế độ predict của Ultralytics YOLO tạo batch ở cấp độ yêu cầu từ các đầu vào YOLO26 lấy từ nguồn: một file .streams chứa URL camera chạy thành một batch gồm khung hình mới nhất từ mỗi luồng, nên 8 luồng chạy với batch size 8; đối số batch nhóm các khung hình từ video, thư mục hoặc danh sách ảnh .txt vào một lượt forward.
Cách Lập lịch ở Cấp độ Vòng lặp Hoạt động#
Bộ lập lịch chạy một bước giải mã cho mỗi chuỗi đang hoạt động, sau đó kiểm tra từng chuỗi để tìm token kết thúc chuỗi hoặc giới hạn độ dài. Các chuỗi đã hoàn tất được trả về và bộ nhớ của chúng được giải phóng; các yêu cầu đang xếp hàng được tiếp nhận nếu vừa với KV cache. Orca xử lý (prefill) prompt của yêu cầu mới đến trong cùng bước giải mã các chuỗi khác; các engine hiện nay cũng thực hiện tương tự với prefill phân đoạn.
Việc kết hợp các chuỗi có độ dài khác nhau cần thêm một ý tưởng nữa, được Orca gọi là batching chọn lọc. Các phép toán xử lý độc lập từng token, chẳng hạn phép nhân ma trận lớn trong mỗi lớp transformer, chạy đồng thời trên mọi token của tất cả chuỗi. Attention chạy riêng cho từng chuỗi, vì mỗi chuỗi có độ dài ngữ cảnh riêng.
Mô phỏng này lập lịch cùng tám yêu cầu trên một GPU giải mã đồng thời bốn chuỗi:
import heapq
output_lengths = [5, 50, 8, 12, 40, 3, 30, 7] # tokens each queued request will generate
slots = 4 # sequences the GPU decodes together at each step
# Static batching: each group of 4 runs until its longest request finishes
static_steps = sum(max(output_lengths[i : i + slots]) for i in range(0, len(output_lengths), slots))
# Continuous batching: the next request takes the first slot that frees up
slot_free_at = [0] * slots
for length in output_lengths:
start = heapq.heappop(slot_free_at)
heapq.heappush(slot_free_at, start + length)
continuous_steps = max(slot_free_at)
for name, steps in [("static", static_steps), ("continuous", continuous_steps)]:
print(f"{name}: {steps} decode steps, slots busy {sum(output_lengths) / (steps * slots):.0%}")Batching tĩnh cần 90 bước giải mã và giữ các slot bận 43% thời gian. Batching liên tục hoàn tất trong 50 bước, bằng độ dài của yêu cầu dài nhất, với các slot bận 78% thời gian.
Giới hạn và Kỹ thuật Bổ trợ#
Batch đang chạy lớn hơn làm tăng thông lượng tổng thể, nhưng mỗi bước mất nhiều thời gian hơn, khiến thời gian cho mỗi token đầu ra tăng. Vì vậy, các engine giới hạn số chuỗi chạy đồng thời và số token được xử lý mỗi bước; vLLM cung cấp các giới hạn này qua max_num_seqs và max_num_batched_tokens, đồng thời kết hợp batching liên tục với một số kỹ thuật liên quan:
- PagedAttention: Cấp phát KV cache thành các khối nhỏ, để chuỗi hoàn tất giải phóng bộ nhớ ngay lập tức và chuỗi mới chỉ chiếm phần bộ nhớ mà nó sử dụng.
- Prefill phân đoạn: Chia prompt dài thành nhiều phần để prefill của yêu cầu mới không làm đình trệ quá trình giải mã của các yêu cầu khác.
- Giải mã suy đoán: Mang lại hiệu quả cao nhất ở batch size nhỏ, vì các batch liên tục lớn vốn đã sử dụng phần lớn năng lực tính toán của GPU.










