- Refactor kernel attention sang dạng persistent để cải thiện hiệu năng ở độ dài context thấp
- Với fp16, ở context lớn hiệu năng bị giảm do vấn đề lập lịch lệnh của ptxas trong phần softmax
- Với fp8, khi tên kernel chứa "cutlass" thì ghi nhận mức tăng hiệu năng khoảng 100 TFLOPS
- Tối ưu hóa này được phân tích là một mẹo tối ưu hóa hard-code thông qua cách đặt tên kernel
- Ảnh hưởng tới hiệu năng và nguyên nhân hoạt động là hiện tượng bất thường do cách triển khai nội bộ của NVIDIA ptxas
Tóm tắt: Refactor Persistent Attention kernel và hiệu ứng đặt tên "cutlass"
Tổng quan
- Pull Request này refactor kernel attention của Triton theo hướng persistent attention
- Mục tiêu chính là đạt được tối ưu hiệu năng ở vùng độ dài context thấp
- Tuy nhiên, với kiểu fp16, khi kích thước context tăng lên thì xuất hiện hiện tượng giảm hiệu năng do vấn đề lập lịch lệnh của ptxas ở phần softmax
Hiệu quả của việc dùng tên "cutlass" với fp8
- Khi dùng mô hình fp8, nếu thêm "cutlass" vào tên kernel thì đo được mức tăng hiệu năng tới khoảng 100 TFLOPS
- Nguyên nhân là ptxas (trình assembler PTX) của NVIDIA dường như áp dụng một tối ưu hóa đặc biệt khi tên kernel có chứa "cutlass"
- Trong mã thực tế, nếu dtype là float8e5 thì tên kernel được gán thành "cutlass_gluon_attention" v.v.
- Kết quả phân tích disassembly của ptxas cho thấy trong mã nội bộ thực sự có điều kiện
strstr(kernel_name, "cutlass")
Benchmark hiệu năng
- Trong dữ liệu benchmark trước và sau khi refactor, quan sát thấy hiệu năng tương đối giảm ở D=64 so với trước khi áp dụng persistent attention
- Nguyên nhân là do vấn đề lập lịch lệnh ở phần softmax
- Tuy nhiên, khi kết hợp kiểu fp8 với cách đặt tên có "cutlass", ở một số context và kích thước nhất định ghi nhận throughput cao vượt trội
- Tóm tắt một số kết quả tiêu biểu:
- Attention Z=4, H=32, D=64, causal=False:
- trước khi áp dụng persistent: triton-fp16 khoảng 383, triton-fp8 khoảng 413, cudnn-fp16 khoảng 565
- sau khi áp dụng persistent: triton-fp16 khoảng 360, triton-fp8 khoảng 370
- Attention Z=4, H=32, D=128, causal=True:
- trước khi áp dụng persistent: triton-fp16 khoảng 312, triton-fp8 khoảng 345, cudnn-fp16 khoảng 553
- sau khi áp dụng persistent: triton-fp16 khoảng 356, triton-fp8 khoảng 351
Phát hiện và phân tích mẹo đặt tên
- Phân tích từ cộng đồng xác nhận rằng khi chuỗi
"cutlass" xuất hiện trong tên kernel thì một routine tối ưu hóa thực nghiệm trong NVIDIA ptxas sẽ được kích hoạt
- Trong ptxas có logic hard-code để khớp tên (
strstr(kernel_name, "cutlass"))
- Mẹo này là một tối ưu hóa mang tính aggressive và experimental, nên việc độ chính xác của kernel có thay đổi hay không có thể phụ thuộc vào phần cứng và từng tình huống
Thảo luận trong cộng đồng
- Nhiều reviewer đã đặt câu hỏi và phân tích về so sánh hiệu năng, độ chính xác và cách tối ưu hóa
- Nội dung trong Deepseek technical report, cũng như khác biệt trên một số kiến trúc cụ thể như GPU Hopper, cũng được đem ra thảo luận
- Cộng đồng cũng đặt vấn đề về phạm vi áp dụng của tối ưu hóa thông qua đổi tên, cũng như các vấn đề về độ ổn định
Kết luận và hàm ý
- Việc chỉ riêng tên kernel cũng có thể tạo ra thay đổi hiệu năng thực tế ở cấp độ phần cứng là một hiện tượng rất đặc biệt
- Điều này cho thấy trong software stack của NVIDIA (ptxas) tồn tại các trigger tối ưu hóa ẩn, và quy ước đặt tên cũng có thể ảnh hưởng tới hiệu năng khi phát triển framework AI
- Trong thực tế, nếu dùng mẹo này thì cần обязательно kiểm tra tính tái lập và độ ổn định, đồng thời nên theo dõi sát chính sách tối ưu hóa từ nhà cung cấp phần cứng
1 bình luận
Ý kiến trên Hacker News
Nếu phân tích
ptxasthì có thể xác nhận rằng có logic được hardcode để phát hiện tên kernel là "cutlass"Có vẻ NVIDIA đã áp dụng ở đây một tối ưu hóa không ổn định, mang tính thử nghiệm và rất quyết liệt; nếu luôn bật tối ưu hóa này trong mọi trường hợp thì có thể phát sinh các lỗi tinh vi
Trình biên dịch GPU cực kỳ phức tạp, và cứ hễ cố đi xa hơn các tối ưu hóa cơ bản thì kết quả gần như luôn là sự pha trộn giữa lợi ích và vấn đề
Có kernel thì nhanh hơn, có kernel thì chậm hơn, và việc làm sao để hiệu năng tổng thể thực sự tăng lên là điều rất khó
Gần như không có tối ưu hóa đơn lẻ nào mà lúc nào cũng làm mọi bài test chạy nhanh hơn
Kinh nghiệm của tôi là ở các hệ thống GPU không phải của Nvidia, nhưng tình huống này nghe rất quen
Có lẽ Nvidia cũng đã tìm ra những tối ưu hóa cho kết quả tuyệt vời với một số tập kernel, nhưng lại cho kết quả tệ hại với những tập khác, và dường như họ cũng không tìm ra được tiêu chí đủ đáng tin để tự động áp dụng nó
Cảm ơn vì đã giải thích bối cảnh này
Tôi không làm trong mảng này (và cũng mới nghe về dự án này lần đầu), nên đọc tiêu đề với nội dung PR mà mãi vẫn không hiểu nổi
Điều này làm tôi nhớ đến vụ ATI (AMD) cách đây 25 năm bị phát hiện gian lận khi hiệu năng trong benchmark Quake III thay đổi nếu đổi tên file thực thi thành 'quack'
Có để lại các liên kết liên quan: bài review trên techreport.com, bài review trên hardocp.com, bài viết trên 3dcenter.de
Tôi ghi lại cho những ai có thể hiểu lầm giống tôi
ATI phát hiện tên file thực thi là 'quake' rồi thay đổi chất lượng texture v.v. để nâng điểm benchmark
Mọi người đổi tên file thực thi thành 'quack' thì phát hiện chất lượng hình ảnh tăng lên còn điểm số giảm xuống, từ đó lộ ra việc driver ATI đã cố tình hạ chất lượng để tăng tốc độ
Nói cách khác, không phải ATI tự đổi tên file, mà là người dùng đã đổi
Hoặc còn có vụ Intel C++ Compiler kiểm tra chuỗi "GenuineIntel" trong đầu ra
Liên kết wiki liên quan là ở đây
Cho đến tận ngày nay, mọi vendor vẫn làm kiểu này
Driver can thiệp vào vòng lặp render của các game phổ biến để sửa lỗi, thay shader bằng phiên bản được tối ưu hơn, hoặc mở ra các code path nhanh hơn, bằng đủ mọi cách
Những thay đổi như vậy lẽ ra chỉ nên ảnh hưởng tối thiểu đến kết quả đầu ra, nhưng có những trường hợp can thiệp quá mạnh tay đến mức chất lượng bị giảm đáng kể
Vì thế họ chỉnh sửa để game chạy nhanh hơn trên phần cứng của mình
Có một thread thảo luận sâu hơn về chủ đề này, nên khuyên xem ở đây
Thú vị ở chỗ đó cũng là một bài viết cũ liên quan đến cùng tối ưu hóa cutlass này
Những trường hợp như vậy rất phổ biến
Các hãng làm chipset điện thoại từng gian lận benchmark (VW với khí thải, Nvidia với benchmark 3DMark, Intel với benchmark SPEC cho Xeon, v.v.)
Trong đồ họa máy tính thì giờ gần như đã thành thông lệ việc driver nhét vào các tweak, thiết lập và workaround riêng cho từng game
(Đáng tiếc là dạo này liên kết nguồn tử tế biến mất quá thường xuyên, nên phải dùng archive.org. Tôi nghĩ những ký ức kiểu này cần được lưu lại)
Liên kết tham khảo: Mediatek gian lận benchmark, vụ bê bối gian lận khí thải của Volkswagen, tranh cãi Nvidia 3DMark, ảnh hưởng của tối ưu hóa compiler Intel tới benchmark SPEC
Từ góc nhìn của người làm compiler, kiểu tối ưu hóa như thế này đôi khi действительно phụ thuộc vào tên (schema, substring, v.v.)
Dù không thích thì ngoài thực tế nó vẫn vận hành như vậy
Không nhất thiết là ác ý; việc thiết kế để tối ưu hóa chỉ áp dụng cho chính thư viện của mình đôi khi còn là lựa chọn an toàn hơn so với rủi ro làm hỏng mọi thứ
Hoặc cũng có khi là do frontend không thể cung cấp thông tin đáng tin cậy hơn (chẳng hạn thông tin có cấu trúc)
Tôi không nghĩ cách này là hữu ích
Tôi không nghĩ đây là điều gì quá mới
Chuyện này làm tôi nhớ đến việc khoảng 10 năm trước, ở một phiên bản Webpack nào đó, nếu dùng tên file
add.svgthì build sẽ bị hỏngCuối cùng phải đổi tên file thành
plus.svgmới giải quyết đượcnumpycũng tương tựCó người từng vô tình phá
numpychỉ vì đặt một file làsecret.pyTôi thấy ấn tượng vì commit message viết rất thẳng thắn
Có người từng chỉ trích cách tổ chức diff của commit đó
Có người bảo rằng khi ai đó viết “đã làm cái gì đó nhanh hơn khoảng 100 tflops”, lại đi chê rằng “commit message dở quá”... vậy thì chắc họ cũng sẽ không thích kiểu commit của John Carmack
Cá nhân tôi lại thích kiểu message thẳng thắn như vậy
Tôi thấy nó tốt hơn rất nhiều so với việc toàn thấy các commit message do AI tự sinh kiểu lặp đi lặp lại như "refactored X"
Tôi nghĩ nên squash để gộp lịch sử commit lại
Tôi không hiểu sao khi đưa lên GitHub lại không squash
Chuyện này làm tôi nhớ thời học cách dùng NVIDIA Jetson
Khi đó tôi nhận ra rằng chỉ cần chạy một lệnh là mọi thứ sẽ nhanh hơn hẳn (liên kết liên quan)
Theo bài viết thì có hai mức 5W và 10W, mà 10W lại là mặc định, nên thậm chí có thể hiểu là chỉ khi đổi từ mặc định sang 5W thì mới áp dụng chuyện “nhanh hơn”; hay là tôi đang hiểu sai điều gì đó?
Có những lúc bạn viết code được tuning rất mạnh bằng ngôn ngữ cấp cao (C++ chẳng hạn), đồng thời cũng kỳ vọng kết quả cụ thể ở mức GPU assembly, nhưng compiler lại không tạo ra thứ bạn muốn
Nếu hỏi đội ngũ nội bộ thì họ có thể đưa ra nhiều giải pháp, nhưng với mã nguồn mở thì nhiều cách khó áp dụng (ví dụ
#pragmađộc quyền, intrinsic v.v.)Với người làm thư viện hiệu năng cao, nếu hiệu năng không đạt thì gần như không thể phát hành được
Trong những lúc như vậy, đôi khi không còn cách nào khác ngoài việc dùng các mẹo như tên hàm để kích hoạt các phép biến đổi mã cụ thể
Những tối ưu hóa như vậy rất phổ biến trong thế giới thực, và tôi không nghĩ có thể xem nó ngang hàng với việc cố tình hạ chất lượng hình ảnh để gian lận benchmark
Chủ đề này đã được bàn đến ngay từ lúc PR này mới được đăng lần đầu
Tôi không thấy có gì mới
Thảo luận trước đó
Tôi ước gì tồn tại một cấu trúc kinh tế giúp việc chia sẻ code trở nên dễ dàng hơn
Thay vì những cấu trúc phức tạp như driver binary blob, baseband v.v., sẽ tốt hơn nếu ai cũng có thể dễ dàng tiếp cận thông tin để giảm bớt thời gian và công sức bị lãng phí
Rất nhiều kỹ sư và nhà nghiên cứu giỏi đã phải tiêu tốn hàng tháng, hàng năm để reverse engineering và giải mã các tài liệu, sơ đồ mạch và mã nhị phân mà ai đó đã nắm sẵn
CUDA và những công ty như NVIDIA thật sự khiến người ta bức bối
Với ứng dụng desktop, chi phí tăng thêm cho mỗi người dùng gần như tiến về 0
Vì thế phần mềm cần một cấu trúc doanh thu định kỳ liên tục, nhưng doanh thu đó lại không nên tiếp tục tăng tỷ lệ thuận với số người dùng
Những người đã đầu tư vào việc phát triển mã mới cần có cách thu hồi vốn khi sản phẩm trở nên phổ biến, nhưng crowdfunding hiện nay không đáp ứng được cấu trúc này
Khi số người dùng tăng lên thì mức đóng góp trên đầu người giảm rất mạnh, nên chỉ cần mọi người đóng 100%, hay 10%, thậm chí 1% thôi thì tổng số tiền hoàn vốn cũng có thể thành con số khổng lồ
Cuối cùng tôi nghĩ cần một mô hình pledge theo kiểu đấu giá
Cấu trúc này cũng có vấn đề riêng, trong đó chuyện chuyển đổi giữa chế độ độc quyền và không độc quyền là đặc biệt rắc rối
Nếu một vài tập đoàn lớn trả toàn bộ chi phí phát triển rồi công bố thành mã nguồn mở, thì tất cả cá nhân hay công ty còn lại về thực chất đều trở thành người đi nhờ miễn phí