
NVIDIA Blackwell(sm_120)向け世界初のハザードチェッカー。自社コンパイラとバイト単位で一致するように調整されたアセンブラとスケジューラを備えています。彼らが決してリリースしなかった検査。
NVIDIA GPU の命令は 128 ビットで、そのうち 21 ビットは命令そのものではありません。これらはスケジューリング制御ワード、stall から reuse までで、次の命令を発行する前に何サイクル待機するか、どのスコアボードにシグナルを送るか、どのスコアボードを待つか、どのオペランドが再利用キャッシュから供給されるかを示します。
ハードウェアはそのいずれも検査しません。 sm_120 には固定レイテンシ命令に対するインターロックがありません。シリコンは制御ワードを生成したものを信頼します。ストール数が次の命令が消費する値のレイテンシよりも短い場合、フォールトもストールも発生せず、警告も出力されません。命令はまだ書き込まれていないレジスタを読み取り、古いデータで計算を毎回フルスピードで実行します。
これは奇妙な種類のバグです。クラッシュしません。デバッガにも現れません。単に誤った数値を生成するだけです。行列乗算やアテンションカーネルでは、目に見えて壊れるモデルではなく、わずかにうまく学習できないモデルになるということです。
最も安価な 3 つのエンコーディングが壊れており、どこもそれを報告しません。また、左端の バーが何をしているかに注目してください。ゼロのストールはゼロサイクルではなく、未処理の 結果を待つ明確に安全なエンコーディングであり、スケジュール済み命令の約 9 倍のコストがかかり ます。これをゼロと読むチェッカーは、正しいプログラムを壊れていると呼ぶでしょう。
このアーキテクチャのマシンコードを生成するツールは、レイテンシモデルからそれらの制御ビットを割り当てます。basalt はその答えを検証するものです。
NVIDIA は、それら 21 ビットを書き込むコンパイラを提供します。しかし、それらを読み戻して安全だと教えてくれるものは何も提供しません。他の誰も提供していません。
NVIDIA GPU 用のアセンブラは 10 年前から存在し、Blackwell のエンコーディングは過去にリバースエンジニアリングされ、sm_120 のサイクルレベル特性は公開されており、このアーキテクチャ向けの公開アセンブラは、スケジューリング制御ビットを自身で割り当て、カード上で独自カーネルを実行して答えが正しいことを確認しています。すべて事実ですが、どれもこの主張ではありません:
自分が生成していない cubin を渡されて、そのスケジューリング制御ビットが安全かどうかを述べるよう求められるものは、他には何もありません。
あなたのコンパイラがその cubin を生成したか、ライブラリが出荷したか、誰かが手書きしたかです。そして今まで、問い合わせる方法はありませんでした。ハードウェアインターロックのないアーキテクチャでは、それが「実行された」と「正しい」の違いであり、その違いは目に見えません。1 サイクル足りないストールは、古いレジスタを読み取り、フォールトも警告もなしに、毎回フルスピードで誤った数値を返します。
ここにある他のすべては、その文をテスト可能にするために存在します。アセンブラは、1 つのストールを意図的に短くしたプログラムを構築するものです。スケジューラは、他人の答えを評価するのではなく、モデルに答えを確定させるものです。そして監査は、その文が欠如ではなく測定になる場所です。basalt は、NVIDIA が cuBLAS、cuSOLVER、cuSPARSE、NPP などで出荷する 2,473 個の sm_120 cubin を対象にしました。
なぜ存在しなかったのか、この分野自身の言葉で。 最も使われている SASS アセンブラは、その独自ドキュメントで、「公式サポートなしでプログラム全体の厳密な正しさを検証することはほぼ不可能です。したがって、ユーザーがアセンブラからの非常に限られた支援のみでプログラムの正しさを保証することになります」と述べています。SIP は、SASS スケジュールの自動チューニングに関して、「sass の形式的意味論がクローズドソースであるため、GPU ネイティブアセンブリコードの検証は不可能です」と述べています。
どちらも意味的正しさに関するものです。つまり、カーネルが意図したとおりに計算するかどうかです。basalt はそれに答えず、ここにあるものもそれを主張しません。basalt は厳密に小さな問いに答えます。その要点は、より小さな問いは意味論なしで決定可能であるということです:
このプログラムの制御ビットは、自身のデータ依存関係をカバーしているか?
それには、エンコーディングが提供する依存構造と、測定によってシリコンが提供するレイテンシモデルが必要です。どちらも、命令が何を計算するかを知る必要はありません。カーネルはこの検証に合格しても、依然として誤ったアルゴリズムであり得ます。できないのは、値が到着する前にレジスタを読み取ることです。
第二に、他の何ものもベンダー自身のバイトと照合されていません。 basalt の参照は ptxas 出力です。したがって、不一致は反証がない限り basalt のバグです。そのアセンブラはコンパイラの正確な 128 ビットを再現しなければなりません。そのスケジューラは、コンパイラが選択したすべての制御ビットを捨て、新しいものを計算し、GPU に同じ答えを計算させなければなりません。
すべてに共通する基準: ベンダーと正確に一致するか、そうでないなら理由を説明すること。
そして、スケジューラが通常は黙っている部分: 正しさのコストです。basalt のスケジュールは、ベンダーの発行サイクルの 1.05 倍を消費し、1,323 のカーネルと最適化レベルの組み合わせのうち 111 件で遅く、842 件で安価ですが、比較可能なすべてのカーネルは GPU 上で依然としてバイト単位で同一です。
3 行目が他の 3 行を変えたものです。コーパスで較正されたチェッカーは、そのコーパスでは失敗できません。コンパイラが残すことが観察された最小ギャップは、測定されたコードに対して、構造上、下限そのものだからです。このチェッカーが初めて別の場所のコードを見たとき、誤ったピクセルを返したことのない JPEG デコーダで、カーネルごとに 26 個のハザードを報告し、6,593 個すべてが basalt 側の誤りでした。それらを修正するとゼロになりましたが、1 つのライブラリでのゼロは証拠にはなりませんでした。保持したセットを 3 つのライブラリと 520 万命令に広げると、すぐに 940 に戻り、最初の 8 つに加えてさらに 5 つのモデルエラーが見つかりました。修正は 13 件で、そのどれも NVIDIA 側のものではありません。24,311 個の出荷済みカーネルから再抽出された要件は、229,567 件の観測にわたる 13 サイクルのガード述語を置きました。これは、フォールトインジェクションがこのカード上でプログラムを意図的に壊して測定した数です。finding 32 を参照してください。
ベンダーより安価であることは、得意がるべき主張ではありません。basalt はすべての依存関係を、ptxas がその正確なペアに対して残すことが観察された最小ギャップでスケジュールします。そして ptxas は、このツールが 1 つの数値を最適化する一方で、発行レイテンシと並行してレジスタプレッシャーとメモリのバランスを取っています。また、一目で信じられたわけでもありません。比率が初めて 1.0 を下回ったとき、ハードウェア往復が壊れ、露呈したバグが修正されて初めてその数値は成立しました。そのため、この比率はテストスイートで両側から固定されています。
中央の列が要点です。同じレイテンシモデルを共有するチェッカーとスケジューラは、両方が間違っていても互いに一致するため、どちらも相手の証拠にはなりません。議論に利害関係がないのはシリコンだけです。7 つの手書きカーネルでスケジューラを実行すると、長い間 7 つ中 7 つが合格しました。300 で実行すると 41 個の誤りが見つかり、findings のすべての修正は、その数値が動くのを見て生まれました。
同じことが入力にも当てはまります。古い読み取りは、古い値と新しい値が異なる場合にのみ答えを変えます。したがって、1 つのバイトパターンは 1 回の気付きの機会です。すべてのカーネルを 2 番目、3 番目、4 番目のパターンに対して実行すると、オペランドモデルが最初からソースとして読み取っていたキャリーアウト述語がすぐに見つかりました。それは、往復自体を含む、その時点までのすべての管理を生き延びていました。
同じ規律が、アセンブラに何を許すかを決定します。そして、アセンブラが持つ 2 つの数値を分けて考える価値があります。
カバレッジはコーパスの 99.9%、出荷済みライブラリコードの 87.5% です。 正しさは 100% であり、それがテストで固定された数値です。 その間のギャップは、basalt が拒否する命令です。それぞれが、配置できなかったフィールドを名指しします。推測するツールは、正しいテキストに逆アセンブルされ、別のものを計算するワードを出力することで完全なカバレッジに到達するからです。59,760 のコーパス命令と 5,237,448 の出荷済み命令を通じて、そのようなワードを一度も出力したことはありません。
そこに到達したのは、自信満々に誤っていた 8 回の別々のラウンドを経てからです:
そのどれもが、アセンブルされ、元のテキストに正確に逆アセンブルされ、別のものを計算するワードを生成しました。これは、このリポジトリの残りが存在する理由である同じ失敗です。そのため、8 つすべてが現在、フィールドが実際に保持するものを名指しする理由とともに拒否され、誤ったバイトにアセンブルされる命令の数がテーブル内の数値ではなくゼロに固定されたテストなのです。
9 つ目は、アセンブラが初めて自分が生成していないマシンコードを対象にしたときに現れ、それは異なる種類のものでした。c[0x0][UR4] は、記録された形式が数値を保持する場所で、オフセットをレジスタでインデックスします。エンコーダは拒否する代わりに例外を発生させました。外部入力でのクラッシュは、誤った判定より悪いものです。呼び出し元はどちらも得られないからです。
sm_120 はモデル番号ではありません。これはコンシューマー Blackwell ライン全体が共有するコンピュートケイパビリティであり、命令エンコーディング、データベース、アセンブラ、チェッカーはそのすべてのカードに適用されます:
ptxas は同じファミリの別チップである sm_121 もターゲットにします。basalt は sm_121 で実行したことがなく、サポートも主張していません。言えることは測定されたことだけです。コンパイラは、ここで提供される 6 つのターゲットすべてに対して制御ワードを含むバイト単位で同一のコードを生成するため、カーネルが必要とするスケジュールはパーツ固有のプロパティではなくアーキテクチャのプロパティです(finding 28)。もしそうでなければ、NVIDIA 自身のコンパイラがそのうちの 1 つに対して安全でないスケジュールを生成していることになります。
シリコン上で測定されたすべての数値は、1 枚の物理カードから得られたもので、正確に名前が示されています。「5070 Ti」だけでは実行を再現するのに不十分だからです:
basalt のほとんどは GPU をまったく必要としません。 2 つのオラクル、命令データベース、アセンブラ、ハザードチェッカーは、ptxas と nvdisasm を通常のサブプロセスとして実行します。そのため、グラフィックスカードのないマシン上の CI で実行されます。252 のテストのうち 237 がこのグループにあり、200 はカードも NVIDIA バイナリも必要としません。
GPU が必要なのは正確に 3 つだけです。それらは、もっともらしいツールを信頼できるツールに変える 3 つです:
ここで測定されたすべては 1 枚のカードで測定されました。basalt は、それらを普遍的として提示するのではなく、すべての測定値とともに SKU を記録します。5090 は 2 倍以上の SM と独自のクロック動作を持ちます。エンコーディングは同一ですが、レイテンシは推定するのではなく再測定する必要があります:```bash python -m basalt.cli measure -o my-card.json python -m basalt.cli verify kernel.cubin --latencies my-card.json
それは謙遜ではない。チェッカーとスケジューラが共有するレイテンシモデルこそ、間違った数値が潜みやすい場所であり、だからこそ2枚目のカードは誰にとっても最も有用な貢献となる。
</details>
## 仕組み
すべては2つのオラクルに依存しており、どちらも外部プロセスとして駆動される標準のNVIDIAバイナリである。NVIDIAのソース、ヘッダ、ライブラリは一切使用も再配布もされない。
| オラクル | 呼び出し | 得られるもの |
| :--- | :--- | :--- |
| **正解(グラウンド・トゥルース)** | `ptxas` → cubin → `nvdisasm -c -hex` | ベンダーコンパイラが実際に出力するエンコーディング。意味論は議論の余地がない。 |
| **プローブ** | `nvdisasm -b SM120a` を生バイトに対して | `ptxas` が決して出力しないワードをデコードし、エンコーディング空間を推測する対象ではなく検索可能な対象に変える。 |
重要なのはプローブオラクルの方である。コンパイラの出力だけに限ったツールは、コンパイラがすでに行っていることを再発見するだけに終わる。合成された128ビットのワードを直接デコーダに渡すことで、命令セットは *測定* 可能になる。
どちらのオラクルもGPUを必要としないため、命令データベース全体が任意のマシン上のCIで再構築される。
### エンコーディングを変更して導出する
basalt は、どこからもオペコードのテーブルを読み込まない。アセンブル済みのエンコーディングを取り、1ビットを反転し、結果をデコードして、何が変わったかを記録する。デスティネーションレジスタを変えるビットはデスティネーションビットであり、ニーモニックを変えるビットはセレクタであり、観測可能なものを変えないビットは不活性である。
`IADD R5, R5, 0x2a` に対して実行すると、測定結果は次のようになる:```
operand[0] bits 16:23 flip 16 -> R4, flip 17 -> R7 destination register
operand[1] bits 24:31 plus bit 72, which negates it source register
operand[2] bits 32:63 flip 32 -> 0x2b, flip 33 -> 0x28 32-bit immediate
opcode bits 2, 4, 12:15
inert 36 bits no observable effect
invalid 11 bits the decoder rejects the mutation
8ビットのレジスタフィールドと32ビットの即値は、推測ではなく実験によって決められた。
| コンポーネント | 機能 | 検証方法 | 結果 |
|---|
| アセンブラ | SASS テキストを 128 ビットワードに変換 | ptxas が出力したすべての命令を再アセンブルしてバイトを比較。コーパス上と、これまで見たことのない出荷済みライブラリコード 5.2M 命令で実施 | コーパス命令 59,760 件中 59,693 件、出荷済み命令 5,237,448 件中 4,585,336 件が完全一致。残りは名前を明示して拒否。どちらも誤り 0 |
| チェッカー | スケジュールを読み取り、ハザードを報告 | ベンダー自身の出力がクリーンであることを検証し、意図的に短縮されたストールを検出できること | ベンダーのカーネルと最適化レベルの組み合わせ 1,323 件でエラー 0、壊れた 233 件で見逃し 0 |
| 監査 | 同じチェッカーを出荷済みライブラリに適用 | 参照するすべてのテーブルから除外した本番 sm_120 カーネル群に対して実行 | 2,762 カーネルと 10,218,030 の依存関係に対してエラー 0、2,762 すべてを完全に分析 |
| スケジューラ | すべての制御ビットをゼロから割り当て | ベンダーのものを破棄し、新しいものを計算し、両方を GPU で 8 つの入力に対して実行し、出力バイトを比較 | 比較可能なカーネル 439 件中 439 件がバイト単位で同一。3 つの最適化レベルすべてで |
| カード | コンピュートケイパビリティ | 対象 |
|---|
| GeForce RTX 5090, 5090D | 12.0 (sm_120) | 対応 |
| GeForce RTX 5080, 5070 Ti, 5070 | 12.0 (sm_120) | 対応 |
| GeForce RTX 5060 Ti, 5060, 5050 | 12.0 (sm_120) | 対応 |
| GeForce RTX 50 シリーズ ラップトップ向けパーツ | 12.0 (sm_120) | 対応 |
| RTX PRO Blackwell ワークステーションカード | 12.0 (sm_120) | 対応 |
| データセンター向け Blackwell (B100, B200, GB200) | 10.0 (sm_100) | 非対応、エンコーディングが異なる |
| カード | 正確には何か |
|---|
| ボード | Gigabyte GeForce RTX 5070 Ti EAGLE OC |
| ドライバによる報告 | NVIDIA GeForce RTX 5070 Ti |
| コンピュートケイパビリティ | 12.0 |
| ストリーミングマルチプロセッサ | 70 |
| ブーストクロック | 2542 MHz |
| ツールチェーン | CUDA 13.3.1, ptxas V13.3.73 |
| カードが必要なもの | 理由 |
|---|
measure, probe-stalls | 命令のタイミングを計測し、依存関係が実際に何を必要とするかを壊して見つける |
scripts/roundtrip_corpus.py | すべてのコーパスカーネルを再スケジュールし、両バージョンを実行して出力バイトを比較する |
scripts/agreement_sweep.py | カーネルごとに 1 つの依存関係を短縮し、basalt が正しいかどうかをシリコンに問い合わせる |
工場出荷時のオーバークロックは測定結果を動かしません。ここでのすべてのレイテンシはサイクル単位であり、これはクロックではなくパイプラインの特性です。ブースト値がその横に記録されているのは、ウォールクロック比較を可能にするためだけです。ボードが影響するのは再現性であり、そのため basalt measure --board がそれを記録します。
| フィールド | ビット | 意味 |
|---|---|---|
stall | 108:105 | 次の命令を発行する前に待機するサイクル数 |
yield | 109 | ウォープスケジューラがウォープを切り替えてもよいというヒント |
write_barrier | 112:110 | ライトバック時に通知するスコアボード(7 = なし) |
read_barrier | 115:113 | オペランド読み出し時に通知するスコアボード(7 = なし) |
wait_mask | 121:116 | 発行前にクリアされている必要があるスコアボード |
reuse | 125:122 | オペランド再利用キャッシュフラグ。ソーススロットごとに1つ |
そのレイアウトは、実際に使うとすぐに正しさが裏付けられる。単純なカーネルでは、S2R は write_barrier=0 を設定し、その結果を消費する IMAD は wait_mask=0x01 を持つ。LDCU.64 は write_barrier=1 を設定し、それに依存する STG.E は wait_mask=0x02 を持つ。すべてのプロデューサとコンシューマのペアが一致し、nvdisasm が .reuse と注釈する命令には、対応する reuse ビットが設定されている。
CUDA のインストールも GPU も不要です。ツールチェーンスクリプトが固定版の再配布物(約45 MB)を取得します。管理者権限は不要で、PATH にも何も追加されません。```bash git clone https://github.com/sunnypatell/basalt.git cd basalt python -m venv .venv && source .venv/bin/activate # Windows: ..venv\Scripts\Activate.ps1 pip install -e ".[dev]"
python scripts/fetch_toolchain.py # pinned ptxas + nvdisasm python -m basalt.cli doctor # verify both oracles end to end python scripts/verify_all.py # every control in this README, in order
入力が空です。翻訳する内容が提供されていないため、翻訳を実行できません。```console
$ python -m basalt.cli doctor
ok toolchain V13.3.73 in third_party/cuda/13.3.1/bin
ok ptxas assembled sm_120a
ok cubin oracle 16 instructions with encodings
ok probe oracle 16/16 mnemonics round-tripped
both oracles healthy. no GPU required for anything above.
pip install basalt-sass は、CLI、ライブラリ、および3つの測定済みテーブルをすべてインストールし、
実行時の依存関係はありません。マシンに既にCUDAがある場合はこれを使用してください。上記のチェックアウトは、
CUDAがない場合や、測定値を再現したい場合に適しています。```bash
pip install basalt-sass
basalt doctor
basalt verify kernel.cubin
### Where it looks for `ptxas` and `nvdisasm`
basalt は両方を外部プロセスとして実行し、どちらも再配布しないため、コピーを見つける必要があります。
応答した最初のものが採用され、**CUDA 13 のインストールならどれでも構いません**: 特定の再配布版に固定されている必要はありません。
| 順序 | 場所 |
| ---: | :--- |
| 1 | `--cuda-bin`, コマンドラインで渡される |
| 2 | `BASALT_CUDA_BIN`, 両方のバイナリを保持するディレクトリ |
| 3 | `CUDA_PATH`, `CUDA_HOME` または `CUDA_ROOT`, それぞれに `/bin` を加えたもの |
| 4 | `PATH` 上の `ptxas` |
| 5 | チェックアウト内の `third_party/cuda/<version>/bin`, 新しいものから順に |
`basalt doctor` は、どのコピーが解決されたかを表示し、見つからない場合は非ゼロで終了します。そのため、単に読むためのものではなく、ビルドステップの前提条件として機能します。
命令データベースの照会にはツールチェーンは一切不要です。データベースは事前に測定され、パッケージ内に同梱されているためです:```bash
basalt isa --stats
basalt isa --opcode QMMA
命令データベースをゼロから再構築するか、コミット済みのものを照会してください:```bash python -m basalt.cli build-isa # harvest, probe, write src/basalt/data/isa/sm_120a.json python -m basalt.cli isa --stats python -m basalt.cli isa IMAD.WIDE.U32 # one form, with its measured field layout python -m basalt.cli isa --opcode QMMA # every form of one opcode
### あなたが書いていないマシンコードをチェックする
これは他にはない機能であり、GPUも引数も必要ありません。計測された
レイテンシモデルと抽出された要件テーブルは両方ともコミットされているため、新しいクローンは
生成元が何であれ、cubin を直接指すことができます:```bash
python -m basalt.cli verify kernel.cubin
The input content for this chunk is empty. No text was provided to translate. Please supply the actual Markdown content for chunk 17 of 29.```console $ python -m basalt.cli verify nvjpeg.sm_120.cubin 25 kernels, 0 with an error 7984 instructions in 789 blocks, 11580 dependencies checked across blocks: 0 errors, 3 warnings pair data: 3957 pairings from 25634 kernels, 427 producers with enough observations to use latency model: measured on NVIDIA GeForce RTX 5070 Ti
ライブラリのELFには数百のカーネルが含まれており、それぞれが個別にチェックされます。オフセットはゼロから再開し、あるカーネルから次のカーネルへは何も引き継がれないためです。ハザードが発生した場合に非零で終了するには `--strict` を追加します。これはビルドステップが求める動作です。sm_120 カードをお持ちで、このリポジトリ内のシリコンではなく、ご自身のシリコン上でモデルを測定したい場合は、以下のようにします。```bash
python -m basalt.cli measure -o my-card.json # needs a GPU, once
python -m basalt.cli verify kernel.cubin --latencies my-card.json
| コマンド | 機能 | GPUが必要 |
|---|---|---|
doctor | 両方のオラクルをエンドツーエンドで確認する | 不要 |
build-isa | ハーベストとプローブを行い、命令データベースを書き出す | 不要 |
isa | フォーム、オペコード、またはカバレッジを照会する | 不要 |
validate-isa | 測定されたフィールドを書き込めることを証明する | 不要 |
mine-stalls | コンパイラがスケジュールする内容からペアごとの要件を学習する | 不要 |
verify | cubinの制御ビットを調べてデータハザードを確認する | 不要 |
schedule | cubinの制御ビットをゼロから割り当て、結果を確認する | 不要 |
assemble | SASSテキストまたはcubin全体をエンコードし、読み戻して証明する | 不要 |
measure | 実シリコン上で命令レイテンシを計測する | 必要 |
probe-stalls | プログラムを意図的に壊して必要なストールを特定する | 必要 |
CLIが行うすべての処理はインポート可能で、実行可能な例を含むライブラリのインターフェースは
docs/API.md にあります。
そして、他のすべての結果の信頼性を支える2つのコントロールがあります。1つ目はカード(GPU)が必要で、2つ目は同梱のライブラリが必要で、ハードウェアは一切不要です:```bash python scripts/roundtrip_corpus.py # reschedule all 441 corpus kernels, run both on the GPU
python scripts/fetch_toolchain.py --libs # ~1.2 GB, no admin, nothing on PATH python scripts/audit_shipped.py --libs third_party/cuda/13.3.1/libs
[翻訳対象のMarkdownコンテンツが提供されていません。入力テキストを貼り付けてください。]```console
$ python -m basalt.cli verify kernel.cubin --latencies src/basalt/data/latency/rtx-5070-ti.json
kernel.cubin
32 instructions in 3 blocks, 23 dependencies checked: clean
latency model: measured on NVIDIA GeForce RTX 5070 Ti
ここに示す数値はツールによって出力され、クリーンチェックアウトから再生成されます。上記のコマンドが真実の源であり、以下の表はスナップショットです。
命令データベース。 すべてのエントリには、実際にアセンブルされたエンコーディングと、それを生成したコンパイラビルドが記載されています。
| 命令データベース | 数 |
|---|---|
| 命令フォーム | 345 |
| 異なるオペコード | 90 |
| 完全なオペランドマップを持つフォーム | 339 |
| テンソルコアフォーム | 46 |
| ビルドに使用 | ptxas V13.3.73 |
低精度ハードウェアはテンソル命令カバレッジに存在します:具体的には、HMMA と IMMA、非対称オペランドペアを含む FP8・FP6・FP4 型にわたる QMMA、ブロック単位の指数を保持するスケールファクタ形式 QMMA.SF と OMMA.SF、スパースな IMMA.SP、そして転置バリアントを含むすべての形状の行列移動命令 LDSM、STSM、MOVM です。
レイテンシ(RTX 5070 Ti 上)。 70 SM、すべてのフィットで R² ≥ 0.9998。依存チェーンのタイミングを計測して傾きを取ることで測定。チェーン長は推測ではなく、コンパイル済みの SASS から読み戻されています。
| 命令 | サイクル |
|---|---|
IMAD IADD3 FFMA FADD FMUL LOP3 SHF | 4 |
POPC | 18 |
I2FP + F2I together | 24 |
MUFU | 44 |
DADD DFMA | 64 |
そのうちの 3 つは、basalt が同梱していた推測モデルと矛盾しています:DADD は 48 と想定され、POPC は 4 と想定され、各変換は 6 と想定されていましたが、往復では 24 と測定されました。
推測されたレイテンシモデルは、測定されたモデルの小さな近似ではありません。それが測定する根拠のすべてです。
そして、ゼロの stall はゼロサイクルではありません。 これは、未解決の結果を待つ明確に安全なエンコーディングであり、スケジュールされた命令が 4 サイクルかかるのに対し、約 37 サイクルを要します。そのため、ptxas -O0 は完全にゼロ化された制御ワードを出力し、コードは依然として正しく計算されますが、おおよそ 9 倍遅くなります。
stall | サイクル/命令 | 結果 |
|---|---|---|
| 0 | 36.85 | 正しい |
| 1 | 4.88 | 誤り |
| 2 | 4.88 | 誤り |
| 3 | 5.88 | 誤り |
| 4 | 6.88 | 正しい |
コーパス内のすべてのカーネルについて、ベンダーコンパイラと一致します。 ptxas がコーパスからビルドするすべてのカーネルは、スケジューリングを行うすべての最適化レベルで、独自のスケジューリングと照合して検証されます:30,421 の依存関係、ゼロエラー。そのスイープはプッシュのたびに CI で実行され、このプロジェクトがこれまでに犯したすべてのモデリングエラーは、推論ではなくこのスイープによって捕捉されました。
判定はシリコンと一致します。 依存プロデューサー上のエンコード可能なすべての stall について、basalt の静的答えとハードウェアが実際に計算する結果は、ゼロの場合も含めて一致します。これはここで断言されるのではなく、テストとして保持されています。必要な stall を求める 3 つの独立した方法と、その過程で行われた修正を含む完全な証拠は、findings にあります。
そして、スケジュールが安全でないと判断した場合、シリコンも同意します。 233 個のカーネルに対するベンダー自身の動作スケジュールを取り、それぞれの実際の依存関係を 1 つ短縮し、basalt の判定を GPU が計算する結果と比較します:壊れていると判定された 79 個は壊れており、安全と判定されたものはどれも誤った答えを計算しませんでした。その数はゼロではなく 34 の見逃しから始まり、findings には原因と、修正にどれだけの誤報がかかったかが説明されています。なぜなら、最終結果だけを報告するスイープは、最初の結果を報告するスイープよりも価値が低いからです。
検証器は、スケジュールが安全かどうかに答えます。スケジューラは、同じ測定結果から、安全なスケジュールがどのようなものになるかに答えます:ptxas が生成したすべての制御ビットを破棄し、独自のものを計算し、その結果を検証器に渡し、GPU 上で同じカーネルのベンダーバージョンの隣で実行します。
カード上でコーパス全体に対して、スケジュールを生成するすべての最適化レベルで実行すると、比較可能な 439 個のカーネルすべてが、basalt 自身が割り出した制御ビットから、ベンダーのスケジュールとバイト単位で同一の結果を計算することがわかります。除外された 2 つはクロックとグリッド ID を読み取るため、それらは自分自身とも一致しません。findings は、それらをパーセンテージに含めるのではなく、その旨を述べています。
その制御こそが、他のすべてが信頼できる理由です。チェッカーとスケジューラは同じレイテンシモデルを読み取るため、モデル内の誤ったエントリは両方を同時に満たし、両方が間違っていながら互いに一致します。議論に利害関係を持たないのはシリコンだけです。手書きの 7 個のカーネルに対してスケジューラを実行したときは、長い間 7 個中 7 個が合格しました。300 個に対して実行したところ、41 個の誤りが見つかり、それ以降のすべてのモデル修正は、その数字が動くのを見ることから生まれました。
実際のバグはそのループから生まれました。プロデューサーとコンシューマーの間のウィンドウの外で費やされた stall は何の効果もなく、そこで費やすと、まだ短いプログラムで探索が終了します。安全なエンコーディングに固定された stall は、後のパスによって上書きされ、保証が小さな数に置き換えられていました。fp64 オペランドはレジスタペアを占有しますが、ニーモニックにはそれを示すものがないため、fp64 の依存関係の半分はチェッカーとスケジューラの両方から見えませんでした。命令のガードとして使用される述語は 13 サイクルを必要としますが、同じ述語をデータとして読み取る場合は 5 サイクルで済みます。ガードは命令が発行される前に解決されなければならないからです。さらに、スコアボードを待っても依存関係は完全には解決されません。プロデューサーはまだ独自の小さな stall を負っており、fp64 加算では 2 サイクルで、1 サイクル少ないと静かに間違った結果になります。これらのいずれも推論では見つかりませんでした。すべて、出力を実行して誤った数値を得ることで見つかりました。
[!NOTE] 1.0、その意味を具体的に。 完了していること:両方のオラクル、フィールドが書き込み可能であることが証明された命令データベース、実際の制御フローグラフに対するハザードチェッカー、3 つの独立した方法による 1 つの SKU でのレイテンシ測定、比較可能なすべてのコーパスカーネルをハードウェアにバイト単位で往復させるスケジューラ、そしてチェッカーが読み取るすべてのテーブルから除外された 2,762 個の出荷済みカーネルの監査。完了していないこと:構造上実行不可能な 12 個のコーパスカーネルと、ベンダー出力が決定的でない 2 個(すべて findings に記載)、10 個のオペコードは依然として測定値ではなく推測のレイテンシを保持しており、そのいずれも両コード群のプロデューサーになったことはありません。そして測定された GPU は 1 つだけで、finding 28 は、それが聞こえるほど重要ではないことを示しています。測定ではなく推測されたものがある場合、ツールはそれを事実に丸めるのではなく、その旨を明示します。roadmap と method を参照してください。
```
src/basalt/
toolchain.py Locating and driving ptxas / nvdisasm
encoding.py The 128-bit instruction word and its control fields
disasm.py Both oracles: cubin ground truth and raw-word probe
harvest/ PTX corpus generation and encoding extraction
probe/ Differential bit probing and field inference
isa/ The generated instruction database and its builder
asm/ The assembler, and the ELF reader that rewrites words in place
sched/ Assigning the control bits, and costing the result
verify/ Register def-use analysis, hazard model, latency checking
gpu/ Driver-API bindings and the latency measurement harness
src/basalt/data/ The measured tables, inside the package so an installed copy
has them: the ISA database, the latency model and the mined
stall requirement
docs/ Findings, method, the Python API, roadmap, artwork sources
scripts/ Toolchain fetch, asset rendering, drift check, and the two
hardware controls: the corpus round trip and the agreement sweep
tests/ Unit tests, plus toolchain- and GPU-marked suites
</details>
## クリーンルームの立場
basalt は、相互運用性を目的とした独立したクリーンルーム成果物です。NVIDIA のソースコード、ヘッダー、ライブラリ、ドキュメントを一切含まず、それらを再配布することもありません。公開配布された実行可能ファイルの挙動を観察し、それを記録します。これは、この種の作業が10年以上にわたって立脚してきた基盤です。
NVIDIA、CUDA、Blackwell は NVIDIA Corporation の商標です。このプロジェクトは NVIDIA とは提携しておらず、NVIDIA による推奨やスポンサー提供も受けていません。
[Apache-2.0](https://github.com/sunnypatell/basalt/blob/main/LICENSE) の下でライセンスされています。意図的に制限的なライセンスではなく Apache が選ばれています。誰にも構築を許されない正確性ツールは、誰も実行しない正確性ツールにすぎません。そして、ハードウェアにこれほど近い作業にとって、特許許諾は重要です。
## 貢献
最も価値の高い貢献は、basalt が誤ってエンコードするケースです。[`CONTRIBUTING.md`](https://github.com/sunnypatell/basalt/blob/main/CONTRIBUTING.md) と [ISAギャップテンプレート](https://github.com/sunnypatell/basalt/blob/main/.github/ISSUE_TEMPLATE/isa_gap.yml) を参照してください。このテンプレートは、あなたのマシンがなくても再現できる十分な情報を収集します。
[`SUPPORT.md`](https://github.com/sunnypatell/basalt/blob/main/SUPPORT.md) は質問の送り先を示し、[`GOVERNANCE.md`](https://github.com/sunnypatell/basalt/blob/main/GOVERNANCE.md) は変更が通過すべき基準を、[`RELEASING.md`](https://github.com/sunnypatell/basalt/blob/main/RELEASING.md) はリリースの切り方と検証方法を、[`SECURITY.md`](https://github.com/sunnypatell/basalt/blob/main/SECURITY.md) は非公開での報告方法をそれぞれ説明しています。
## basalt の引用
basalt が論文、ツール、モデル、バグ報告に役立った場合は、引用してください。GitHub は
[`CITATION.cff`](https://github.com/sunnypatell/basalt/blob/main/CITATION.cff) をネイティブに読み取るため、サイドバーの **Cite this repository** から
APA と BibTeX が転記なしで得られます。同じファイルは Zenodo や引用管理ツールが
解析するものであり、著者の権威ある記録です。
下記のキーは GitHub が生成するものなので、ここからコピーしてもサイドバーからコピーしても、
別々の作品のように見える2つのエントリではなく、同じエントリが得られます:```bibtex
@software{Patel_basalt_a_hazard_2026,
author = {Patel, Sunny},
license = {Apache-2.0},
month = aug,
title = {{basalt: a hazard checker, assembler and scheduler for NVIDIA consumer Blackwell (sm\_120)}},
doi = {10.5281/zenodo.22072811},
url = {https://github.com/sunnypatell/basalt},
version = {1.0.0},
year = {2026}
}
コンセプトDOI、10.5281/zenodo.22072811 を、バージョンDOIやこのURLではなく引用してください。これは最新リリースに解決されるため、再度編集されることなく常に正しい状態を保ちます。CITATION.cff に含まれているため、上記の両方の形式で既に利用できます。
測定済みテーブル(src/basalt/data/)を再利用する場合や図を再現する場合は、main ではなく、それらが由来するリリースを引用してください。数値は特定のコミットで scripts/verify_all.py によって再生成され、再現性を担保するのはタグです。
帰属表示は礼儀ではなくライセンス条件です。 Apache-2.0 §4は、LICENSE と NOTICE があらゆる再配布や派生作品に同梱されることを要求しており、NOTICE には著作者情報とクリーンルーム声明が含まれます。フォーク、ベンダーコピー、再パッケージ化されたホイールはすべて両方のファイルを保持します。
Sunny Patel · sunnypatel.net · github.com/sunnypatell