- Bắt đầu từ việc thiếu một trình gỡ lỗi có thể tạm dừng việc thực thi GPU và kiểm tra trạng thái, bài viết giải thích quá trình tự triển khai điều này trên GPU AMD
- Giao tiếp trực tiếp với GPU thông qua giao diện DRM và libdrm, đồng thời xây dựng tuần tự các bước tạo context, cấp phát bộ đệm và gửi lệnh
- Xây dựng cơ chế tạm dừng thực thi GPU và đọc/khôi phục trạng thái bằng cách tận dụng thanh ghi TBA/TMA và trap handler, kết hợp đồng bộ với CPU
- Mở rộng sang môi trường gỡ lỗi shader thực tế thông qua biên dịch mã SPIR-V và tích hợp RADV, cho phép triển khai các tính năng breakpoint·stepping·watchpoint
- Cách tiếp cận điều khiển trực tiếp cấu trúc bên trong GPU này chứng minh khả năng hiện thực một trình gỡ lỗi hoàn chỉnh cho GPU AMD, và còn dư địa phát triển để tích hợp Vulkan trong tương lai
Sự cần thiết của gỡ lỗi GPU và cách tiếp cận
- Xuất phát từ sự thiếu vắng công cụ có thể tạm dừng thực thi GPU và kiểm tra trạng thái như trên CPU
- Mô hình thực thi song song của GPU khiến việc gỡ lỗi phức tạp hơn nhiều
- Dù có
rocgdb trong môi trường AMD ROCm, nó chỉ hỗ trợ phạm vi giới hạn trong ROCm
- Tham khảo loạt bài blog của Marcell Kiss để thử tự triển khai một trình gỡ lỗi giao tiếp trực tiếp với GPU
Giao tiếp trực tiếp với GPU
- Theo dõi cách hoạt động của driver RADV để học cách giao tiếp trực tiếp với GPU
- Mở
/dev/dri/cardX để kết nối với KMD (kernel mode driver), sau đó gọi amdgpu_device_initialize
- Dùng
libdrm để tạo context (amdgpu_cs_ctx_create) và cấp phát bộ đệm
- Tạo hai bộ đệm: bộ đệm mã và bộ đệm lệnh
- Ánh xạ bộ đệm vào không gian địa chỉ ảo của GPU/CPU
- Thay vì
amdgpu_bo_va_op, xử lý ánh xạ bằng cách gọi IOCTL trực tiếp
- Dùng
clang và objdump để biên dịch mã hợp ngữ shader và trích xuất nhị phân
- Tạo lệnh GPU dưới dạng PM4 Packet để gửi lệnh thực thi shader
Trap GPU và sử dụng Debugfs
- Thiết lập trap handler bằng thanh ghi TBA/TMA của ISA RDNA3
TBA: địa chỉ trap handler
TMA: địa chỉ bộ nhớ tạm cho trap handler
- Vì không thể truy cập trực tiếp từ không gian người dùng nên sử dụng giao diện debugfs
- Truy cập thanh ghi thông qua tệp
/sys/kernel/debug/dri/{PCI address}/regs2
- Dùng
amdgpu_debugfs_regs2_write để ghi vào thanh ghi
- Thiết lập TBA/TMA theo từng VMID để kích hoạt trap handler
- Mỗi VMID dùng để phân biệt context tiến trình GPU
Triển khai trap handler
- Trap handler là chương trình shader đặc quyền chạy khi GPU gặp ngoại lệ
- Dùng thanh ghi TTMP để lưu trạng thái GPU (STATUS, EXEC, VCC, v.v.)
- Dùng lệnh
global_store_addtid_b32 để ghi giá trị thanh ghi theo từng luồng vào bộ nhớ
- Khi GPU ghi dữ liệu xong, CPU phát hiện việc đó và tạm dừng GPU bằng thanh ghi SQ_CMD
- Sau khi CPU phân tích dữ liệu, tiếp tục khôi phục thực thi GPU cũng bằng SQ_CMD
- Khi quay về, trap handler sẽ khôi phục program counter và trạng thái thanh ghi
Thực thi mã SPIR-V và tích hợp RADV
- Hỗ trợ biên dịch mã SPIR-V thay cho viết hợp ngữ thủ công
- Tận dụng trình biên dịch
ACO của RADV để chuyển SPIR-V thành nhị phân GPU
- Tạo thiết bị ảo bằng biến môi trường
RADV_FORCE_FAMILY
- Dùng chế độ
null_winsys của RADV để chỉ biên dịch mà không truy cập phần cứng thật
- Trích xuất từ kết quả biên dịch mã shader, cấu hình tài nguyên và thông tin gỡ lỗi
Mở rộng tính năng trình gỡ lỗi
- Stepping: dùng các bit
RSRC1.DEBUG_MODE, RSRC3.TRAP_ON_START để điều khiển thực thi theo từng lệnh
- Breakpoints: xử lý trap sau khi tính vị trí program counter dựa trên địa chỉ của bộ đệm mã
- Source Mapping: ánh xạ dòng mã nguồn bằng thông tin gỡ lỗi của trình biên dịch ACO
- Watchpoints: có thể triển khai chức năng giám sát địa chỉ bằng bảo vệ trang GPU hoặc thanh ghi
SQ_WATCH
- Theo dõi tên và kiểu biến: cần cải thiện việc truyền thông tin gỡ lỗi trong giai đoạn tối ưu hóa NIR của Mesa
- Tích hợp Vulkan: dựa trên RADV, có thể gỡ lỗi theo từng frame và tận dụng thông tin về buffer, texture, hằng số
Phần thưởng thêm: mã page walking ở user mode
- Cung cấp ví dụ mã duyệt page table cho GPU RDNA3 (gfx11)
- Bao gồm định nghĩa struct PDE/PTE và hàm giải mã
- Triển khai quá trình chuyển đổi từ địa chỉ ảo sang địa chỉ vật lý
- Có thể phân tích cấu trúc ánh xạ bộ nhớ GPU bằng cách đọc thanh ghi page table theo từng VMID
Kết luận
- Chứng minh khả năng hiện thực một trình gỡ lỗi hoàn chỉnh cho GPU AMD thông qua truy cập ở mức kernel và phần cứng
- Xây dựng vòng lặp giao tiếp hai chiều giữa CPU và GPU để hiện thực việc tạm dừng thực thi, phân tích trạng thái và tiếp tục chạy
- Trong tương lai, có thể phát triển thành môi trường gỡ lỗi GPU thân thiện hơn với lập trình viên thông qua tích hợp RADV và Vulkan
1 bình luận
Ý kiến trên Hacker News
Không phải AMD, nhưng Metal cung cấp một bộ debugger và công cụ phát triển thực sự xuất sắc
Vì vậy khi làm việc với GPU, tôi luôn ưu tiên dùng Metal trước rồi mới port sang hệ thống khác
Có thể tham khảo tài liệu Metal Debugger
Tôi không phải lập trình viên game AAA, nhưng với nhu cầu của tôi thì nó gần như hoàn hảo
Đặc biệt ấn tượng là tính năng in chuỗi log được định dạng từ shader rồi hiển thị lẫn cùng log của ứng dụng
Tôi đang phát triển một ứng dụng GPU dùng cả Metal và OpenGL, và ở phía OpenGL thì rất khó tìm được công cụ ở mức như Metal
Cả hai nền tảng đều cung cấp debugger chuyên dụng, và chất lượng khá tốt
Cuối cùng tôi nhận ra rằng khi chỉ thấy một màn hình đen thì toolchain là tất cả
Tôi tự hỏi nếu dùng DirectX thay vì OpenGL thì có thể có tool tốt hơn trên Windows hay không
Đặc biệt khi xử lý compute shader thì profiling nhiều lúc không hoạt động tốt
Đây là bộ công cụ được thiết kế thiên về đồ họa, nên có vẻ vẫn còn giới hạn với AI hoặc tác vụ buffer dung lượng lớn
Nó hợp với tôi hơn OpenGL rất nhiều
Ở phía OpenGL, bạn đã thử RenderDoc chưa? Với Vulkan/OpenGL thì đó là công cụ gần giống nhất
Mua một chiếc máy đắt tiền chỉ để debug API độc quyền của Metal là không hiệu quả
Nếu nghiêm túc muốn học lập trình đồ họa, tôi nghĩ nên học DX12 hoặc Vulkan trên Windows hay Linux thì hơn
Dùng các công cụ như RenderDoc là hoàn toàn đủ
Metal là một API tốt, nhưng hạn chế lớn nhất là không thể dùng bên ngoài nền tảng Apple
Trong môi trường server hay game, phần lớn đều dùng GPU AMD hoặc Nvidia, nên phát triển xoay quanh Metal là không thực tế
CUDA của NVIDIA có một bản GDB chính chủ tên là cuda-gdb
Như có thể thấy trong tài liệu chính thức, nó rất phù hợp với mô hình luồng của CUDA
Tuy vậy, chỉ có thể single-step ở cấp độ warp
Trên card NVIDIA có thể dùng NSight, và cũng có RenderDoc chạy được trên nhiều loại GPU
Khi thiếu các trực quan hóa cấp cao như QML hay QSG_VISUALIZE=overdraw, việc lần theo cảnh ở mức từng lệnh gọi API khá thú vị
Nhiều người không biết rằng chúng vẫn dùng được ngay cả khi không có GPU
Trước câu hỏi có công cụ chính thức nào cho AMD không, thì GDB có hỗ trợ gỡ lỗi AMD GPU
Ngoài ra còn có các công cụ như UMR của AMD,
Radeon GPU Detective,
và Radeon Developer Tool Suite
Chia sẻ một công cụ giám sát tự làm cho AMD GPU
Đó là dự án picomon, được tạo ra để xử lý vấn đề nvtop quá khắt khe nên hay bị crash
Metal, CUDA, Pix, PS/Switch... mỗi nền tảng đều có công cụ chuyên dụng riêng
Đây cũng là lý do các nhà nghiên cứu vẫn có xu hướng ưa chuộng CUDA
Nsight Systems cũng là một trong số đó
Không biết có ai đang dùng GPU 7900 XTX cho suy luận cục bộ (local inference) hay diffusion không
Tôi đã cài Linux nhưng nó hầu như đang để không, nên muốn tận dụng nó
Trước đây từng có vấn đề liên quan đến Python, nhưng gần đây đã ổn định và thậm chí làm được cả img2video
Với 24GB VRAM, tôi vẫn cho rằng đây là chiếc card có hiệu năng/giá tốt nhất
ROCm gần đây đã được cải tổ mạnh để cải thiện UX, nên bạn nên xem thử TheRock
Cả model devstral:24b cũng chạy khá nhanh
Trong ComfyUI thì phần lớn hoạt động tốt, nhưng với một số tác vụ lạ thì không ổn định
Gần đây tôi nghe nói nó đã ổn định hơn