FDE PulseViệc làm FDE đang mở 314Mới đăng 7 ngày qua 10Chủ đề nổi bật: Đào tạo kỹ năng FDE tại Đông Nam Á

Tờ báo của nghề Forward Deployed Engineer

Bách khoa

Ước tính GPU cho model 70B: tính từ tham số, KV cache đến lượng tử hoá

Khách hỏi cần mấy GPU để chạy model trong datacenter của họ, và bạn nên có câu trả lời trước khi rời phòng họp, không phải sau khi deploy thất bại.

Đồ hoạNăm bước ước tính VRAM để chạy LLM
  1. 1Bộ nhớ trọng sốSố tham số × byte mỗi tham số: 70B ở FP16 là 140 GB, ở INT4 là 35 GB
  2. 2KV cache mỗi token2 × số layer × số KV head × head_dim × byte mỗi phần tử
  3. 3Nhân theo tải thật× độ dài context (tính cả câu trả lời) × số request đồng thời
  4. 4Cộng dự phòng 10–20%Cho activation, CUDA context và framework
  5. 5So với VRAM của kháchThiếu thì lượng tử hoá, giảm context hoặc thêm GPU, rồi đo lại

Trọng số chỉ là bước đầu; KV cache theo context và số người dùng thường quyết định số GPU.

Đồ hoạ: FDE Times

Tóm tắt nhanh

  • Trọng số chỉ là phần đầu: 70B tham số ở FP16 đã tốn 140 GB, chưa kể KV cache và overhead.
  • KV cache tăng theo độ dài context và số người dùng cùng lúc, nên đó là con số bạn phải hỏi khách.
  • INT4 có thể đưa model 70B từ hai GPU 80 GB xuống một, nhưng hãy đo lại bằng get_memory_footprint.
Chia sẻLinkedInFacebookX

Buổi họp thứ hai với một khách hàng ngân hàng. Đội hạ tầng của họ không cho dữ liệu ra ngoài, nên model phải chạy on-prem, và trưởng phòng IT hỏi thẳng: “Chạy model 70B thì cần mua mấy card?” Nếu bạn trả lời “để em về kiểm tra”, bạn mất một tuần.

Nếu bạn trả lời sai, khách mất tiền mua phần cứng mà model vẫn không chạy nổi.

Khi model phải chạy trong hạ tầng của khách, bạn nên làm được ngay tại bàn họp việc biến một tên model thành con số gigabyte, rồi thành số GPU. Phép tính không khó. Cái khó là biết phải tính những phần nào, và phần nào khách không tự nói ra.

Lộ trình dưới đây đi từ khái niệm tham số, qua một ví dụ tính tay đầy đủ cho model 70B, đến đoạn code để kiểm chứng. Cuối cùng là những lỗi khiến bản ước tính lệch gấp đôi.

Tham số là gì, và vì sao nó quyết định số GPU?

IBM định nghĩa tham số của LLM là những thiết lập điều khiển đầu ra và hành vi của model, với hai loại chính là trọng số (weights) và độ lệch (biases). Trọng số là các giá trị số thể hiện mức độ quan trọng model gán cho một đầu vào cụ thể. Gộp cả hai lại, một model có thể có hàng tỷ tham số.

Với người làm deployment, mỗi tham số là một con số phải nằm trong bộ nhớ GPU khi model chạy. Vì thế công thức đầu tiên rất đơn giản: bộ nhớ trọng số = số tham số × số byte mỗi tham số. Chữ “70B” trong tên model chính là số tham số; việc còn lại là biết mỗi tham số chiếm bao nhiêu byte.

Đó là chỗ lượng tử hoá (quantization) xuất hiện. IBM mô tả nó là cách đơn giản hoá toàn bộ phép toán bên trong model, giúp model nhỏ hơn và hiệu quả hơn. Thay vì lưu mỗi trọng số bằng 2 byte (FP16/BF16), ta lưu bằng 1 byte (INT8) hoặc nửa byte (INT4).

Độ chính xác Byte mỗi tham số Trọng số của model 70B
FP16 / BF16 2 140 GB
INT8 1 70 GB
INT4 0,5 35 GB

