vLLM คืออะไร และทำไม throughput ถึงกระโดดเมื่อย้ายมาใช้

โดย vLLM Bangkok9 นาที
Read in English

ถ้าคุณเคยย้ายโมเดลมาใช้ vLLM แล้วเห็น throughput เพิ่มขึ้นหลายเท่าโดยไม่ได้แตะตัวโมเดลเลย บทความนี้อธิบายว่ามันมาจากไหน

มีสองแนวคิดที่ทำงานหลัก

1. คอขวดคือ KV cache ไม่ใช่การคำนวณ

ตอนโมเดลสร้างข้อความ มันจะเก็บ KV cache — attention key และ value ของทุก token ที่ผ่านมา — เพื่อไม่ต้องคำนวณ prefix ใหม่ทั้งหมดในทุก token ที่สร้าง cache นี้ใหญ่ และโตขึ้นทุกครั้งที่สร้าง token เพิ่ม

วิธีเก็บแบบตรงไปตรงมาคือจองหน่วยความจำ GPU เป็นบล็อกต่อเนื่องหนึ่งก้อนต่อหนึ่ง request โดยจองเผื่อความยาวสูงสุดที่ request นั้นอาจสร้างได้ และนั่นคือจุดที่ความสูญเปล่าอยู่:

  • request ที่อนุญาตไว้ 2,048 token แต่หยุดที่ 100 เท่ากับจองไว้มากกว่าที่ใช้จริง 20 เท่า
  • หน่วยความจำที่จองแล้วไม่ได้ใช้ ให้ request อื่นยืมไม่ได้
  • คุณต้องออกแบบทั้งเซิร์ฟเวอร์เผื่อกรณีแย่สุด ทำให้ concurrency ต่ำอยู่ตลอด

ทีมส่วนใหญ่เจอปัญหานี้ในรูป “GPU ยังมีหน่วยความจำว่างเยอะ แต่พอเพิ่ม concurrency แล้ว out-of-memory”

2. PagedAttention: มองหน่วยความจำ GPU แบบ virtual memory

ไอเดียหลักของ vLLM ยืมมาจากระบบปฏิบัติการ แทนที่จะจองพื้นที่ต่อเนื่องก้อนเดียวต่อ request มันแบ่ง KV cache เป็น บล็อก ขนาดคงที่ แล้วใช้ block table แมปตำแหน่ง token เชิงตรรกะของแต่ละ request ไปยังบล็อกจริงที่อยู่ตรงไหนของหน่วยความจำก็ได้

ผลที่ตามมาเห็นได้ทันที:

  • แทบไม่มี internal fragmentation request ใช้บล็อกไปเรื่อย ๆ ตามที่สร้างจริง ไม่ใช่จองล่วงหน้า ความสูญเปล่าเหลืออย่างมากแค่บล็อกที่ยังเติมไม่เต็มหนึ่งบล็อกต่อ sequence
  • การแชร์แทบไม่มีต้นทุน request สองอันที่มี prefix เดียวกัน — system prompt ร่วม, few-shot preamble, เอกสาร RAG — สามารถชี้ไปที่บล็อกจริง เดียวกัน แทนที่จะเก็บสองชุด สำหรับงานที่มี prefix ยาวคงที่ แค่ข้อนี้ก็ช่วยได้มาก
  • concurrency สูงขึ้น ใส่ request ได้มากขึ้นบนการ์ดใบเดิม ซึ่งคือที่มาจริง ๆ ของตัวเลข throughput

ชื่อก็มาจากตรงนี้ตรง ๆ: paging ที่เอามาใช้กับ attention

3. Continuous batching: เลิกรอ request ที่ช้าที่สุด

แนวคิดที่สองเป็นเรื่องการจัดคิว static batching แบบดั้งเดิมจะรวบ request N อัน รันพร้อมกัน แล้วคืนผลเมื่อครบทั้ง N เสร็จ ในเมื่อความยาวการสร้างต่างกันมาก batch จึงเดินด้วยความเร็วของตัวที่ช้าที่สุด และ GPU ก็นั่งว่างในช่องที่เสร็จไปแล้ว

Continuous batching ทำงานที่ระดับ iteration แทน หลังจบ decoding step แต่ละครั้ง scheduler สามารถเอา sequence ที่เสร็จแล้วออกและรับตัวที่รออยู่เข้ามาได้ทันที batch จึงถูกเติมต่อเนื่อง แทนที่จะรอให้หมดแล้วค่อยเติมใหม่

สำหรับทราฟฟิกที่ปนกัน — บาง request อยากได้ 20 token บางอันอยากได้ 2,000 — นี่คือความต่างระหว่าง GPU ที่ทำงานอยู่กับ GPU ที่นั่งรอ

แล้วในทางปฏิบัติหมายความว่าอย่างไร

มีข้อสรุปบางอย่างที่ควรเข้าใจก่อนจะไปจูนอะไร

throughput กับ latency เป็นลูกบิด ไม่ใช่ค่าคงที่คู่กัน sequence ที่รันพร้อมกันมากขึ้น = token ต่อวินาทีรวมสูงขึ้น และ latency ต่อ request สูงขึ้น ต้องตัดสินใจว่าโปรดักต์ของคุณจ่ายเงินเพื่ออะไรกันแน่

