GPU cho dự án của bạn · thanh toán crypto không cần KYC Cách thuê
Tiếng Việt
Mở console
Hướng dẫn thực hành / KERNODECK

Chuyển sang độ chính xác hỗn hợp mà không mất kiểm soát số học

Hãy thiết lập một đường cơ sở ở độ chính xác thông thường, bật autocast cho phần tính toán phía trước và hàm mất mát, rồi so sánh đầu ra, gradient và chất lượng trên cùng các đầu vào. Khi huấn luyện FP16, GradScaler giúp xử lý các gradient có biên độ nhỏ; nó không làm cho mọi mô hình trở nên tương thích. BF16 có hành vi số học khác. Hãy giữ một tiêu chí quay lui rõ ràng trước khi tìm kiếm lợi ích về bộ nhớ hay tốc độ.

10 phút đọc · Hướng dẫn cho nhà phát triển

Bắt đầu bằng một đường cơ sở đáp ứng nhu cầu

Hãy chọn một tập ngắn gồm các đầu vào thông thường, các trường hợp biên và các ranh giới quyết định. Cố định mô hình, trọng số, tiền xử lý và chế độ train hay eval. So sánh giữa hai mô hình hay hai batch không cho phép quy sự khác biệt của chúng cho độ chính xác.

Hãy lưu lại đầu ra hữu ích cho ứng dụng của bạn, không chỉ hàm mất mát. Với bộ phân loại, điều đó có thể gồm điểm số và quyết định; với bài toán hồi quy, gồm sai số và các giá trị cực trị. Trước tiên hãy kiểm tra sự hiện diện của NaN hoặc inf trong đường cơ sở. Một lần chạy FP32 sai không trở thành cơ sở đáng tin chỉ vì nó có nhiều bit hơn.

Hãy đặt ngưỡng dung sai, chất lượng tối thiểu và yêu cầu không có giá trị không hữu hạn trước khi thử nghiệm. PyTorch nhắc rằng tính toán dấu phẩy động không đảm bảo kết quả giống hệt nhau giữa các thiết bị hay đường thực thi.

Phân biệt autocast, định dạng số và GradScaler

autocast chọn kiểu của một số phép toán tùy theo chính sách tính toán của chúng. Nó không chuyển toàn bộ chương trình sang một định dạng duy nhất. Với cách dùng này, hãy tránh chuyển đổi thủ công toàn bộ mô hình bằng half(). Tài liệu hiện hành khuyến nghị torch.autocast hoặc torch.amp.autocast; các giao diện cũ torch.cuda.amp đã bị ngừng hỗ trợ.

GradScaler tác động lên thang của loss và gradient trong quá trình huấn luyện. Nó không được dùng như một công cụ tăng tốc suy luận, vì suy luận không thực hiện backward. FP16 có dải số hạn chế hơn BF16; một mô hình được thiết kế cho BF16 có thể tràn khi dùng FP16. Do đó, việc thang giảm liên tục không chứng minh rằng vấn đề đã được giải quyết.

Hãy chọn định dạng dựa trên các ràng buộc của mô hình và những phép toán thực sự được dùng, rồi kiểm tra khả năng hỗ trợ của mục tiêu. Tên thương mại của một card hay sở thích chuẩn bị PyTorch không chứng minh rằng toán tử tùy chỉnh của bạn có nhân mong muốn.

Cuộn bảng để xem tất cả các cột.
Các quyết định về độ chính xác cần xác nhận trên dự án
Lựa chọnVai tròKiểm tra cần thiết
Tham chiếu FP32Điểm so sánh của dự ánĐầu ra hữu hạn và chất lượng mong đợi
Autocast FP16Một số phép toán ở độ chính xác rút gọnDải số và gradient
Autocast BF16Cân nhắc khác giữa dải và độ chính xácCác toán tử khả dụng và chất lượng
GradScalerQuản lý thang gradientCác cập nhật thực sự được thực hiện

Đặt các bước huấn luyện đúng thứ tự

Đoạn mã đề xuất giả định mô hình và optimizer đã được dựng sẵn, đầu vào và mục tiêu nằm trên cùng một GPU, và loss là scalar. Nó chưa được chạy và không phải là sự xác nhận cho một dịch vụ nào. Ngữ cảnh autocast bao quanh forward và loss; backward diễn ra sau khi ngữ cảnh đóng lại. Scaler được tạo một lần cho phiên huấn luyện, không phải cho từng batch.

