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

Profiler một bước PyTorch để biết thời gian trôi qua ở đâu

Trước tiên hãy xác định bước cần quan sát, tách riêng việc tải, truyền, tính toán và cập nhật, rồi ghi lại một cửa sổ ngắn mang tính đại diện bằng torch.profiler. Hãy đọc đồng thời dòng thời gian CPU và các hoạt động GPU sẵn có. Thời gian khởi chạy Python không phải là thời gian thực thi hoàn tất trên bộ tăng tốc, và một trace có thiết bị đo tự nó không tạo thành một benchmark.

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

Chọn một câu hỏi trước khi mở một trace

Một trace trả lời tốt hơn cho một câu hỏi cụ thể: liệu phép tính có đang chờ dữ liệu, một bản sao có bị lặp lại, hay một toán tử nhỏ có bị gọi quá thường xuyên? Hãy xác định đầu vào, đầu ra và các ranh giới của bước của bạn. Với huấn luyện, hãy nêu rõ bước đó có chứa lan truyền ngược, cập nhật bộ tối ưu và đọc batch hay không. Với suy luận, hãy tách riêng việc tải mô hình và truy vấn.

Hãy giữ một kịch bản ngắn mà bạn biết rõ tính đúng đắn. Ghi lại hình dạng, batch, độ chính xác, chế độ mô hình, khả năng biên dịch và nguồn dữ liệu. Một đầu vào được đơn giản hóa có thể giúp cô lập một hành vi, nhưng nó không còn nhất thiết đại diện cho toàn bộ tải. Hãy nêu rõ khác biệt này trong báo cáo.

Hãy cố định đơn vị cuối cùng: mili giây mỗi bước hoặc số ví dụ xử lý được mỗi giây. Tổng các sự kiện không thay thế cho thời gian trôi qua. Hãy so sánh các cửa sổ có cùng ranh giới đọc và truyền.

Phân biệt thời gian CPU, công việc GPU và thời gian chờ

CPU chuẩn bị và khởi chạy các phép toán; GPU có thể thực thi chúng sau đó. Vì vậy một khoảng Python có thể chứa thời gian khởi chạy, thời gian chờ, hoặc cả hai. Tài liệu CUDA của PyTorch chỉ ra rằng các phép đo chính xác phải tính đến tính bất đồng bộ này, đặc biệt bằng đồng bộ hóa hoặc các sự kiện phù hợp với phạm vi đo.

Đối với một phép đo thời lượng GPU có mục tiêu, các sự kiện CUDA có thể phù hợp. Đối với độ trễ từ đầu đến cuối, hãy chờ công việc nằm trong độ trễ đó kết thúc và đo toàn bộ yêu cầu. Đừng trộn lẫn hai đơn vị này. Một đồng bộ hóa được thêm vào giữa mỗi phép toán có thể loại bỏ sự chồng lấn thực sự và biến đổi chương trình mà bạn đang cố tìm hiểu.

Trong profiler, thời gian riêng của một toán tử và thời gian bao gồm các toán tử con cũng trả lời những câu hỏi khác nhau. Hãy xem dòng thời gian trước khi cộng các dòng trong bảng. Các hoạt động đồng thời hoặc lồng nhau không đại diện cho những phần thời gian trôi qua tách rời nhau.

Dành riêng một giai đoạn khởi động và một cửa sổ hoạt động

Lần chạy đầu tiên có thể bao gồm khởi tạo, tải hoặc biên dịch. Hãy quyết định xem câu hỏi của bạn liên quan đến giai đoạn khởi động này hay đến một giai đoạn đã ổn định. Hãy giữ lại cả hai quan sát khi chúng quan trọng đối với việc sử dụng, thay vì xóa đi chi phí ban đầu bằng một giá trị trung bình được trình bày như thể là tổng thể.

Hàm schedule cho phép phân biệt thời gian chờ, thời gian chuẩn bị thu thập và cửa sổ hoạt động. Việc khởi động profiler không phải là bằng chứng rằng mô hình của bạn đã đạt trạng thái ổn định. Hãy kiểm tra cả các hình dạng gặp phải và trạng thái của các bộ nhớ đệm. Một ứng dụng có đầu vào thay đổi có thể gặp những đường đi mới sau nhiều lần lặp.

Lịch trình mang tính minh họa được đề xuất bên dưới chờ một bước, chuẩn bị một bước và ghi lại hai bước. Bốn bước đủ để giải thích cơ chế, nhưng không đủ để thiết lập một phân bố hiệu năng. Trong một chiến dịch thực sự, hãy chọn một cửa sổ có lý do chính đáng và lặp lại phép đo bên ngoài profiler sau khi phân tích.

