𝗞𝗩 𝗖𝗮𝗰𝗵𝗲 𝗮𝗻𝗱 𝗣𝗮𝗴𝗲𝗱𝗔𝘁𝘁𝗲𝗻𝘁𝗶𝗼𝗻: 𝗪𝗵𝘆 𝗬𝗼𝘂𝗿 𝗟𝗟𝗠 𝗦𝗲𝗿𝘃𝗲𝗿 𝗦𝗹𝗼𝘄𝘀 𝗗𝗼𝘄𝗻

Máy chủ LLM của bạn đang chạy chậm.

Bạn triển khai một mô hình 70B trên bốn GPU A100. Mọi thứ đều ổn lúc 8 giờ sáng. Đến giờ trưa, độ trễ (latency) tăng gấp đôi. Bạn kiểm tra bộ nhớ. Hầu hết bộ nhớ bị chiếm dụng bởi các "tensor buffers". Thực chất, đây là các trạng thái được lưu trong bộ nhớ đệm (cached states) từ các cuộc hội thoại cũ.

Đây chính là vấn đề của KV cache. Nó là nút thắt cổ chai lớn nhất trong việc phục vụ (serving) LLM trong môi trường thực tế (production).

KV cache là gì?

Mọi mô hình transformer đều tạo ra các token theo từng bước một. Để tạo ra một token mới, mô hình cần các tensor Key và Value từ tất cả các token trước đó. Việc tính toán lại những thứ này mỗi lần là quá chậm. Thay vào đó, công cụ (engine) sẽ lưu trữ chúng. Phần lưu trữ này chính là KV cache.

Vấn đề bộ nhớ:

Đối với mô hình Llama 3.1 70B, một chuỗi (sequence) 4096 token duy nhất cần khoảng 1,3 GB bộ nhớ.

Nếu bạn có 256 người dùng cùng lúc, bạn cần tới 336 GB bộ nhớ. Con số này vượt quá khả năng lưu trữ của bốn GPU A100. KV cache tăng trưởng nhanh đến mức nó thường chiếm nhiều bộ nhớ hơn cả chính các trọng số (weights) của mô hình.

Quản lý bộ nhớ truyền thống thất bại vì:

  • Phân mảnh nội bộ (Internal fragmentation): Bạn cấp phát không gian cho 4096 token nhưng chỉ sử dụng 300. Bạn lãng phí 93% không gian đó.
  • Không có sự chia sẻ: Hai người dùng có cùng một system prompt sẽ mỗi người lưu trữ một bản sao riêng của prompt đó.
  • Loại bỏ kiểu "tất cả hoặc không có gì" (All-or-nothing eviction): Khi hết bộ nhớ, bạn phải chuyển toàn bộ chuỗi sang CPU. Điều này làm đình trệ (stall) GPU.

PagedAttention giải quyết vấn đề này như thế nào:

PagedAttention hoạt động giống như một hệ điều hành. Nó chia KV cache thành các khối nhỏ có kích thước cố định gọi là các pages (trang).

Điều này giải quyết ba vấn đề chính:

  • Cấp phát theo nhu cầu (On-demand allocation): Một chuỗi chỉ chiếm các trang khi nó phát triển. Bạn không lãng phí bộ nhớ cho dung lượng không sử dụng.
  • Hỗ trợ tiền tố dùng chung (Shared prefix support): Nhiều người dùng có thể chia sẻ cùng các trang vật lý cho một system prompt chung. Điều này sử dụng logic "copy-on-write" để tiết kiệm một lượng lớn bộ nhớ.
  • Loại bỏ ở mức độ chi tiết (Fine-grained eviction): Khi bộ nhớ đầy, hệ thống sẽ chuyển các trang nhỏ sang CPU thay vì chuyển cả những chuỗi khổng lồ.

Kết quả:

Sử dụng PagedAttention (công nghệ bên trong vLLM) có thể tăng thông lượng (throughput) lên gấp 2 đến 4 lần so với các phương pháp truyền thống.

Khi nào nên dùng:

  • Tính đồng thời cao (High concurrency).
  • Các chuỗi có độ dài khác nhau.
  • Các prompt có phần bắt đầu giống nhau.

Khi nào nên bỏ qua:

  • Suy luận cục bộ (local inference) cho một người dùng.
  • Các mô hình rất nhỏ.
  • Các tác vụ mà mọi chuỗi đều có độ dài chính xác như nhau.

Source: https://dev.to/tech_nuggets/kv-cache-and-pagedattention-what-they-do-and-why-they-matter-jce

Optional learning community: https://t.me/GyaanSetuAi