システム言語がGPUへ進出:Zig SPIR-Vバックエンドの野望

システム言語がGPUへ進出:Zig SPIR-Vバックエンドの野望

ZigSPIR-VGPUコンパイラシェーダーシステムプログラミング

データソース:Lobsters

2026年6月26日、Zig開発ログに「SPIR-V Backend Progress」と題するエントリが登場した。著者はAli Cheraghi、ZigコンパイラのSPIR-Vバックエンドの中核的コントリビューターだ。これは「SPIR-Vバックエンドが使えるようになりました」というマイルストーン記事ではない——むしろ逆で、bitrot(コード腐食)、シングルスレッド制限、わずか49%の動作テスト通過率について、多くの紙幅が割かれている。しかし同日、このログはLobstersのトップページ28ポイントに押し上げられ、3件のコメントはすべて興奮を表現していた。

筆者はこの興奮の源泉を理解しようと試みた。セルフホストコンパイラのバックエンド、動作テスト通過率は半分に満たず、メインブランチへのマージ後に複数箇所で破損し修復に数週間を要した——伝統的なソフトウェアデリバリーのどの基準から見ても、これは「初期実験」に分類されるべきものだ。コミュニティはそこからまったく異なるシグナルを読み取った。システムプログラミング言語がGPU領域に橋頭堡を築き始めたのだ。

SPIR-Vの位置付け

このシグナルを理解するには、まずGPUエコシステムにおけるSPIR-Vの位置付けに立ち戻る必要がある。

SPIR-VはKhronosグループが定義したバイナリ中間表現(IR)であり、Vulkan、OpenCL、OpenGLにサービスを提供し、近い将来DirectXもこれを消費することになる。その核心的設計目標はシンプルだ。シェーダー/計算カーネルのコンパイルをドライバから取り出し、アプリケーション側に置くこと。SPIR-Vが登場する以前、GPUプログラミングの標準経路は——GLSLやHLSLでソースコードを書き、ドライバのランタイムコンパイルに委ねる——というものだった。ドライバ内蔵のコンパイラの品質はまちまちで、ベンダーやドライババージョンによってコンパイル結果が異なりうる。SPIR-Vはこの分業を変えた。言語フロントエンドが仕様に準拠したSPIR-Vバイナリを生成する責任を負い、ドライバは単にそれをGPU ISAに変換するだけだ。コンパイラの責任がドライバから言語ツールチェーンへと移ったのである。

この一手の移動が意味するのは、準拠したSPIR-Vを生成できるあらゆるコンパイラフロントエンドが、GPUプログラミングの入り口になりうるということだ。GLSLはもはや必要ない。HLSLももはや必要ない。Vulkan仕様そのものは、あなたのSPIR-VバイナリがGLSLからトランスパイルされたものであれ、C++、Rust、Julia——あるいはZig——から直接コンパイルされたものであれ、気にしない。

これこそが、コンパイラバックエンドがSPIR-Vを出力できることの重要性だ。汎用プログラミング言語のコンパイラが直接GPUコードを生成できる——シェーダー言語と汎用言語の境界が曖昧になり始める。

Zigのバックエンドはどこまで到達したか

2026年6月26日の開発ログは五つの次元の進捗をカバーしている。筆者は工学的重要性の順に並べる。

第一に、@SpirvType組み込み命令。 SPIR-VにはZigの型システムに直接対応しない型がいくつかある——サンプラー(sampler)、イメージ(image)、サンプルドイメージ(sampled image)、ランタイム配列(runtime array)。これまではこれらの型をインラインアセンブリで手書きのSPIR-V命令によって表現するしかなく、これは長年「シェーダーを書く際の最大の障壁」とされてきた。@SpirvTypeはGPU専用型をコンパイラが認識する第一級の概念へと引き上げ、コード内でZigの構文を使ってサンプラーを宣言し、descriptor setとバインディングポイントに結びつけることができる——これは「SPIR-V命令を生成できる」から「Zigで自然にシェーダーを書ける」への決定的な飛躍である。