Ví dụ đề xuất: bốn bước với các ranh giới dễ đọc

Đoạn mã sau đây chưa được thực thi. Nó giả định rằng model, optimizer, loss_fn, loader và device đều tồn tại, rằng mô hình nằm trên device và loader cung cấp ít nhất bốn batch gồm các cặp x, y. Nó thực hiện các cập nhật: hãy dùng một trạng thái thử nghiệm được dành cho việc này, chứ không phải một phiên mà bạn cần giữ nguyên các trọng số.

Các nhãn phân tách việc đọc CPU, truyền dữ liệu và huấn luyện. Iterator được tạo trước cửa sổ, điều này loại trừ một phần thời gian khởi động của nó khỏi phạm vi đo. Tệp được chọn mới để tránh ghi đè lên một vết cũ. Ví dụ từ chối thu thập GPU khi không khả dụng thay vì âm thầm trình bày một vết CPU như một phân tích GPU.

Tín hiệu step() đẩy tiến trình lập lịch sau mỗi bước. Công thức chính thức mô tả mối liên hệ này giữa các vòng lặp và việc thu thập. Trên một hệ ROCm, thiết bị PyTorch vẫn được đặt tên là cuda; tuy nhiên khả năng thu thập trên bộ tăng tốc phụ thuộc vào bản build và các công cụ của nó. Hãy kiểm tra những hoạt động thực sự có trong kết quả.

Ghi lại mang tính minh họa một cửa sổ ngắn, không được thực thi
from pathlib import Path
import torch
from torch.profiler import (
    profile, schedule, record_function,
    ProfilerActivity, supported_activities,
)

trace = Path("trace-etape.json")
if trace.exists():
    raise FileExistsError("Chọn một tên vết mới")
activities = [ProfilerActivity.CPU]
if device.type == "cuda":
    if ProfilerActivity.CUDA not in supported_activities():
        raise RuntimeError("Thu thập GPU không khả dụng trong bản build này")
    activities.append(ProfilerActivity.CUDA)
iterator = iter(loader)
model.train()

with profile(
    activities=activities,
    schedule=schedule(wait=1, warmup=1, active=2, repeat=1),
    record_shapes=False, profile_memory=False, with_stack=False,
    on_trace_ready=lambda p: p.export_chrome_trace(str(trace)),
) as prof:
    for _ in range(4):
        with record_function("lecture_batch_cpu"):
            x, y = next(iterator)
        with record_function("transfert"):
            x, y = x.to(device), y.to(device)
        with record_function("entrainement"):
            optimizer.zero_grad(set_to_none=True)
            loss = loss_fn(model(x), y)
            loss.backward()
            optimizer.step()
        prof.step()
print(prof.key_averages().table(
    sort_by="self_cpu_time_total", row_limit=8,
))

Biến một quan sát thành giả thuyết có thể kiểm chứng

Hãy bắt đầu với cửa sổ đang hoạt động và kiểm tra xem các nhãn mong đợi có xuất hiện không. Sau đó xem xét các khoảng trống giữa các hoạt động, các bản sao chép và các lần lặp lại. Một khoảng chờ dài trong lecture_batch_cpu hướng đến pipeline đầu vào; nó không đo trực tiếp lưu trữ. Việc sao chép thường xuyên gợi ý nên xem xét vị trí đặt các tensor, nhưng không chứng minh rằng nó là vô ích.

Hãy đưa ra một giả thuyết duy nhất rồi đề xuất một thay đổi có kiểm soát. Ví dụ, nếu một hằng số được tạo lại và truyền đi ở mỗi bước, hãy kiểm tra xem vòng đời của nó có thể bao trùm nhiều bước mà không làm thay đổi kết quả hay không. Nếu một toán tử có vẻ chiếm ưu thế, hãy xem xét các hình dạng và số lần gọi của nó trước khi tìm một thứ thay thế.

Các dòng dưới đây là những cách đọc khả dĩ, không phải những kết luận rút ra từ một vết đã thực thi. Không có thời lượng hay mức tăng tốc nào được công bố. Kết luận hữu ích là một thử nghiệm tiếp theo có thể xác nhận hoặc bác bỏ nguyên nhân được đề xuất.

