Đầu tháng 8, giới công nghệ xôn xao vì một startup mới tròn một tuổi tên Infinity, do cựu nghiên cứu viên Google Brain Jeremy Nixon sáng lập, tuyên bố đội ngũ của họ dùng AI coding agent viết lại một phần mềm kiểu CUDA cho chip D-Matrix chỉ trong 10 giờ đồng hồ. Startup vừa gọi vốn 15 triệu đô la ở định giá 100 triệu đô la, và Nixon gọi đây là điểm bước ngoặt cho thấy con hào phần mềm hai thập kỷ của NVIDIA không còn bất khả xâm phạm. Không phải ai cũng đồng tình: CEO Futurum Group Daniel Newman phản bác rằng NVIDIA vừa đào con hào CUDA sâu thêm, ví nó sâu tới khoảng 2,4 mét. Nhưng cuộc tranh cãi về ai kiểm soát tầng phần mềm GPU khiến nhiều kỹ sư đặt ra một câu hỏi gốc rễ hơn: bên dưới lớp CUDA đó, điều gì thực sự khiến việc huấn luyện một mô hình AI nhanh hay chậm, và vì sao gần như mọi framework hiện đại đều mặc định bật một kỹ thuật gọi là mixed precision training.
Ba định dạng số, một bài toán đánh đổi
Mọi phép tính trong mạng nơ-ron đều là nhân cộng ma trận, và cách máy tính lưu mỗi con số quyết định tốc độ lẫn độ chính xác. FP32 dùng 32 bit, cho dải giá trị rộng và độ chi tiết cao, nhưng chiếm gấp đôi bộ nhớ và chạy chậm hơn trên phần cứng hiện đại. FP16 chỉ dùng 16 bit, giảm một nửa bộ nhớ và tăng tốc đáng kể, nhưng dải giá trị biểu diễn được rất hẹp, khoảng từ 0,00006 đến 65.504, nên dễ tràn số khi giá trị quá lớn hoặc quá nhỏ. BF16 ra đời để dung hòa: vẫn 16 bit nhưng phần mũ giữ nguyên độ rộng như FP32, đánh đổi lấy độ chính xác thấp hơn ở phần thập phân. Vì vậy BF16 thường không cần các thủ thuật chống tràn số phức tạp như FP16, còn FP16 lại có độ chi tiết cao hơn ở vùng giá trị nhỏ, mỗi loại phù hợp với một kiểu mô hình khác nhau.
Loss scaling: cứu những gradient sắp biến mất
Vấn đề lớn nhất của FP16 nằm ở pha lan truyền ngược. Nhiều gradient trong quá trình huấn luyện có giá trị cực nhỏ, cỡ một phần mười triệu, và khi ép vào khuôn FP16, chúng bị làm tròn thẳng xuống số không, hiện tượng gọi là gradient underflow. Một khi gradient bằng không, trọng số tương ứng ngừng học hoàn toàn dù mô hình vẫn đang chạy bình thường, không báo lỗi. Giải pháp là loss scaling: nhân giá trị loss với một hằng số lớn, thường khởi điểm là hai lũy thừa mười sáu, trước khi lan truyền ngược, đẩy toàn bộ gradient lên vùng giá trị mà FP16 biểu diễn được, rồi chia ngược lại đúng tỷ lệ đó trước khi cập nhật trọng số. Kỹ thuật dynamic loss scaling còn tự động tăng giảm hệ số này theo thời gian thực, nếu phát hiện tràn số thì giảm hệ số và bỏ qua bước cập nhật đó, còn nếu huấn luyện ổn định lâu thì tăng dần hệ số để tận dụng tối đa độ chính xác.
Bản sao trọng số chủ và vai trò của Tensor Core
Ngay cả khi gradient đã được bảo toàn, việc cộng dồn hàng triệu bước cập nhật cực nhỏ vào trọng số FP16 vẫn gây mất mát vì bước nhảy tối thiểu của FP16 quá thô. Vì vậy các framework luôn giữ một bản sao trọng số chủ ở FP32, gọi là master weight copy: mọi phép cộng gradient được thực hiện trên bản sao FP32 này, sau đó mới ép về FP16 để dùng cho lượt tính toán tiếp theo. Đây chính là ý nghĩa của từ "mixed": tính toán ở FP16 hoặc BF16 để tận dụng tốc độ, nhưng lưu trữ trạng thái quan trọng nhất ở FP32 để giữ độ chính xác. Toàn bộ cơ chế này chỉ có lợi thực sự khi phần cứng hỗ trợ, cụ thể là Tensor Core, đơn vị tính toán chuyên biệt có mặt trên mọi GPU NVIDIA từ kiến trúc Volta trở đi, cho phép nhân ma trận ở độ chính xác thấp nhanh hơn từ hai đến bốn lần so với FP32 thuần túy. Nói cách khác, dù ai đó viết lại được một lớp phần mềm giống CUDA trong mười giờ, phần cứng và các thuật toán số học tinh vi như loss scaling hay master weight vẫn là lớp kiến thức mà bất cứ đối thủ nào của công nghệ NVIDIA cũng phải tái tạo cho bằng được mới có thể cạnh tranh sòng phẳng.