第二に、実行モードが呼び出し規約によって担われるようになった。 ワークグループサイズ、フラグメント原点、メッシュシェーダーパラメータ——これらの実行モード情報は、これまでインラインアセンブリのOpExecutionModeを通じて手動で挿入されていた。新しい設計では、関数の呼び出し規約を callconv(.{ .spirv_kernel = .{ .x = 8, .y = 8, .z = 1 } }) と宣言すれば、コンパイラが自動的に正しい実行モードを導出する。同時に spirv_taskspirv_mesh という二つの新しい呼び出し規約が追加され、メッシュシェーディングパイプラインをサポートする。ユーザー側から見れば、コンピュートシェーダーのエントリ関数を宣言することが、通常のエクスポートされるZig関数を宣言するのと同じくらい自然になった。

第三に、マルチスレッドコード生成。 SPIR-Vバックエンドは初日からリンカスレッド内でシングルスレッド実行されていた。今回のリファクタリングで、コンパイラの統一されたMIR → コード生成パイプラインに統合され、各コード生成タスクは他のセルフホストバックエンドと同様にスレッドプールにスケジュールされる。同時に dedup_types(重複型命令のマージ)と prune_unused(デッドコードの削除)の二つのISelパスも復帰した——これらのパスは以前のシングルスレッドリファクタリングで削除されていたが、今回のアーキテクチャアップグレードにより復元された。ユーザーへの実際の影響はコンパイル速度だが、工学的判断にとっては、SPIR-Vバックエンドがアーキテクチャレベルで「特別扱い」状態を脱し、他のターゲットと同格のコンパイルユニットになったことを意味する。

第四に、オブジェクトファイルリンク。 .spv ファイルがオブジェクトファイルフォーマットとして認識されるようになった。複数の .zig ファイル(あるいは外部 .spv オブジェクト)をコンパイルした後、SPIR-Vリンカがそれらを単一モジュールに縫合できる。これは大規模なシェーダープロジェクトを複数のコンパイルユニットに分割でき、理論上はインクリメンタルコンパイルやライブラリ配布をサポートすることを意味する——現在これらの高度なワークフローはまだ準備段階だが、フォーマットレベルの基盤は敷かれた。

第五に、ケーパビリティと拡張がCPUフィーチャーセットから駆動されるようになった。 これまで OpCapabilityOpExtension はコード生成またはインラインアセンブリによってアドホックに挿入されていたが、今後はSPIRV-Headersから依存チェーンを抽出し、CPUフィーチャーセットによって統一的に管理される。アセンブラはこれらの命令を手動で挿入しようとするいかなる試みも拒否する——コンパイラは出力の正当性に対してシステムレベルの責任を負い始め、検証を下流の spirv-val ツールに押し付けなくなった。

4週間前と比較して、動作テスト通過率は約39%から49%(spirv64-vulkan ターゲット)に向上し、数十のバグが修正され、std.gpustd.spirv に改名された。Cheraghi自身の表現は抑制的だ。「SPIR-Vバックエンドは1ヶ月前よりも意味のある形で使いやすくなったが、まだ遠い道のりだ」

競合マップの中に位置付ける

Zigは汎用言語からGPUに到達しようとする唯一のプロジェクトではない。主要な競合を並べることで、Zig SPIR-Vバックエンドの位置をより正確に特定できる。

Rust GPU(rust-gpu) は最も直接的な参照対象だ。rustc_codegen_spirv に基づき、RustをSPIR-Vシェーダーにコンパイルする。プロジェクトは2019年頃に始まり、Embark Studiosの支援とコミュニティへの移管を経た。現在は基本的に使用可能な標準ライブラリサブセット(spirv-std)、ブラウザで遊べるSHADERedデモ、リンク時最適化のための実験的SPIR-Tフレームワークを持つ。しかしGitHubのissueやコミュニティの議論から見ると、Rustコンパイラのアップグレードがcodegenプラグインの追随対応を必要とすることが多く、安定版はまだ登場していない。