prefix ร่วมที่ยาวคุ้มค่าที่จะออกแบบเผื่อ ถ้าทุก request แบก system prompt เดียวกัน 800 token การแชร์ prefix กำลังทำงานให้คุณอยู่จริง ๆ รักษาส่วนที่ใช้ร่วมกันให้เหมือนกันระดับไบต์และวางไว้ข้างหน้า — การใส่ timestamp รายคำขอไว้ตำแหน่งแรกทำลายการแชร์นี้ไปเงียบ ๆ

--max-model-len คือการตัดสินใจเรื่องหน่วยความจำ มันกำหนดขอบเขต KV cache ต่อ sequence และจึงกำหนดว่ากี่ sequence จะอยู่พร้อมกันได้ การตั้งไว้เท่าค่าสูงสุดของโมเดล “เผื่อไว้ก่อน” คือการตัด concurrency ของตัวเองแบบเงียบ ๆ

จับตาดู preemption เมื่อหน่วยความจำหมด vLLM จะ preempt แล้วค่อยคำนวณใหม่หรือ swap sequence กลับมา ตัวเลข preemption ที่ไต่ขึ้นใน metrics แปลว่าคุณรับงานเกินตัว — นั่นคือสัญญาณให้ลด concurrency หรือเพิ่มหน่วยความจำ ก่อนที่ latency พุ่งจะไปโผล่เป็นคำร้องเรียนจากผู้ใช้

สำหรับงานภาษาไทยโดยเฉพาะ

มีรายละเอียดหนึ่งที่ทีมในบ้านเรามักสะดุด: ภาษาไทย tokenize ได้ไม่ดีในโมเดล multilingual ส่วนใหญ่ ภาษาไทยไม่มีช่องว่างระหว่างคำ และ tokenizer ที่เทรนด้วยภาษาอังกฤษเป็นหลักมักออกมาเป็นหนึ่ง token ต่อหนึ่งอักขระหรือต่อกลุ่มสั้น ๆ prompt ภาษาไทยจึงกิน token มากกว่าคำแปลภาษาอังกฤษที่ความหมายเท่ากันอย่างเห็นได้ชัด

และมันกระทบทุกอย่างที่เล่ามาข้างบนโดยตรง — token ต่อ request มากขึ้น แปลว่า KV cache ต่อ request มากขึ้น แปลว่า sequence ที่รันพร้อมกันได้บนการ์ดใบเดิมน้อยลง ถ้าคุณตั้งงบหน่วยความจำ GPU จาก benchmark ภาษาอังกฤษแต่เสิร์ฟทราฟฟิกภาษาไทย วัดจำนวน token จริงของคุณก่อนกำหนดขนาด deployment

อ่านต่อ

  • repository ของ vLLM และเอกสารประกอบ
  • เปเปอร์ PagedAttention: Efficient Memory Management for Large Language Model Serving with PagedAttention
  • และในวันที่ 6 กันยายน ถาม maintainer ได้โดยตรงที่ vLLM Bangkok Day — คนที่เขียนมันเอง

แท็ก

  • vllm
  • inference
  • พื้นฐาน

บทความอื่น

ภาพปกรีวิวเปเปอร์ DSpark พร้อมกราฟแท่ง prefix survival ของ draft token of, course, I และ can ที่ 0.95, 0.86, 0.60 และ 0.30 โดยที่ heavy load จะ verify สอง token แรก และที่ light load จะ verify ครบทั้งสี่ตัว
53 นาที

รีวิวเปเปอร์ DSpark: Confidence-Scheduled Speculative Decoding with Semi-Autoregressive Generation

รีวิวเปเปอร์ว่า DSpark ช่วยให้ speculative decoding ดีขึ้นได้อย่างไร ในบทความนี้เราจะพาไปดูว่า DSpark ออกแบบมาอย่างไร และทำไมถึงเพิ่ม throughput ได้ด้วย accepted length ที่สูงขึ้น

  • vllm
  • inference
  • speculative-decoding
สไลด์แรกของเด็คสรุปภาษาไทย: ชื่อทอล์ก Serving the Agentic Workload บนพื้นสีกรมท่าเข้มลายตารางพิกเซล ผู้บรรยาย Simon Mo
40 นาที

สรุปทอล์ก Serving the Agentic Workload ของ Simon Mo: งาน AI agent เปลี่ยนการ serve โมเดลอย่างไร

สรุปภาษาไทยจากทอล์กของ Simon Mo (Inferact) ที่ Runtime 2026 ว่าทำไมงาน AI agent ที่อ่าน context ยาวแต่ตอบสั้นทำให้ KV cache กลายเป็นหัวใจของการ serve โมเดล ทีม vLLM แก้อย่างไร และ hardware หลายค่ายเข้ามาเกี่ยวตรงไหน พร้อมสไลด์และแหล่งอ้างอิง

  • vllm
  • inference
  • agent
6 นาที★

vLLM Bangkok Day: ผู้สร้าง vLLM กำลังจะมากรุงเทพฯ

วันที่ 6 กันยายน 2569 ทีมผู้สร้าง vLLM จะมากรุงเทพฯ พร้อมกับหนึ่งบ่ายเต็มของ การพูดคุยเรื่อง inference บนงานจริง เคสจากทีมไทย และการพบปะสร้างเครือข่าย เข้าร่วมฟรี — นี่คือสิ่งที่จะได้เจอ

  • งานอีเวนต์
  • คอมมูนิตี้