FP4: Số dấu phẩy động 4-bit và vai trò quan trọng trong tối ưu hóa AI
Với sự phát triển của mạng nơ-ron, nhu cầu về dữ liệu có độ chính xác thấp hơn nhưng tiết kiệm bộ nhớ hơn ngày càng tăng, dẫn đến sự ra đời của các định dạng số dấu phẩy động 4-bit (FP4). Bài viết này sẽ phân tích cấu trúc, lợi ích của định dạng FP4, đặc biệt là biến thể E2M1 phổ biến trên phần cứng Nvidia, cũng như lý do tại sao nó lại quan trọng cho các mô hình trí tuệ nhân tạo hiện đại.

Trong quá khứ, các con số dấu phẩy động (floating point) thường được lưu trữ trong 32 bit, sau đó 64 bit trở thành tiêu chuẩn. Ngôn ngữ lập trình C vẫn giữ những thuật ngữ này: float cho số 32 bit và double cho số 64 bit. Python đơn giản hóa bằng cách dùng float để chỉ định dạng phổ biến nhất (tương đương double của C).
Các lập trình viên từng rất hài lòng khi chuyển từ 32 bit sang 64 bit vì độ chính xác cao hơn giúp giải quyết nhiều vấn đề tính toán. Tuy nhiên, sự bùng nổ của mạng nơ-ron (neural networks) đã mang lại một yêu cầu trái ngược: nhu cầu về các con số dấu phẩy động có độ chính xác thấp hơn.
Các mạng này có số lượng tham số khổng lồ, và việc chứa được nhiều tham số hơn vào bộ nhớ quan trọng hơn là việc có các tham số với độ chính xác quá cao. Thay vì độ chính xác kép (64 bit), các nhà phát triển muốn nửa độ chính xác (16 bit), hoặc thậm chí ít hơn như FP8 (8 bit) hay FP4 (4 bit). Bài viết này sẽ đi sâu vào cấu trúc của số dấu phẩy động 4-bit.
Tại sao lại dùng dấu phẩy động thay vì số nguyên?
Có thể bạn sẽ hỏi: Tại sao lại dùng dấu phẩy động khi không cần độ chính xác cao? Tại sao không dùng số nguyên? Ví dụ, với 4 bit, bạn có thể biểu diễn các số nguyên 0, 1, 2, ..., 15. Bạn cũng có thể thêm một độ lệch (bias) để biểu diễn số âm.
Lý do là dấu phẩy động cung cấp một phạm vi động (dynamic range) lớn hơn, rất cần thiết trong các phép tính của mạng nơ-ron khi giá trị có thể thay đổi rất mạnh về mức độ.
Cấu trúc của FP4
Đối với số dấu phẩy động 4-bit có dấu (signed FP4), bit đầu tiên dùng để biểu diễn dấu. Câu hỏi đặt ra là làm gì với 3 bit còn lại. Ký hiệu ExMm biểu thị một định dạng với x bit mũ (exponent) và m bit trị (mantissa).
Với số 4-bit có dấu, tổng x + m = 3. Chúng ta có bốn khả năng: E3M0, E2M1, E1M2 và E0M3. Tất cả đều được sử dụng ở đâu đó, nhưng E2M1 là phổ biến nhất và được hỗ trợ bởi phần cứng của Nvidia.
Một số có bit dấu s, mũ e và phần trị m sẽ có giá trị:
$$ (-1)^s 2^{e-b} (1 + m/2) $$
Trong đó, b là độ lệch (bias). Mục đích của bias là cho phép các số mũ dương và âm mà không cần dùng số có dấu cho e.
Định dạng E3M0 là toàn mũ, không có phần trị, nên các giá trị khả dụng của nó phân bố đều trên thang logarit. Ngược lại, E0M3 là toàn phần trị, phân bố đều trên thang tuyến tính. E1M2 và E2M1 thì phân bố không đều trên cả hai thang.
Có một ngoại lệ cho công thức trên khi e = 0. Trong trường hợp đó, m = 0 biểu thị số 0 và m = 1 biểu thị số ½.
Bảng giá trị định dạng E2M1
Vì chỉ có 16 số FP4 khả dụng, chúng ta có thể liệt kê tất cả. Dưới đây là bảng cho định dạng E2M1:
| Bits | s | exp | m | Value |
|---|---|---|---|---|
| 0000 | 0 | 00 | 0 | +0 |
| 0001 | 0 | 00 | 1 | +0.5 |
| 0010 | 0 | 01 | 0 | +1 |
| 0011 | 0 | 01 | 1 | +1.5 |
| 0100 | 0 | 10 | 0 | +2 |
| 0101 | 0 | 10 | 1 | +3 |
| 0110 | 0 | 11 | 0 | +4 |
| 0111 | 0 | 11 | 1 | +6 |
| 1000 | 1 | 00 | 0 | -0 |
| 1001 | 1 | 00 | 1 | -0.5 |
| 1010 | 1 | 01 | 0 | -1 |
| 1011 | 1 | 01 | 1 | -1.5 |
| 1100 | 1 | 10 | 0 | -2 |
| 1101 | 1 | 10 | 1 | -3 |
| 1110 | 1 | 11 | 0 | -4 |
| 1111 | 1 | 11 | 1 | -6 |
Ngay cả trong định dạng nhỏ xíu này, vẫn tồn tại hai số 0: +0 và -0, giống như các định dạng dấu phẩy động full precision.
Mô phỏng với thư viện Pychop
Thư viện Python Pychop có thể mô phỏng nhiều định dạng dấu phẩy động giảm độ chính xác khác nhau. Đoạn mã dưới đây minh họa cách lấy metadata cho định dạng mxfp4_e2m1 và tạo bảng giá trị như trên:
import pychop
# Lấy metadata định dạng từ Pychop
spec = pychop.MX_FORMATS["mxfp4_e2m1"]
assert (spec.exp_bits, spec.sig_bits) == (2, 1)
def e2m1_value(s: int, e: int, m: int) -> float:
sign = -1.0 if s else 1.0
# Subnormal / zero
if e == 0:
return sign * (m / 2.0)
# Normal
return sign * (2.0 ** (e - 1)) * (1.0 + m / 2.0)
# (Phần mã hiển thị bảng được giản lược cho gọn)
Các định dạng khác
FP4 không phải là định dạng duy nhất. Số lượng định dạng đang được sử dụng thực tế khá nhiều. Một định dạng đáng chú ý khác là NF4, trong đó các số có thể biểu diễn khớp tốt hơn với phân bố của các trọng số (weights) trong các Mô hình Ngôn ngữ Lớn (LLM). Đây sẽ là nội dung được bàn kỹ hơn trong các bài viết tiếp theo.
Bài viết liên quan

Công nghệ
Tesla khuyên chủ xe HW3 "hãy kiên nhẫn" sau 7 năm chờ đợi FSD, khơi mào làn sóng kiện tụng tại Châu Âu
17 tháng 4, 2026

Phần mềm
Ra mắt Rail: Ngôn ngữ lập trình tự hosting tích hợp HTTPS thuần túy
18 tháng 4, 2026

Phần cứng
Startup sản xuất chip AI Cerebras Systems chính thức nộp đơn lên sàn chứng khoán
18 tháng 4, 2026