Circle C++ Shader Compiler は標準C++でシェーダーを書くことを可能にし、属性マーカーでGPUエントリを区別し、コンパイル産物は直接SPIR-Vになる。構文レベルではCUDAに近い——単一ソース、C++スーパーセット。しかしCircleはクローズドソースのコンパイラであり、Sean Baxter個人のメンテナンスに依存し、エコシステムの範囲は限られている。

Julia GPU はCUDA.jlとAMDGPU.jlを通じてGPUプログラミング機能を提供し、低位層ではSPIR-Vを迂回して直接PTXまたはAMDGCN命令を生成する。強みはインタラクティブ開発——REPLで即座にカーネルを書き、実行できる。弱みも明らかだ。クロスベンダーの可搬性は標準IRではなくパッケージエコシステムに依存する。

Zig SPIR-Vバックエンドのこのマップ上の位置は極めて具体的だ。それはSPIR-Vをコンパイラのセルフホストバックエンドとして持つ唯一のシステムプログラミング言語である——rust-gpuはRustコンパイラの外部codegenプラグインであり、Rustプロジェクトの第一級コンポーネントではない。Circleはクローズドソースの個人プロジェクト。JuliaはSPIR-Vを迂回している。ZigのSPIR-Vバックエンドはx86、ARM、RISC-Vバックエンドと同じコードリポジトリ、同じビルドシステムの中でメンテナンスされ、同じコアコントリビューターグループによってレビューされる。

これは両刃の剣だ。コンパイラのメインラインとリポジトリを共有することは、SPIR-VバックエンドがZigコンパイラのアーキテクチャ調整のたびに受動的に進化することを意味する——bitrotはこの密結合の代償である。しかしそれはまた、コンパイラインフラへのあらゆる改善(型システム、コード生成パイプライン、リンカ)が自動的にSPIR-Vバックエンドに恩恵をもたらす可能性をも意味する。6月26日のログにおけるマルチスレッドコード生成の回復は、まさにこのメカニズムの具体例だ。統一MIRパイプラインのアーキテクチャ決定が、SPIR-Vバックエンドに「無料で」スレッドプールスケジューリング能力をもたらしたのである。

本当の障壁はコンパイラの中にはない

技術ロードマップから見れば、Zig SPIR-Vバックエンドの前に立ちはだかる最大の障壁は、完全にコンパイラ内部にあるわけではない。

第一の障壁はアドレス空間だ。GPUのメモリモデルはglobal、local、private、constantなど複数のアドレス空間を区別するが、Zigのポインタはデフォルトでgenericアドレス空間を指すと仮定している。Cheraghiのブログは、Vulkanが OpPtrCastToGeneric をサポートしていないことに言及している——したがって現在の実装では、すべてのポインタをFunctionストレージクラスと仮定する暫定案が採られている。これは複雑なポインタ操作(アドレス空間を跨ぐ参照の受け渡しなど)がVulkanターゲット下で制限されることを意味する。OpenCLターゲットでは状況はやや良好だ。OpenCLのベースライン環境がより多くのケーパビリティを保証するため、動作テスト通過率もより高い(約75%)。

第二の障壁は数値セマンティクスの差異だ。Vulkan環境下では fmasqrtexplog などの命令が正しい丸めを保証しない——これはZigコンパイラのデフォルトの数値セマンティクス仮定と衝突する。Zigの決定性への要求は、シェーダー言語が数値精度に対して持つ典型的な許容度よりも高い。これは必ずしも解決不可能な問題ではない——Rust GPUもGLSLコンパイラも同じセマンティクスのギャップに直面してきた——しかし明示的な設計判断と文書化が必要であり、現在も進行中である。