Để kiểm tra hoặc cắt gradient, trước tiên hãy gỡ hệ số thang của chúng bằng unscale_. Các ví dụ AMP chính thức nêu rõ chỉ làm việc này một lần cho mỗi optimizer và sau khi đã tích lũy các gradient dành cho việc cập nhật của nó. Ngưỡng cắt 1.0 dưới đây là giá trị minh họa cần chọn cho dự án của bạn, không phải khuyến nghị phổ quát.

Các guard ở đây dừng việc chẩn đoán nếu loss, gradient hay norm tổng không hữu hạn. Những lần đọc trên CPU này gây ảnh hưởng: đừng đo thời gian đoạn mã này. Việc tích lũy, nhiều optimizer và scheduler đòi hỏi định nghĩa riêng cho bước cập nhật.

Chuỗi AMP minh họa trên GPU, chưa được chạy
import torch

# Điều kiện tiên quyết: model, optimizer, loss_fn, inputs và targets đã tồn tại.
# Mô hình và đầu vào nằm trên cùng thiết bị CUDA/HIP.
dtype = torch.float16  # Lựa chọn cần xác nhận; BF16 là một thử nghiệm khác.
scaler = torch.amp.GradScaler("cuda", enabled=(dtype == torch.float16))

# Đặt trong vòng lặp của bạn, giữ scaler qua các batch.
optimizer.zero_grad(set_to_none=True)
with torch.autocast(device_type="cuda", dtype=dtype):
    prediction = model(inputs)
    loss = loss_fn(prediction, targets)
if not bool(torch.isfinite(loss).item()):
    raise FloatingPointError("Loss không hữu hạn: dừng chẩn đoán")
scaler.scale(loss).backward()
scaler.unscale_(optimizer)
if any(p.grad is not None and
       not bool(torch.isfinite(p.grad).all().item())
       for p in model.parameters()):
    raise FloatingPointError("Gradient không hữu hạn: dừng chẩn đoán")
torch.nn.utils.clip_grad_norm_(
    model.parameters(), max_norm=1.0, error_if_nonfinite=True,
)
scaler.step(optimizer)
scaler.update()

Ví dụ minh họa: hai quyết định gần nhau không thể thay thế cho nhau

Giả sử một dịch vụ chọn lớp có điểm cao nhất. Trên một đầu vào minh họa, tham chiếu tạo ra hai điểm rất gần nhau: 1,0000 và 1,0003. Một đường tính toán số khác có thể thay đổi thứ tự của chúng hoặc tạo ra thế hòa. Những con số này minh họa một ranh giới quyết định; chúng không phải là đầu ra đo được của FP16 hay BF16.

Việc kiểm tra đúng đắn gồm hai mức. Hãy so sánh các điểm với dung sai rõ ràng, rồi so sánh quyết định và quy tắc áp dụng cho các trường hợp hòa. Một khác biệt nhỏ về giá trị tuyệt đối có thể thay đổi hành động được chọn. Ngược lại, một khác biệt số nhìn thấy được có thể không gây hậu quả cho một tác vụ có ngưỡng nằm xa các điểm quan sát được.

Ghi lại số liệu nhận dạng, kết quả tham chiếu, thử nghiệm AMP và tác động lên quyết định. Đặt quy tắc chấp nhận trước khi đọc kết quả. Đừng nới rộng dung sai để làm biến mất một trường hợp khó chịu; các kết quả ở thang đo khác nhau có thể cần tiêu chí riêng.

Cuộn bảng để xem tất cả các cột.
Bảng so sánh mang tính hướng dẫn, cần bổ sung bằng số đo
Tiêu chíMã tham chiếuThử nghiệm AMPQuyết định
Kết quả hoàn chỉnhCần kiểm traCần kiểm traTừ chối các kết quả chưa hoàn chỉnh không rõ nguyên nhân
Sai lệch số họcGiá trị được giữ lạiSai lệch cần tínhDung sai định trước khi thử
Quyết định ứng dụngLớp hoặc hành độngLớp hoặc hành độngXem xét các thay đổi
Chất lượng trên bộ dữ liệu cố địnhCần đoCần đoTuân thủ ngưỡng của dự án

Diễn giải NaN và các cập nhật bị bỏ qua

Khi xuất hiện các giá trị không hữu hạn, hãy tìm bước đầu tiên tạo ra chúng: đầu vào, đầu ra trung gian, loss hay gradient. Chạy lại cùng trường hợp ở chế độ tham chiếu, rồi tạm tắt autocast cục bộ quanh phép toán nghi ngờ, đồng thời kiểm tra cả kiểu dữ liệu của đầu vào. Chuyển toàn bộ quá trình huấn luyện về FP32 có thể dùng để so sánh, nhưng không tự động khoanh vùng được vấn đề.

