localaiforum
Đăng nhập
Hướng dẫn › Chạy & phục vụ

Xử lý theo lô & nhiều người dùng

Một request mỗi lần là cách mọi phiên desktop bắt đầu — và nó lãng phí một GPU. Toàn bộ ván chơi của phục vụ là xử lý theo lô: làm một lượt qua trọng số phục vụ nhiều request cùng lúc. Trang này bao vì sao điều đó hiệu quả, batching liên tục và paged attention thực sự là gì, khi nào bạn cần engine phục vụ thật, và cách chọn cỡ.

Vì sao phục vụ tuần tự lãng phí GPU

Nhớ lại công thức tốc độ: mỗi token decode đọc gần như toàn bộ trọng số kích hoạt một lần (tốc độ). Phục vụ một luồng, GPU làm trọn lượt đọc đó cho một token của một người dùng. Giờ gộp lô tám luồng vào cùng lượt forward: trọng số đọc một lần và dùng cho tám chuỗi — phần số học thêm gần như miễn phí, vì decode chặn-bởi-băng-thông, không phải chặn-bởi-tính-toán. Tốc độ mỗi luồng gần như không giảm trong khi tổng thông lượng leo gần tuyến tính, cho đến khi bạn bão hòa băng thông hay bộ nhớ KV. Riêng sự kiện đó là toàn bộ kinh tế học của phục vụ cục bộ.

Batching tĩnh vs liên tục

Bản ngây thơ — batching tĩnh — nhóm các request đến cùng nhau và chạy lô đến khi mọi thành viên xong. Nó hoạt động, nhưng tệ:

Batching tĩnh Batching liên tục
Lô được lập Một lần, khi nhóm tụ đủ Đánh giá lại mỗi bước decode
Gia nhập giữa chừng Không — chờ lô kế Có, khe đầy dần theo request đến
Request ngắn trong lô toàn request dài Bị chặn đến khi cái dài nhất xong Xong và giải phóng khe ngay
Độ trễ đuôi Tệ (chặn đầu hàng) Tốt

Batching liên tục (cấp-độ-lặp) — mặc định trong vLLM và SGLang — là lý do những engine đó trụ vững dưới lưu lượng thật trong khi server ngây thơ sụp.

Paged attention: chữa phân mảnh KV

Mỗi request đang hoạt động cần bộ nhớ KV cache (xem KV cache). Cách cũ giữ sẵn ngữ cảnh tối đa của mỗi request ngay từ đầu — nên một cuộc chat dùng 2k token có thể nắm một khối 32k đặt trước, khóa chặt không ai dùng được. Phần lớn bể KV ngồi không. Paged attention lưu KV trong các khối kích-thước-cố-định cấp theo nhu cầu, như HĐH phân trang bộ nhớ: lãng phí rơi từ phần đông (tác giả vLLM báo 60–80% trong bài báo của họ) xuống vài phần trăm, gấp mấy lần chuỗi đồng thời vừa hơn, và thông lượng theo sau. Cùng ý tưởng, giờ chuẩn across các engine phục vụ.

Chi phí cho bạn: không gì hướng người dùng — đó là thay đổi bộ cấp phát; bạn chỉ thấy dung lượng đồng thời cao hơn trên cùng GPU.

Khi nào bạn cần engine phục vụ thật

Khối lượng công việc Engine
Bạn cộng gia đình, vài cuộc chat tuần tự Ollama / LM Studio — đã ổn rồi
Vài dev lụi cụi đồng thời llama-server với khe song song, hoặc biến môi trường parallel của Ollama
Lưu lượng sản phẩm, chat đội nhóm, người dùng thật vLLM hoặc SGLang
Đội agent chia sẻ system prompt dài SGLang (cache tiền tố) hoặc vLLM

Góc trò chơi của diễn đàn này là ví dụ kinh điển của hàng cuối: các trận cờ vua và cờ janggi chạy vài agent, mỗi agent xin một nước mỗi giây một lần — prompt nhỏ, nhiều luồng, system prompt dùng chung. Đó chính xác là khối lượng công việc muốn engine phục vụ có batching, không phải ollama run trong vòng lặp (xem agent).

Thông lượng vs độ trễ