Hugging Face ghi rõ trong tài liệu Transformers rằng lượng tử hoá 8-bit bằng bitsandbytes giảm một nửa bộ nhớ so với 16-bit, còn 4-bit nén thêm nữa. Chỉ riêng trọng số, 140 GB ở FP16 đã vượt một GPU 80 GB.

Đó là lý do một bài phân tích trên Machine Learning at Scale viết rằng INT4 biến model 70B từ chỗ cần hai GPU 80 GB thành vừa trên một.

Trọng số mới là nửa câu chuyện

Nếu dừng ở bảng trên, bạn sẽ báo khách “INT4, một card 80 GB là đủ” và có thể sai. Khi phục vụ request, model còn giữ KV cache: các vector key và value của mọi token đã xử lý, để không phải tính lại ở mỗi bước sinh token mới.

Công thức cho mỗi token là: kv_bytes_per_token = 2 × n_layers × n_kv_heads × head_dim × bytes_per_element. Hệ số 2 là vì có cả key lẫn value. Các thông số còn lại nằm trong file config của model, bạn đọc trực tiếp từ đó.

KV cache phình theo context window, tức toàn bộ văn bản model có thể tham chiếu khi sinh câu trả lời. Tài liệu của Claude nhấn mạnh context window tính cả phần trả lời. Nghĩa là một request với prompt 6.000 token và câu trả lời 2.000 token chiếm KV cache của 8.000 token, không phải 6.000.

Tính tay một ca cụ thể

Thử hình dung model 70B của khách ngân hàng có cấu hình giả định sau: 80 layer, 8 KV head, head_dim 128, KV cache lưu ở 2 byte mỗi phần tử. Các con số này chỉ để minh hoạ; khi làm thật, bạn lấy từ config.json của model.

KV mỗi token = 2 × 80 × 8 × 128 × 2 = 327.680 byte, khoảng 0,33 MB. Khách cho biết context điển hình là 8.192 token và muốn phục vụ 10 người dùng cùng lúc. Một request tốn 327.680 × 8.192 ≈ 2,68 GB, mười request tốn khoảng 26,8 GB.

Giờ cộng lại. Ở INT4: 35 GB trọng số + 26,8 GB KV cache = 61,8 GB. Machine Learning at Scale khuyên dành thêm 10–20% trên tổng trọng số và KV cache cho activation, CUDA context và framework; lấy mức 20% cho an toàn, ta được khoảng 74,2 GB. Vừa một GPU 80 GB, nhưng sát nút.

Ở FP16, phép tính đổi hẳn: 140 + 26,8 = 166,8 GB, cộng 20% là khoảng 200 GB. Hai GPU 80 GB chứa được trọng số nhưng không đủ cho tải này; bạn cần ba card, hoặc giảm số người dùng đồng thời. Cùng một model, khác độ chính xác, chênh nhau hai card.

Bây giờ khách nói thêm: “Bọn anh muốn nhét cả hợp đồng dài, cỡ 32 nghìn token.” Giả sử context lúc này là 32.768 token.

Một request tốn 327.680 × 32.768 ≈ 10,7 GB KV cache, mười request là khoảng 107 GB. Cộng 35 GB trọng số INT4 và 20% dự phòng, tổng lên khoảng 171 GB, tức ba GPU 80 GB thay vì một. Phương án một card vừa nãy sụp đổ chỉ vì một câu hỏi về độ dài tài liệu.

Context dài còn tốn thêm ở chỗ khác

Bộ nhớ chưa phải chi phí duy nhất. IBM lưu ý yêu cầu tính toán của attention tăng theo bình phương độ dài chuỗi, nên request dài tốn tài nguyên không tương xứng. Tài liệu của Claude cũng cảnh báo context dài hơn không tự động tốt hơn, vì hiện tượng context rot.

Đây là lúc nên bàn lại yêu cầu với khách. Thay vì mua thêm card để nhồi cả hợp đồng 32.768 token, bạn có thể đề xuất cắt tài liệu thành đoạn và chỉ đưa phần liên quan vào prompt. Làm sizing kỹ, nhiều khi bạn tìm ra một thiết kế gọn hơn chứ không chỉ một danh sách card cần mua.

Đừng tin con số trên giấy, hãy đo

Sau khi tính tay, bạn kiểm chứng trên máy thật. Tài liệu Transformers cho phép load model ở 8-bit với device_map=“auto” để tận dụng các GPU có sẵn, và cung cấp hàm get_memory_footprint để đo model đã load. Chưa có card 80 GB thì cứ kiểm chứng công thức trên một model nhỏ trước:

