Chaofa Yuan - Ngày 6 tháng 10 năm 2024 - Khoảng 6 phút đọc
Nội dung trang này:
- Bạn sẽ học được gì sau khi đọc bài viết này?
- Kiến thức cơ bản
- Sử dụng bộ nhớ GPU
- Suy luận
- Huấn luyện
- Giả sử sử dụng DeepSpeed để huấn luyện
- Câu hỏi thường gặp (FAQ)
- Kết bạn nào 🤣
- Trong quá trình huấn luyện và suy luận, các phần nào chiếm dụng bộ nhớ GPU?
- Với một mô hình xB, cần bao nhiêu bộ nhớ GPU cho suy luận?
- Để huấn luyện toàn bộ tham số của một mô hình xB, cần bao nhiêu bộ nhớ GPU?
- Tại sao huấn luyện với độ chính xác hỗn hợp có thể tiết kiệm bộ nhớ GPU?
- Sau khi sử dụng DeepSpeed, mỗi card GPU sẽ tiêu thụ bao nhiêu bộ nhớ?
Kiến thức cơ bản
- 1 Byte = 8 bits, 1 KB = 1024 Bytes, 1 MB = 1024 KB, 1 GB = 1024 MB
- 1 float64 = 8 Bytes = 64 bits, đây là số thực đôi (double precision floating point number)
- 1 float32 = 4 Bytes = 32 bits, đây là số thực đơn (single precision floating point number), còn gọi là fp32
- 1 float16 = 2 Bytes = 16 bits, đây là số thực nửa (half precision floating point number), còn gọi là fp16
- 1 bf16 = 2 Bytes = 16 bits, đây là định dạng Brain Floating Point, còn gọi là bf16
Sử dụng bộ nhớ GPU
Đề nghị nên đọc kỹ phân tích từ các chuyên gia, bài viết này rất hữu ích.
78win+đăng+nhập Suy luận
Trong quá trình suy luận mô hình, có hai phần chính chiếm dụng bộ nhớ j88 tặng 50k GPU: tham số mô hình và KV cache.
-
Giả sử tham số mô hình là θ, thì lượng bộ nhớ GPU mà suy luận cần dùng sẽ là 2Φ. Điều này xảy ra vì hầu hết các mô hình hiện nay trong HuggingFace đều lưu tham số ở dạng BF16, trừ khi không có yêu cầu đặc biệt, chúng ta sẽ không tải tham số dưới dạng fp32.
-
KV cache: Giả sử chiều dài chuỗi đầu vào là s, chiều dài chuỗi đầu ra là n, và KV cache được lưu trữ dưới dạng float16, thì đỉnh điểm sử dụng bộ nhớ của KV cache sẽ là: b(s+n)hl2*2 = 4blh(s+n). Trong đó, số “2” đầu tiên đại diện cho K/V cache, số “2” thứ hai đại diện cho việc float16 chiếm 2 bytes.
Theo cách tính sơ lược, bộ nhớ cần thiết cho quá trình suy luận là: 1.2 lần bộ nhớ tham số mô hình = 1.2×2Φ = 2.4Φ. Ví dụ với mô hình 7B, bộ nhớ cần thiết cho suy luận khoảng: 16.8 GB. Tính toán chính xác hơn có thể theo công thức đã đề cập.
Lưu ý⚠️: Trong quá trình suy luận, không cần lưu giá trị kích hoạt (activation value), nhiều blog nói rằng cần lưu giá trị kích hoạt là sai.
Huấn luyện
Hiện nay, mọi người thường sử dụng phương pháp huấn luyện với độ chính xác hỗn hợp (mixed-precision training), do đó tất cả các phân tích đều dựa trên giả định này và áp dụng tối ưu hóa AdamW. Trong quá trình huấn luyện, lượng bộ nhớ GPU chiếm dụng gồm 4 phần: tham số mô hình, gradient, trạng thái tối ưu hóa và giá trị kích hoạt. Giả sử tham số mô hình là Φ.
-
Tham số mô hình: fp32 parameters + bf16 parameters = (4+2)Φ = 6Φ bytes.
-
Gradient có hai trường hợp:
- Trường hợp bật gradient accumulation: Cần giữ đồng thời fp32 và bf16 = 6Φ bytes.
- Trường hợp không bật gradient accumulation: Chỉ cần giữ bf16, chiếm dụng bộ nhớ là 2Φ bytes, nhưng trong quá trình truyền ngược (backpropagation) cần chuyển về fp32 tính toán, do đó đỉnh điểm vẫn cần 4Φ.
-
Trạng thái tối ưu hóa:
- Một momentum fp32 và hai momentum fp32, tổng cộng là (4+4)Φ = 8Φ bytes.
-
Giá trị kích hoạt (bf16): (34bsh + 5bs^2a)*l bytes.
Do đó, trong quá trình huấn luyện, lượng bộ nhớ cần thiết cho mỗi card GPU là: 20Φ + (34bsh + 5bs^2a)*l.
Giả sử sử dụng DeepSpeed để huấn luyện
Nếu sử dụng DeepSpeed, làm thế nào để tính toán lượng bộ nhớ GPU mỗi card cần?
-
ZeRO1, chia nhỏ tối ưu hóa:
- (Momentum cấp 1 + Momentum cấp 2 + bản sao tham số fp32) / số card sunvip.club + gradient + tham số bf16 + giá trị kích hoạt.
- Lưu ý: Tham số fp32 được lưu trong tối ưu hóa.
-
ZeRO2, chia nhỏ gradient:
- (Momentum cấp 1 + Momentum cấp 2 + bản sao tham số fp32 + gradient) / số card + tham số bf16 + giá trị kích hoạt.
-
ZeRO3, chia nhỏ tham số mô hình:
- (Momentum cấp 1 + Momentum cấp 2 + bản sao tham số fp32 + gradient + tham số bf16) / số card + giá trị kích hoạt.
Cụ thể có thể xem hình ảnh (Hình ảnh được giải thích theo Zero-offload với ước tính 16Φ, nhưng ZeRO-Infinity lại nói cần 20Φ, nhưng sự khác biệt không đáng kể):
Câu hỏi thường gặp (FAQ)
-
Câu hỏi 1 🤔: Ngoài KV cache và giá trị kích hoạt, tại sao lại có tranh cãi về việc liệu phần tham số mô hình chiếm dụng 16Φ hay 18Φ hay 20Φ? Vì sao lại như vậy?
- Cố gắng trả lời:
- Trong các tài liệu của NVIDIA và triển khai của DeepSpeed, họ đều dựa trên 20Φ, nghĩa là sẽ đồng thời tạo một bản sao fp32 của gradient để tránh vấn đề thiếu độ chính xác của gradient, do đó ước tính theo cách này không có vấn đề lớn (đề xuất sử dụng cách này để ước tính).
- Vậy tại sao lại có người nói là 18Φ? Vì trong quá trình lan truyền xuôi và ngược, gradient thực tế là bf16, nhưng khi cập nhật tham số mô hình, cần chuyển gradient từ bf16 sang fp32, lúc này gradient đạt đỉnh điểm sẽ cần 4Φ, do đó tổng cộng là 18Φ.
- Còn ai nói là 16Φ thì sao? Rõ ràng là chưa tính đến điều trên, dù nhiều hình vẽ và tài liệu không nhắc tới việc cần tạo một bản sao fp32 của gradient, nhưng thực tế mã nguồn chứng minh rằng điều này là cần thiết, kể cả khi không bật gradient accumulation, vẫn cần 18Φ.
- Cố gắng trả lời:
-
Câu hỏi 2 🤔: Nếu huấn luyện với độ chính xác hỗn hợp, cần đồng thời giữ bản sao bf16 và fp32 của tham số, khiến bộ nhớ tham số chiếm dụng lên tới 20Φ, tại sao lại nói rằng huấn luyện với độ chính xác hỗn hợp tiết kiệm bộ nhớ?
- Cố gắng trả lời: Nếu huấn luyện với độ chính xác đơn (fp32) cùng tối ưu hóa AdamW, bộ nhớ tham số chiếm dụng sẽ là (4+4+4+4)Φ = 16Φ, nhưng một phần lớn khác chiếm dụng bộ nhớ GPU là giá trị kích hoạt, khi chuyển đổi giá trị kích hoạt từ fp32 sang bf16, có thể tiết kiệm được một lượng lớn bộ nhớ. Hơn nữa, huấn luyện với độ chính xác hỗn hợp nhanh hơn trong quá trình lan truyền xuôi và ngược.
-
Câu hỏi 3 🤔: Mối quan hệ giữa bf16 và fp16 là gì?
- fp16 có độ chính xác cao hơn vì có nhiều bit phần thập phân hơn.
- bf16 duy trì độ chính xác tương đối (< fp16) nhưng cung cấp phạm vi số lớn hơn.
-
Câu hỏi 4 🤔: Lợi ích của bf16 và fp16 là gì?
- Tiết kiệm băng thông.
- Tiết kiệm bộ nhớ.
-
Câu hỏi 5 🤔: Mối quan hệ giữa số lượng tham số mô hình và kích thước lưu trữ?
- Thông thường, khi nói về kích thước mô hình, chúng ta đang đề cập đến số lượng tham số. Đây thường là chỉ số tham số bên trong mô hình.
- Tuy nhiên, cũng có lúc người ta nói đến kích thước mô hình khi nó được lưu trữ trên đĩa cứng.
- Quan hệ chuyển đổi rất đơn giản:
- Mô hình đơn độ chính xác: 1B tham số mô hình = 1e9 * 4 = 4GB
- Mô hình bán độ chính xác: 1B tham số mô hình = 1e9 * 2 = 2GB; nếu là mô hình 0.5B tham số = 0.5e9 * 2 = 1GB
- Ví dụ với Qwen/Qwen2-0.5B-Instruct, khi lưu trữ dưới dạng bf16 = 2 bytes, kích thước mô hình sẽ là 998 MB ≈ 1GB.
Kết bạn nào 🤣
Cuối cùng, mời bạn theo dõi tôi, tên trên hầu hết các nền tảng mạng xã hội đều giống nhau: chaofa.
- Facebook: chaofa
- YouTube: chaofa
- Notion: Trang giới thiệu của chaofa