- Attention カーネルを persistent 形式にリファクタリングし、短い context 長で性能を改善
- fp16 では 大きな context で softmax パーティションの ptxas 命令スケジューリング問題により性能低下が発生
- fp8 ではカーネル名に "cutlass" が含まれると約 100TFLOPS の性能向上を確認
- この最適化は カーネル命名によるハードコード最適化トリックと分析されている
- 性能への影響と動作原因は NVIDIA ptxas の内部実装による特異な現象
要約: Persistent Attention カーネルのリファクタリングと "cutlass" 命名効果
概要
- この Pull Request は Triton の attention カーネルを persistent attention 方式にリファクタリングする内容
- 主な目的は 短い context 長の区間で性能最適化を得ること
- ただし fp16 型では context サイズが大きくなるほど、softmax 部分の ptxas 命令スケジュール問題によって性能低下が発生する
fp8 での "cutlass" 名採用の効果
- fp8 モデルを使うと、カーネル名に "cutlass" を含めるだけで約 100TFLOPS まで性能向上することが測定された
- これは NVIDIA の ptxas(PTX アセンブラ) が内部的にカーネル名へ "cutlass" が含まれている場合、特殊最適化を適用するため
- 実際のコードでは dtype が float8e5 の場合、カーネル名を "cutlass_gluon_attention" などに割り当てている
- ptxas の逆アセンブル解析の結果、内部コードに
strstr(kernel_name, "cutlass") 条件文が実際に存在する
性能ベンチマーク
- リファクタリング前後の benchmark データでは、persistent attention 適用前より D=64 で相対的な性能低下が観測された
- これは softmax パートの命令スケジュール問題に起因する
- ただし fp8 型と "cutlass" 命名を組み合わせると、特定の context とサイズでは 著しく高いスループットを記録する
- 代表的な結果の要約:
- Attention Z=4, H=32, D=64, causal=False:
- persistent 適用前: triton-fp16 約 383, triton-fp8 約 413, cudnn-fp16 約 565
- persistent 適用後: triton-fp16 約 360, triton-fp8 約 370
- Attention Z=4, H=32, D=128, causal=True:
- persistent 適用前: triton-fp16 約 312, triton-fp8 約 345, cudnn-fp16 約 553
- persistent 適用後: triton-fp16 約 356, triton-fp8 約 351
命名トリックの発見と分析
- カーネル名に
"cutlass" という文字列が含まれる場合、NVIDIA ptxas で実験的な最適化ルーチンが有効化されることがコミュニティ分析で確認された
- ptxas には命名マッチング用のハードコードロジック(
strstr(kernel_name, "cutlass"))が存在する
- このトリックは aggressive かつ experimental な最適化であり、カーネルの精度変化の有無はハードウェアや状況によって異なる可能性がある
コミュニティでの議論
- 複数のレビュアーが性能比較、精度、最適化方式について質問と分析を進めた
- Deepseek technical report の内容や、Hopper GPU のような 特定アーキテクチャでの違いなども議論された
- 命名変更による最適化がどの程度広く適用されるのか、安定性の問題なども提起された
結論と示唆
- カーネル名だけでハードウェアレベルの実質的な性能変動が発生する点は非常に特異
- NVIDIA ソフトウェアスタック(ptxas)に隠れた最適化トリガーが存在するという点で、AI フレームワーク開発では命名規則も性能に影響しうることを示唆している
- 実務的にはこのトリックを使う際、再現性と安定性を必ずテストし、ハードウェアベンダーの最適化方針を注視する必要がある
1件のコメント
Hacker Newsの意見
ptxasを分解してみると、
cutlassというカーネル名を検出するロジックがハードコードされていることが確認された。NVIDIAはここに不安定で実験的かつ攻めた最適化を適用しているのだと思う。常時この最適化を有効にすると、微妙なバグが入り込む可能性があるのだろう。
GPUコンパイラは非常に難しく、基本的な最適化以上のことをやろうとすると、常に問題と入り混じった結果になる。
あるカーネルは速くなり、別のカーネルは遅くなり、全体として性能が向上することを期待するのはとても難しい。
テスト全体で、単一の最適化によって常に速度が上がることはほとんどない。
私の経験はNvidiaではないGPUシステムのものだが、この状況には見覚えがある。
Nvidiaも、あるカーネル群には驚くほど有効で、別の群にはひどい結果になる最適化を見つけたものの、それを自動適用するための信頼できる基準を見いだせなかったのだと思う。
こういう文脈の説明はありがたい。
この分野の人間ではないので(このプロジェクトのことも初めて聞いた)、タイトルもPRの内容も何を言っているのかまったく分からなかった。
25年前、ATI(AMD)がQuake IIIベンチマークで実行ファイル名を
quackに変えると性能が変わることで不正が発覚した件を思い出した。関連リンク: techreport.comのレビュー, hardocp.comのレビュー, 3dcenter.deの記事
私のように誤解した人がいるかもしれないので整理しておく。
ATIは
quakeという実行ファイル名を検出して、テクスチャ品質などを変えることでベンチマークスコアを引き上げていた。人々が実行ファイル名を
quackに変えたところ、画質が上がってスコアが下がることが分かり、ATIドライバが意図的に品質を落として速度を稼いでいたことが明らかになった。つまり、ATI自身がファイル名を変えたのではなく、ユーザーが変えたということだ。
あるいは、Intel C++ Compilerが出力値中の
GenuineIntel文字列をチェックしていた件もあった。関連Wikiは こちら
今日に至るまで、どのベンダーもこういうことをやっている。
ドライバが人気ゲームのレンダリングループをフックしてバグを直したり、シェーダをより最適化された版に置き換えたり、高速なコードパスを有効にしたりと、さまざまな形で介入している。
こうした変更は出力結果への影響を最小限にすべきだが、場合によっては介入が攻撃的すぎて品質が大きく低下することもある。
要するに、自社ハードウェアでゲームがより速く動くように手を入れているわけだ。
この話題をより深く議論したスレッドがあるので、こちらも参照するとよい。
面白いことに、同じcutlass最適化に関する過去の投稿だ。
こうした事例は非常によくある。
携帯向けチップセットメーカーはベンチマーク用に不正をしてきたし(VWは排ガス、Nvidiaは3DMarkベンチマーク、IntelはXeon向けSPECベンチマークなど)、
コンピュータグラフィックスでは、今やドライバがゲームごとに調整、設定、ワークアラウンドなどを入れるのがほとんど慣習になっている。
(残念ながら今はまともな出典リンクが消えることが多すぎて、archive.orgを使わざるを得ない。こういう記憶は残しておくべきだと思う。)
参考リンク: Mediatekのベンチマーク不正, Volkswagen排ガス不正スキャンダル, Nvidia 3DMark論争, Intel compilerのSPECベンチへの影響
コンパイラを扱う立場からすると、この種の最適化が名前(schema、substringなど)に依存することはある。
気に入らなくても、現実にはそう動く。
必ずしも悪意があるわけではなく、自前のライブラリにだけ最適化が適用されるよう設計するほうが、全体を壊すリスクより安全な選択であることもある。
あるいは、フロントエンドがより信頼できる情報(構造的な情報など)を提供できないためという場合もある。
こういうやり方は良くないと思う。
あまり新しい話ではないと思う。
約10年前、特定バージョンのWebpackで
add.svgというファイル名を使うとビルドが壊れたことを思い出した。結局、ファイル名を
plus.svgに変えて解決した。secret.pyというファイルを置いてしまい、意図せずnumpyを壊した経験をした人もいる。コミットメッセージが率直なのが印象的だ。
あるコミットdiffの構成の仕方について批判があった。
誰かが「何かをだいたい100 tflopsぶん速くした」と書いたときに、むしろ「コミットメッセージがよくない」と指摘する人がいるのだとしたら……その人はJohn Carmackのコミットスタイルも嫌うだろうと思う。
個人的には、こういう率直なメッセージは好きだ。
AIが自動生成したコミットメッセージ(
refactored Xみたいな繰り返し)ばかり並ぶより、ずっとましだと感じる。squashしてコミット履歴をまとめたほうがよいと思う。
なぜGitHubに載せるときにsquashしなかったのか、あまり理解できない。
NVIDIA Jetsonで使い方を学んでいた頃を思い出した。
たった1つのコマンドを実行するだけで、すべてが速くなると知ったのだった(関連リンク)。
記事の通りなら5Wと10Wの2種類があり、10Wがデフォルトなので、むしろデフォルトから5Wに切り替えたときだけ「より速くなる」が当てはまるようにも読めるのだが、私の理解が間違っているのだろうか。
高水準言語(C++など)で強くチューニングしたコードを書き、GPUアセンブリでも具体的な結果を期待しているのに、コンパイラが思った通りに出してくれないことがある。
コンパイラチームに相談すればさまざまな解決策を提示してくれるかもしれないが、オープンソースコードでは適用しにくい方法が多い(たとえば独自の
#pragmaやintrinsicなど)。高性能ライブラリを作る立場では、性能が出なければそもそも出荷できない。
こういうとき、関数名などを使って特定のコード変換を誘導するトリックに頼らざるを得ない。
こうした最適化は現実世界ではよく使われており、ベンチマークをだますために画質を落とす行為と同列にはできないと思う。
このPRが最初に上がったとき、すでに議論された内容だ。
新しい話はないように思う。
以前の議論
コード共有が容易な経済構造があればいいのにと思う。
バイナリブロブのドライバやベースバンドのような複雑な構造ではなく、誰もが容易に情報を得られて、無駄になる時間や労力を減らせるようになってほしい。
多くの優秀なエンジニアや研究者が、すでに誰かが持っている文書や回路図、バイナリコードをリバースエンジニアリングして解読するために、何か月も何年も費やしている。
CUDAやNVIDIAのような企業にはもどかしさを感じる。
デスクトップアプリであれば、ユーザー1人あたりの追加コストはほぼ0に近い。
だからソフトウェアには継続的な定期収入の仕組みが必要だが、ユーザー数に比例して収入が際限なく増えるべきではない。
新しいコード開発に投資した人たちは、製品が人気を得たときに投資を回収できなければならないが、既存のクラウドファンディングはこの構造を満たしていない。
ユーザーが増えるほど1人あたりの拠出額は大きく下がるため、全員が100%あるいは10%、いや1%しか負担しなくても、投資額は天文学的な規模になり得る。
結局のところ、オークション方式のプレッジが必要なのだと思う。
この構造にも問題はあり、特に独占モードと非独占モードの切り替えが厄介だ。
大企業数社が開発費をすべて負担してオープンソースとして公開した場合、他のすべての個人や企業は実質的にフリーライダーになる。