Mọi núm đổi cái này lấy cái kia: lô lớn nâng tổng tok/s trong khi hạ nhẹ tốc độ mỗi luồng, và xếp hàng nâng TTFT dưới tải. Trợ lý lập trình cho một người muốn giới hạn đồng thời ở 1–2 để luồng của người chưa bao giờ xếp hàng. Dịch vụ chat cho ba mươi người muốn lô chất đầy. Quyết định bạn là cái nào trước khi tinh chỉnh (xem phục vụ về TTFT vs decode như hai phép đo riêng).

Gần nhất với bữa trưa miễn phí là cache tiền tố (SGLang): prompt dài lặp lại biến thành prefill gần bằng không, vốn là đa số khối lượng công việc agent.

Núm thực dụng

# llama.cpp: khe decode song song (ngữ cảnh bị chia across các khe)
llama-server -m model.gguf -c 32768 -np 4

# Ollama: request song song mỗi mô hình (khởi động lại dịch vụ sau khi đặt)
export OLLAMA_NUM_PARALLEL=4

# vLLM: hai cái quan trọng
vllm serve model --max-num-seqs 32 --gpu-memory-utilization 0.90

Xếp hàng xảy ra thượng nguồn của tất cả những cái này: khi mọi khe bận, request mới chờ. Theo dõi độ sâu hàng đợi và TTFT, không phải cảm tính.

Đặt giới hạn thượng nguồn nữa: một reverse proxy với trần kết nối hỏng nhanh và trung thực, trong khi hàng đợi sâu hỏng chậm và bí ẩn.

Hoạch định dung lượng, đại khái

Chi phí của một request ngoài trọng số là KV cache, mỗi token, cho toàn bộ ngữ cảnh của nó:

byte KV/token ≈ 2 × tầng × kv_heads × head_dim × bytes_per_value

Ví dụ minh họa, mô hình dense 8B điển hình (32 tầng, 8 đầu KV, đầu dim 128, giá trị fp16):
2 × 32 × 8 × 128 × 2 B ≈ 131 KB mỗi token → một hội thoại 2k-token ≈ 256 MiB KV → mười cuộc chat như vậy ≈ 2.5 GB chồng lên ~5 GB trọng số.

(số 2 là K và V; xem KV cache). Agent ngữ-cảnh-dài do đó đắt hơn hẳn mỗi request so với chat. Bảng thoải mái đại khái, rào đón kỹ — ngữ cảnh độ dài chat, chỉ cấp-độ-lớn:

GPU Mô hình Số chat nhẹ đồng thời đại khái
8 GB 7–8B Q4 1–3
24 GB 8B Q4 ~10–30
24 GB 32B Q4 ~3–8
48 GB 70B Q4 ~5–15

Đo bằng prompt thật của bạn: độ dài ngữ cảnh di chuyển những con số này hơn bất kỳ biến nào khác.

Tín hiệu bạn đã bão hòa

  • TTFT leo từ mili-giây lên giây trong ngày.
  • Độ sâu hàng đợi dai dẳng trên không; request chờ trước token đầu.
  • tok/s mỗi luồng chùng khi lô chất chặt.
  • Log vLLM hiện preemption hoặc tính lại KV — áp lực bộ nhớ, không phải mô hình chậm.

Bất kỳ cái nào: trần ngữ cảnh, lượng hóa KV cache, hoặc thêm GPU — theo thứ tự rẻ đó — trước khi người dùng của bạn càu nhàu to.

Vẽ đồ thị TTFT và độ sâu hàng đợi trong một ngày — leo đều nghĩa là thiếu dung lượng, răng cưa nghĩa là các cú bùng nổ bạn có thể hấp thụ bằng hàng đợi.

Thuê vs mua, phác thảo

Tại thời điểm viết, GPU hạng 24GB thuê chạy chừng $0.50–2/giờ, và card 24GB cũ giá vài trăm đô — hòa vốn đâu đó quanh 300–1,000 giờ sinh thật. Cục bộ thắng ở riêng tư, độ trễ và không giới hạn tốc độ (khung cảnh ở vì sao cục bộ); thuê thắng ở nhu cầu bùng nổ và mô hình hạng 80GB không card tiêu dùng nào chứa (xem toán VRAM cho cái gì vừa ở đâu). Đa số người ước lượng quá cao số giờ của mình — đo một tuần thật trước khi quyết.

Liên quan: Tốc độ · KV cache · Phục vụ endpoint · toán VRAM