Cuộn bảng để xem tất cả các cột.
Các diễn giải mang tính minh họa cần kiểm chứng trong vết của chính bạn
Quan sát khả dĩGiả thuyếtKiểm tra tiếp theo
GPU không hoạt động trong khi đọcPipeline đầu vào không theo kịpCùng một phép tính với batch đã được chuẩn bị sẵn
Sao chép lặp lại một hằng sốVị trí hoặc vòng đời không phù hợpDi chuyển một lần, kiểm tra các đầu ra
Nhiều lần khởi chạy nhỏCông việc bị phân mảnhXem xét việc gộp nhóm và chi phí tổng thể
Một toán tử chạy lâuHình dạng hoặc thuật toán mang tính quyết địnhSo sánh cùng toán tử đó và các đầu vào của nó

Giới hạn chi phí và thông tin của việc ghi đo

Hãy bắt đầu với một lần thu thập ngắn và ít tùy chọn. Chỉ bật hình dạng, ngăn xếp hoặc bộ nhớ khi có một câu hỏi yêu cầu. API PyTorch nêu rõ rằng những thông tin này làm tăng chi phí; việc thu thập hình dạng thậm chí có thể giữ các tham chiếu đến tensor. Do đó, một hồ sơ chi tiết có thể làm thay đổi thời lượng hoặc mức sử dụng bộ nhớ của chương trình.

Một trace có thể chứa tên toán tử, các shape và, tùy theo tùy chọn, đường dẫn mã. Hãy kiểm tra nó trước khi chia sẻ. Nhãn vùng phải mô tả bước mà không kèm email, token, đường dẫn riêng tư hay nội dung đầu vào. Hãy chọn trình đọc trace phù hợp với môi trường của bạn và giữ quyền kiểm soát việc thu thập.

Nếu các sự kiện GPU mong đợi không xuất hiện, đừng điền thời gian của chúng bằng số không. Hãy nêu rõ chúng chưa được quan sát và xem xét khả năng hỗ trợ của việc thu thập. Việc công cụ không có sự kiện không phải là bằng chứng cho thấy không có tính toán.

Xác nhận tối ưu hóa ngoài profiler

Hãy bắt đầu lại từ cùng một trạng thái liên quan và so sánh tính đúng đắn trước và sau khi thay đổi. Với huấn luyện, một bước bổ sung sẽ thay đổi trọng số; hai lần ghi lại chạy liên tiếp không nhất thiết tạo thành một so sánh tương đương. Hãy giữ mã, tham số và điểm khởi đầu để có thể giải thích sự khác biệt.

Sau đó đo kịch bản mà không thu thập chi tiết, với cùng bước khởi động và nhiều lần chạy. Hãy báo cáo phạm vi, giá trị thô và độ phân tán của chúng. Một cải thiện cục bộ có thể biến mất trong toàn bộ vòng lặp hoặc làm giảm chất lượng: cả hai đều phải nằm trong quyết định.

Cuối cùng, hãy dùng các quan sát để xác định rõ tài nguyên thực sự cần thiết. Một trace trên máy của bạn không xếp hạng các gói Kernodeck và không chứng minh được CPU máy chủ hay mạng của một server đi thuê. So sánh GPU đòi hỏi tải, điều kiện và kết quả có thể so sánh trên các tài nguyên liên quan.

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

Thời gian CPU lớn nhất có chỉ ra toán tử GPU chậm nhất không?

Không. Nó có thể bao gồm khởi chạy, xử lý phía máy chủ hoặc chờ đợi. Hãy xem các sự kiện GPU và trình tự thời gian của chúng khi việc thu thập cung cấp chúng. Bảng sắp xếp theo thời gian CPU chỉ trả lời cho góc nhìn đó.

Tôi có nên cộng tất cả thời gian CUDA trong bảng không?

Không, nếu để tự động có được tổng thời lượng. Các hoạt động có thể chồng lấn và các sự kiện có thể lồng nhau. Hãy xác định một cửa sổ thời gian trôi qua và dùng trace để giải thích nội dung của nó.

Hai bước hoạt động có đủ để công bố một kết quả hiệu năng không?

Không. Lịch trình nhỏ được đề xuất chỉ minh họa API. Một kết quả dùng được đòi hỏi một cửa sổ đại diện, các lần lặp lại, bước khởi động rõ ràng và một phép đo cuối cùng không có chi phí phụ của việc thu thập chi tiết.

Một trace CPU có thể chẩn đoán ROCm không?

Nó có thể làm rõ công việc phía máy chủ, nhưng không thay thế các hoạt động GPU. PyTorch cũng dùng tên cuda trên ROCm; hãy kiểm tra backend, các hoạt động được hỗ trợ và những hoạt động thực sự được ghi lại trước khi diễn giải trace.