Mixed Precision Training Là Gì?

Mixed Precision Training là kỹ thuật huấn luyện mô hình AI kết hợp hai mức độ chính xác (precision) khác nhau trong cùng một quá trình, thường là FP16 (16-bit) và FP32 (32-bit). Mục đích chính là giảm bộ nhớ và tăng tốc độ训练 mà không làm giảm chất lượng mô hình.
Hiểu đơn giản, thay vì lưu mọi con số với 32 chữ số thập phân (FP32), bạn dùng 16 chữ số (FP16) cho phần lớn tính toán, và chỉ giữ 32 chữ số cho những chỗ cần độ chính xác cao. Kết quả: train nhanh hơn, tốn ít VRAM hơn, mà model vẫn thông minh như cũ.
Tại Sao Cần Mixed Precision Training?
Khi huấn luyện các mô hình ngôn ngữ lớn như GPT hay Llama, bộ nhớ GPU (VRAM) là tài nguyên cực kỳ đắt đỏ. Một model hàng chục tỷ parameter có thể ăn sạch 80GB VRAM của một con A100 nếu dùng toàn FP32.
Mỗi số FP32 chiếm 4 byte bộ nhớ, còn FP16 chỉ cần 2 byte. Nghĩa là chuyển sang FP16, bạn tiết kiệm được ngay một nửa bộ nhớ cho weights và activations. Nhưng nếu chuyển toàn bộ sang FP16, model sẽ bị mất thông tin quan trọng và gradient có thể bị “underflow” (số quá nhỏ, bị làm tròn về 0).
Đó là lý do “mixed” ra đời: dùng FP16 cho phần lớn tính toán, nhưng giữ FP32 ở những điểm tới hạn để đảm bảo độ chính xác.
Mixed Precision Training Hoạt Động Như Thế Nào?
Quá trình này dựa trên ba kỹ thuật cốt lõi, phối hợp với nhau để vừa nhanh vừa chính xác.
1. FP16 Master Weight Copy
Hệ thống giữ một bản sao weights ở FP32 (master copy) lưu riêng. Trong suốt quá trình training, forward pass và backward pass dùng weights FP16 để tính toán nhanh. Khi cập nhật weights, gradient được cộng vào master copy FP32 để giữ độ chính xác.
Tưởng tượng như bạn tính nhẩm nhanh (FP16) cho hầu hết bài toán, nhưng ghi đáp án cuối cùng vào sổ sách cẩn thận (FP32) để không bị sai số tích lũy.
2. Loss Scaling
Gradient trong deep learning thường rất nhỏ, đôi khi nhỏ đến mức FP16 không thể biểu diễn được và bị làm tròn thành 0. Loss scaling giải quyết bằng cách nhân gradient với một hệ số lớn (ví dụ 1024) trước khi backward pass, rồi chia lại trước khi cập nhật weights.
Cách này “đẩy” gradient ra khỏi vùng nguy hiểm của FP16, đảm bảo không mất thông tin quan trọng.
3. Chọn Precision Thích Hợp Cho Từng Phép Toán
Không phải phép toán nào cũng cần độ chính xác giống nhau. Phép nhân ma trận lớn (matrix multiplication) chạy rất nhanh trên FP16 và kết quả chấp nhận được. Nhưng phép cộng tích lũy (accumulation) thì cần FP32 để tránh sai số tích lũy theo thời gian.
GPU hiện đại như A100 hay H100 có sẵn Tensor Core hỗ trợ tự động việc này: tính nhân ở FP16, cộng tích lũy ở FP32, tất cả trong cùng một clock cycle.
Lợi Ích Thực Tế Của Mixed Precision Training
Mình đã thử huấn luyện model với và không với mixed precision trên cùng con GPU, và sự khác biệt rất rõ ràng.
Tốc độ tăng 1.5x đến 3x: Tensor Core trên GPU Nvidia V100, A100, H100 được thiết kế tối ưu cho FP16. Khi bật mixed precision, các phép matrix multiplication chạy nhanh hơn đáng kể.
Giảm 50% bộ nhớ: Weights và activations chỉ còn chiếm một nửa VRAM. Nghĩa là bạn có thể train model lớn hơn, hoặc dùng batch size lớn hơn trên cùng một GPU.
Tiết kiệm chi phí: Train nhanh hơn nghĩa là ít giờ GPU hơn, tức là ít tiền thuê cloud hơn. Với một job train kéo dài vài ngày trên cluster GPU, tiết kiệm 2x thời gian là rất nhiều tiền.
Nhược Điểm Và Hạn Chế
Mixed precision không phải đũa thần. Có một số trường hợp bạn cần cẩn thận.
Một số thao tác không tương thích FP16: Các phép toán như softmax, layer normalization, hoặc reduction đôi khi bị mất chính xác nếu chạy FP16. Framework như PyTorch tự động xử lý bằng cách giữ những phép này ở FP32, nhưng bạn cần đảm bảo cấu hình đúng.
Sai số tích lũy trong training dài: Dù có master copy FP32, sau hàng chục ngàn step, sai số nhỏ có thể tích lũy. Cần monitor loss curve kỹ hơn so với training thuần FP32.
Phụ thuộc phần cứng: Mixed precision chỉ thực sự hiệu quả trên GPU có Tensor Core (V100 trở lên). Trên GPU cũ hơn như GTX 1080, bạn có thể không thấy cải thiện đáng kể nào.
Cách Bật Mixed Precision Trong PyTorch
Trong PyTorch, cách đơn giản nhất là dùng torch.cuda.amp.Autocast. Bạn chỉ cần bọc forward pass trong autocast() context manager:
from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()
for data, target in dataloader:
optimizer.zero_grad()
with autocast():
output = model(data)
loss = loss_fn(output, target)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()GradScaler tự động xử lý loss scaling, còn autocast tự chọn precision cho từng phép toán. Rất tiện, không cần can thiệp thủ công.
BF16: Bước Tiến Hơn FP16
Một định dạng mới đang phổ biến là BF16 (Bfloat16), được Google phát triển cho TPU. Khác với FP16 có range nhỏ, BF16 có dynamic range tương đương FP32 nhưng ít significant bits hơn.
Ưu điểm lớn nhất của BF16 là không cần loss scaling, vì range đủ rộng để gradient không bị underflow. A100, H100 và hầu hết GPU thế hệ mới đều hỗ trợ BF16. Nếu GPU của bạn có, hãy dùng BF16 thay vì FP16.
Khi Nào Nên Dùng Mixed Precision Training?
Theo kinh nghiệm của mình, bạn nên bật mixed precision trong hầu hết trường hợp, trừ khi đang debug hoặc cần kết quả chính xác tuyệt đối cho paper khoa học.
Nên dùng khi: train model lớn (>1 tỷ parameter), muốn tiết kiệm VRAM, cần train nhanh hơn, chạy trên GPU có Tensor Core.
Không nên dùng khi: prototype nhỏ để test idea, GPU cũ không hỗ trợ Tensor Core, hoặc cần reproduce kết quả chính xác 100%.
Kết Luận
Mixed Precision Training là kỹ thuật tiêu chuẩn trong deep learning hiện đại. Hầu hết framework và library đều hỗ trợ sẵn, bạn chỉ cần bật lên. Lợi ích lớn (nhanh hơn, tiết kiệm VRAM) vượt trội hơn nhiều so với rủi ro (sai số tích lũy). Nếu bạn đang train model mà chưa bật mixed precision, hãy thử ngay, biết đâu batch size tăng gấp đôi mà model vẫn train ngon.