from transformers import AutoModelForCausalLM, BitsAndBytesConfig

def weight_gb(params, bytes_per_param):
    return params * bytes_per_param / 1e9

def kv_gb(n_layers, n_kv_heads, head_dim, bytes_el, context, concurrency):
    per_token = 2 * n_layers * n_kv_heads * head_dim * bytes_el
    return per_token * context * concurrency / 1e9

# Ước tính cho ca 70B ở INT4 trong ví dụ trên, cộng 20% dự phòng
total = (weight_gb(70e9, 0.5) + kv_gb(80, 8, 128, 2, 8192, 10)) * 1.2
print(f"Ước tính ca 70B INT4: {total:.1f} GB")

# Kiểm chứng công thức trọng số trên một model nhỏ, load ở 8-bit (1 byte/tham số)
model_id = "ten-model-nho-cua-ban"  # thay bằng một model nhỏ bất kỳ trên Hugging Face
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    quantization_config=BitsAndBytesConfig(load_in_8bit=True),
    device_map="auto",
)
print(f"Tính tay: {weight_gb(model.num_parameters(), 1):.2f} GB")
print(f"Đo thật:  {model.get_memory_footprint() / 1e9:.2f} GB")

Hàm get_memory_footprint chỉ cho bạn phần model đã load, không phải KV cache khi có tải. Vì thế bước cuối luôn là chạy thử với số request đồng thời và độ dài context mà khách thực sự cần, rồi quan sát bộ nhớ.

Năm lỗi làm bản ước tính lệch

Lỗi phổ biến nhất là chỉ tính trọng số, như ví dụ trên: con số 35 GB trông thoải mái cho tới khi mười người dùng cùng gửi tài liệu dài. Lỗi thứ hai là quên rằng câu trả lời cũng nằm trong context, nên ước tính KV cache theo độ dài prompt.

Lỗi thứ ba là nhầm số tham số với số byte, kiểu nghĩ “70B thì cần 70 GB” mà không hỏi độ chính xác. Lỗi thứ tư là bỏ qua phần dự phòng 10–20%, rồi model crash vì hết bộ nhớ ở đúng buổi demo.

Lỗi thứ năm tinh tế hơn: coi lượng tử hoá là miễn phí. Lượng tử hoá đơn giản hoá phép toán trong model, nên bạn cần chạy bộ eval của chính khách trên bản INT4 trước khi hứa chất lượng như bản FP16. Hãy để khách thấy kết quả và tự quyết đánh đổi.

Mang kỹ năng này vào CV và buổi phỏng vấn

Khi đọc JD FDE, để ý các cụm như “on-prem deployment”, “air-gapped”, “GPU sizing” hay “inference optimization”: đó là nơi kỹ năng này được trả công. Trong CV, một dòng cụ thể có sức nặng hơn mọi tính từ, chẳng hạn mô tả việc bạn ước tính VRAM cho một model, chọn INT4 sau khi đo chất lượng, và giảm số GPU cần mua.

Ở vòng phỏng vấn tình huống, nếu được hỏi “khách muốn chạy model X, cần bao nhiêu GPU?”, đừng vội đưa ra con số.

Hãy hỏi ngược lại năm câu: khách đang có GPU gì, mỗi card bao nhiêu VRAM, mấy người dùng đồng thời, context dài bao nhiêu, và chất lượng chấp nhận được tới đâu.

Năm câu đó cho thấy bạn hiểu con số cuối cùng phụ thuộc vào những gì.

Lần tới khi khách hỏi “mấy card?”, câu trả lời đúng bắt đầu bằng “cho em hỏi lại năm câu”, và kết thúc bằng một phép tính mà cả hai bên cùng kiểm tra được.

5 nguồn
Đọc tiếp trên lộ trình · Chặng 5: Triển khaiKhi đội nguồn của khách lặng lẽ đổi schema: thực hành viết hợp đồng dữ liệu để pipeline không gãyĐội nguồn của khách sẽ có lúc đổi tên một field mà không báo trước. Pipeline của bạn có biết ngay hay không phụ thuộc vào bản hợp đồng dữ liệu bạn viết từ tuần đầu tiên.