Scaler có thể bỏ qua một cập nhật khi gradient chứa inf hoặc NaN. Vì vậy, một vòng lặp tiếp tục chạy không nhất thiết đã thực hiện số cập nhật bằng số vòng lặp. Hãy ghi lại hành vi này trong quá trình chẩn đoán. Đừng mù quáng cho rằng một chính sách học tập tiến triển theo số cập nhật thực tế.

Loss hữu hạn không đảm bảo gradient hữu hạn. Ngược lại, một sự cố đơn lẻ không đủ để kết luận quá trình huấn luyện không dùng được: hãy xem xét tần suất, tiến độ và chất lượng. Công thức AMP cung cấp phương pháp để tách riêng autocast và scaling khi một trong hai bị nghi ngờ.

Chuẩn bị khả năng quay lui có thể tái lập

Trước khi thử, hãy giữ lại cấu hình tham chiếu, trọng số, trạng thái optimizer và một checkpoint nhất quán. Nếu quá trình huấn luyện của bạn dùng scaler, trạng thái của nó cũng là một phần của việc khôi phục. Ghi lại dtype và các vùng có thể vẫn ở FP32. Khôi phục với một chính sách khác là một thay đổi thử nghiệm cần được nhận diện, chứ không phải là sự tiếp nối tương đương ngầm định.

Hãy quay lại cấu hình trước đó nếu kết quả trở nên không hữu hạn, nếu chất lượng vượt ra ngoài tiêu chí đã đặt hoặc nếu các cập nhật ngừng tiến triển ở mức có thể khai thác. Giữ lại trường hợp đã dẫn đến việc quay lui này. Sau một thay đổi, hãy bắt đầu lại so sánh trên cùng bộ dữ liệu trước khi kéo dài thời gian.

Bài tập Kernodeck về checkpoint kiểm tra việc khôi phục trên CPU không có AMP. Hãy tái sử dụng phương pháp so sánh của bài đó, bổ sung các trạng thái mà vòng lặp của bạn thực sự tiêu thụ.

Chỉ đo lợi ích sau khi đã kiểm chứng số học

Sau khi kiểm chứng, hãy đo bộ nhớ và thời gian mà không bật chẩn đoán chi tiết. Giữ nguyên hình dạng, batch, mô hình và chất lượng. Việc đọc scalar, đồng bộ và profiler có thể làm thay đổi thời lượng; hãy loại bỏ các kiểm tra xâm nhập khỏi phép đo cuối cùng.

Trên ROCm, tên thiết bị của PyTorch vẫn là cuda và các giao diện tương ứng được tái sử dụng. Điều này không đảm bảo cùng kernel hay kết quả giống hệt NVIDIA. Hãy kiểm tra backend và các toán tử của dự án trên mục tiêu. Hướng dẫn này không công bố bất kỳ mức giảm bộ nhớ cố định, hệ số tăng tốc hay khả năng tương thích chuẩn bị Kernodeck nào.

Câu hỏi của bạn

AMP có nghĩa là mọi tensor đều chuyển sang FP16 phải không?

Không. autocast áp dụng chính sách theo từng phép toán. Một số phép toán vẫn giữ ở độ chính xác khác. Chuyển thủ công toàn bộ mô hình sang half() không tương đương với dùng autocast và có thể làm thay đổi các điều kiện ổn định.

BF16 có luôn thay thế FP16 một cách có lợi không?

Không. Hai định dạng có những đánh đổi khác nhau, và mức hỗ trợ của chúng phụ thuộc vào phép toán và môi trường. Hãy so sánh chất lượng và chi phí trên khối lượng công việc của bạn; dải giá trị rộng hơn của BF16 tự nó không đảm bảo độ chính xác cần thiết.

GradScaler có cần thiết cho suy luận không?

Scaler chỉ tham gia vào quá trình huấn luyện có gradient, không tham gia vào suy luận không có backward. Với suy luận, thay vào đó hãy kiểm tra kết quả và chất lượng dưới autocast, đồng thời giữ nguyên chế độ đánh giá mong đợi.

Loss hữu hạn có đủ để chấp nhận AMP không?

Không. Hãy kiểm tra cả gradient, các cập nhật, chất lượng và các quyết định của ứng dụng. Một khác biệt số nhỏ có thể mang tính quyết định gần một ngưỡng; một quá trình huấn luyện vẫn tiếp tục cũng có thể bỏ qua một số cập nhật.