第三の障壁はエコシステムのレベルだ。標準ライブラリの適合。GPU上にはOSもファイルシステムも、(伝統的な意味での)ヒープアロケータも存在しない。Zigの標準ライブラリにはこれらの仮定に依存するコードが大量にある。std.mathstd.sort、一般的なデータ構造とアルゴリズムをGPUフレンドリーなサブセットに移植することは、コンパイラバックエンドそのものに劣らぬ規模の作業だ。Cheraghiは「次のステップ」リストにプレフィックスサム、リダクション、行列乗算などの基礎アルゴリズムを挙げている——これらはHPCおよびMLワークロードの礎石であり、優先順位の判断が正しいことを示す一方、進捗がまだ初期段階にあることも示している。

なぜこのログが注目を集めたのか

Lobstersの28ポイントの投稿に立ち戻ろう。技術的詳細を超えた興奮感には二つの源泉がある。

一つの源泉はタイミングマーカーだ。同じ日、Zig開発ログにはもう一つの更新——Matthew Luggによる「New @bitCast Semantics and LLVM Backend Improvements」——があり、Lobsters上で単独で16件のコメントを集めた。一日に二つのZigコンパイラ進捗がランクインするのは、Lobstersのようなコミュニティでは常態ではない。これは言語エコシステムの活発さを示唆している。Zigコンパイラは同時に複数の次元で前進している——整数デグレード、bitCastセマンティクス、LLVMバックエンド最適化、SPIR-Vバックエンド修正——これは単一の経路でのみ反復するプロジェクトではないのだ。

もう一つの源泉は方向性シグナルだ。SPIR-Vバックエンドの存在そのものがこう語っている。Zigのメンテナたちは、システムプログラミング言語がGPUコードをコンパイルできるべきだと考えている。49%の通過率ではまだ「我々もGPUをサポートしています」と言うことはできないが、これはGPUがシステムプログラミングの正統な領土であるという宣言なのだ。

この方向性はRustのGPU物語とは異なる。Rustの安全哲学がGPU上で持つ差別化された価値は明確だ——所有権システムはコンパイル時にデータ競合を防ぐことができ、高度に並列なGPUプログラミングモデルにおいて天然の優位性がある。Zigの価値提案は異なる。暗黙のアロケーションがないこと、コンパイル時計算が同一言語であること、制御フローへの明示的管理。GPU上で暗黙のアロケーションがないことは、存在しないヒープアロケータへの呼び出しを誤ってトリガーしないことを意味する。comptimeはワークグループ分配戦略、メモリレイアウト、アンロール係数をGPUフィーチャーセットに基づいてコンパイル時に動的に決定できることを意味する——マクロもコード生成スクリプトも不要だ。

どちらがGPUプログラミングにより適しているか?筆者には答えを出す立場にない。両言語のGPUへの挑戦はいずれもあまりに初期段階であり、データの貧しさはいかなる比較的結論も支持しない。しかしエコシステムの多様性の観点からは、哲学の異なる二つのシステム言語が同時にSPIR-Vを攻めていることは、一方だけの場合よりも良い。

謙虚な声明

本稿の分析は2026年6月26日のZig開発ログ、Ali Cheraghiの「Zig and GPUs」ブログ記事、Lobstersコミュニティの議論、およびKhronos SPIR-V仕様の公開文書に基づいている。筆者はZigコンパイラへの貢献に参加しておらず、spirv64-vulkan ターゲット下で自らシェーダーをビルド・実行したこともない。文中で引用した49%の動作テスト通過率などのデータは開発ログ著者の自己申述によるもので、独自の検証は行われていない。Rust GPU、Circle、Julia GPUの現状に関する記述は公開リポジトリ、コミュニティ議論、学術論文に基づいている——各プロジェクトの実際の可用性は利用シナリオによって大きく異なる可能性がある。上記のいずれかの領域で直接的な工学的経験をお持ちであれば、本稿の限界を指摘していただけると幸いである。