1 điểm bởi GN⁺ 2025-10-04 | 1 bình luận | Chia sẻ qua WhatsApp
  • 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

 
GN⁺ 2025-10-04
Ý kiến trên Hacker News
  • Nếu phân tích ptxas thì 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ên thực tế, thay vì lỗi tinh vi thì thường thấy nhiều thay đổi hiệu năng rất khó nhận ra hơn
      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)

    • Có lẽ không phải ác ý, nhưng kiểu tối ưu hóa này rốt cuộc vẫn tạo ra một rào cản mới
    • Phụ thuộc vào kiểu hàm hay schema thì còn phần nào hiểu được, nhưng nếu chỉ dựa vào cái tên đơn thuần thì thấy hơi kỳ
    • Dù có là để “ngăn bị hỏng”, nếu ai đó tình cờ dùng đúng cái tên đó thì vẫn có thể phát sinh vấn đề ngoài dự kiến
      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

    • Đầu năm 2024, SPEC đã vô hiệu hóa 2.600 kết quả benchmark CPU Xeon của Intel vì compiler của Intel dùng các tối ưu hóa không công bằng để nâng điểm (bài trên Tom's Hardware)
    • Microsoft cũng từng có những trường hợp làm điều tương tự với các chỉ số benchmark của compiler Java/C
    • Và giờ thì ai cũng đang hăng hái gian lận benchmark AI (bê bối benchmark AI)
  • 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.svg thì build sẽ bị hỏng
    Cuối cùng phải đổi tên file thành plus.svg mới giải quyết được

    • numpy cũng tương tự
      Có người từng vô tình phá numpy chỉ vì đặt một file là secret.py
  • Tô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)

    • Không rõ bạn đang nói đến chế độ nguồn phải không
      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

    • Cũng có người hỏi rằng trong trường hợp này tại sao không dùng inline assembly
  • 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 thấy nội dung này quen mắt, cứ như là đã từng đọc rồi
  • 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

    • Bản chất của vấn đề là chi phí cố định ban đầu để phát triển codebase phần mềm, chi phí nhân công để bảo trì về sau, và chi phí phân phối rất nhỏ (ví dụ máy chủ tải xuống)
      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í