
2026/04/10 22:16
協働ベクトルの概要
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
核心となる進歩は、2021 年にニューラルネットワークの調査を開始したレンダリングフレームワークの進化であり、オフライン推論 전용のソリューションからグラフィックスアプリケーション内部でのリアルタイムトレーニングパイプラインをサポートする状態へ移行しました。当初、開発者は NVIDIA Tensor Cores や Intel Xe Matrix Extensions などのベンダー固有のハードウェアアクセラレータに依存しており、統一されたクロスプラットフォームシェーダインタフェースが欠けていました。これを解決するために、フレームワークは特別なベクトルおよび行列拡張——具体的には Cooperative Vector (NVIDIA) と Linear Algebra (DirectX)——を標準的な Cooperative Matrix 操作と並んで導入しました。これにより、コンピュートシェーダは単純なモデルから Neural Radiance Caching などの複雑なタスクまでを効率的に処理できるようになります。特に、新しい長ベクトルレイアウトはスレッドがブランチングを通じて独自のデータを処理できるようにし、最適化された行列レイアウトは推論乗算とトレーニング累積の区別を行いつつ、複数のディスパッチを必要としません。DirectX は関連機能を「Linear Algebra」の下で名前を変えていますが、Vulkan では Cooperative Matrix を標準拡張として維持し、Cooperative Vector を専用拡張として保持しています。この拡張されたフレームワークは現在、開発者がリアルタイム環境内で完全なトレーニングパイプラインを実行することを可能にし、以前はオフライン 전용のソリューションに限定されていた高度なマテリアル評価を促進しています。
本文
協同ベクトル:導入と簡易的歴史
2021 年、レンダリングエンジンにおけるニューラルネットワーク(NN)の活用事例を調査する取り組みを開始しました。当時は、まず「ニューラルマテリアル(NM)」というプロジェクトが成功に繋がりました。この NM は、当社が開発しているハイブリッドレンダラー内で実装され、UBO2014 由来のデータを用いて訓練されました。当初は推論(インференス)時のサポートだけであれば良かったため、NM の訓練は PyTorch を用いてオフラインで行われていました。当時の状況において、ハードウェア加速による推論をサポートするには、Vulkan 上の先行するベンダー固有のエクスパンション機能である「Cooperative Matrix」が必要でありました。そのため、当社はすべてのターゲットプラットフォームとバックエンドで展開できるよう、これらの拡張機能なしに Compute Shader(HLSL)のみを使用した独自の推論インフラストラクチャを構築しました。
時が経って 1 年が過ぎた頃、ニューラルレディアンスキャシング(NRC)から得られた印象的な成果を目にし、これには Runtime での訓練(主に幅 16, 32, または 64 の小さな)NN が必要となりました。その結果、当社のフレームワークは推論と訓練の両方のパイプラインをサポートするよう拡張されました。
Evolve Scene における NRC のキャプチャ
GPU は NN 推算を加速するための専用ハードウェアを搭載していましたが、シェーダーからこれら機能へのアクセス手段、特にクロスプラットフォームでのアクセス方法は存在しませんでした。例えば、デスクトップハードウェアにおいて各ベンダーごとの選択肢は以下の通りでした:
- NVIDIA Tensor Cores: 当時は CUDA を通じてのみアクセス可能でした。
- Intel Xe Matrix Extensions (XMX): ベンダー固有の機能でした。
- AMD: 「通常の」シェーダーコアを使用する Wave Matrix Multiply Accumulate(WMMA)命令を持っていました。
上記に言及した通り、
(tiled) マトリックスに対するマトリックス演算 へのアクセスが可能である場合、ハードウェア加速を利用するための抽象化として SPV_NV_cooperative_matrix という Cooperative Matrix エクステンション(現在は KHR に昇格)が導入されました。このエクステンションは、バッファを行列として解釈し、それらを乗算する新しいシェーダー命令を追加しました。同様に、DirectX 側でもシャドウモデル(SM)6.8 を対象として当初計画されていた非常に類似の機能である「WaveMatrix」が提案されましたが、これはプレビュー版として公開されるものの公式リリースには至りませんでした。
NVIDIA によるニューラルマテリアルおよびニューラルテクスチャ圧縮(NTC)に関する研究の結果、Optix および Vulkan エクステンション
VK_NV_cooperative_vector(協同ベクトル)としての機能実装が発表されました。NTC パーペラで提案されている解決策では、マテリアルの一連のテクスチャ(アルベド、法線、粗さ、金属性など)をニューラルネットワークおよび学習されたテクスチャのような表現に圧縮しています。
分岐データの課題
両者はいずれも興味深い課題を提示しました。つまり、各マテリアルが独自のネットワークを持つため、画面の隣接するピクセルが異なるテクスチャをサンプリングする状況となり、結果として異なるネットワークの評価、ひいては異なるセットの重みの評価が必要になります。これは、非分岐ワーク用に設計された Cooperative Matrix では現在まだ不可能です。
- 事例: NM における分岐評価において、3 つのマテリアルを描画するために 3 つのネットワークが必要です。
- 類似課題: NM でも同じ問題があり、異なるピクセルが異なる重みのセットを必要とする場合があります。
解決策:協同ベクトル
当初の実装においては、マテリアルへのクエリをバケット化し、各マテリアルごとに複数のディスパッチを実行する手法を採用しました。この解決策は理想的ではありませんが、実用上は機能します。これは手間のかかる複雑な手順ですが、理想としてはシェーダー内での単なるブランチ(分岐)として実現できるはずです。
協同ベクトルはこの課題を解決するため、Cooperative Matrix のような行列対行列(Matrix-Matrix)インタフェースから、ベクトル対行列(Vector-Matrix)操作へとインタフェースをシフトさせます。
NRC は図に示されている通り、より単純な状況でありながら、協同ベクトルからの恩恵を受けます。
- NRC の場合、各ピクセルには異なる入力パラメータ(法線 N、視線方向 V、粗さ R、アルベド A、スペキュラー f0 S など)が含まれます。
- NM と異なり、入力は同じネットワークに供給されるため、異なる重みや行列が不要です。
- このシナリオは、入力行列を入力ベクトルによって構成する点において、行列対行列乗算と同様にスケジュールされるため、パフォーマンス面における協同ベクトルのベストケース(最良の状況)となります。
(画像例: 各「ピクセル」に対して異なる入力ベクトルが提供されますが、これらは単一のネットワークに供給される NRC の様子)
リーダーボードであなたのポジションを主張しましょう!
協同ベクトルとは何か?
まず用語について整理しておきます:
- ロングベクトル(Long Vector): Dx/HLSL において、協同ベクトルまたはロングベクトルはデータ構造そのものを指します。混乱を防ぐため、今後は「ロングベクトル」という用語をデータ構造を指す際に使用します。
- 協同ベクトル: この用語は、ロングベクトルと動作する操作およびハードウェア加速機構全般を指して用います。
「協同(Cooperative)」という名称の由来は、ハードウェア加速の実装詳細にあります。波(Wave)内のスレッドが個別に提出するベクトル対行列乗算リクエストが、波全体で共同加速される行列対行列演算として統合されます。この名前は HLSL コード自体には現れず、あくまで「ベクトル型の定義」や「ベクトル対行列乗算」といった操作のみが使用されます(以下の例に示す通り)。
それ究竟是什么なのでしょうか?
HLSL におけるロングベクトルは、ただ単にシェーダーで慣れ親しんできた usual な 4 エレメントよりもはるかに長いベクトルデータ構造なのです。それ以上のことはありません。これらは透過的なデータ構造であり、ユーザーは以下のように扱うことができます:
- インデックスを用いて個別のエレメントを読み書きする。
- ベクトルに対して加算、乗算、最大値演算(ReLU など)などの操作を行う。
見た目からは、これらのベクトルのレジスタは VGPR(ベクトル汎用レジスタ)として直接格納され、ハードウェア加速が利用可能であっても特殊なレジスタには格納されていないことがわかります。単一のレーン(スレッド)の観点からすると、フルサイズのロングベクトルは VGPR に格納されます。
スレッド/実行モデル
協同ベクトルとは何かが理解できましたが、これらはどこで利用可能でしょうか?
- 現時点では、Vulkan および DirectX の両方で、すべてのシェーダーステージでアクセス可能ですが、主に Compute Shader で使用しています。
- 分岐データをサポートするための手段を提供するという観点から、ピクセルおよび Compute Shader では、各ピクセルまたはスレッドが独自のロングベクトルを保持します。
実装上の最も一般的な方法であり、実用的に見つかった最も効率的な方法は、各スレッドに独自のロングベクトルを持たせることです。また、ロングベクトルを共有メモリアrea に格納することも可能です。
重要な注意点:
- ロングベクトルは宣言されたインボケーション(スレッド)に属するか、共有メモリに格納されます。
- 機能性を確保するために一意的な制御フローや完全occupied なウェーブを必要としません。
- 反面、ユニフォームパスを使用することで、ドライバによる高速パスが利用可能となり、パフォーマンスが向上します。また、シェーダー実行順序変更(SER)などの機能がそれをサポートします。
マトリックス
マトリックスには 2 つの種類があります:
プレインレイアウト
- Row Major(行優先)
- Column Major(列優先)
オプティマルレイアウト
- MulOptimal (推論向け)
- OuterProductOptimal (訓練・蓄積向け)
シェーダー内でのアクセシビリティ
Vulkan および DirectX の両方から、バッファなどのメモリアドレスを指し示すことができるインタフェースが提供されており、これをマトリックスとして利用できます。
- プレインレイアウト: プレインレイアウト(行優先/列優先)の場合、データ型、マトリックスサイズ、レイアウトが既知であればエレメントにアクセス可能です。
- オプティマルレイアウト: しかし、オプティマルレイアウトの場合、メモリアドレスは完全に不透明です:
- レイアウトはドライバによって定義されるため、特定のエレメントへの読み書きを行うことができません。
- 最後に、オプティマルレイアウトではストライド(stride)をゼロにしなければなりません。これにより、ユーザーがインデキシングで各エレメントにアクセスすることは防止されます。このアプローチは、テクスチャタiling と類似した最適化手法です。
主要な違い
- プレインレイアウトのロングベクトルおよびマトリックスは 透過的(Transparent) です。
- オプティマルレイアウトのマトリックスは 不透明(Opaque) です。
考え方は、ユーザーがシェーダー内で自身のロングベクトルを手動で埋めるという点にあります。例えば、ウェーブ内では各スレッドが異なる UV 座標、視線方向、法線などを備えた独自のロングベクトルを保持します。これらのロングベクトルは、そのシェーダー内で直接修改してはいけません固定されたマトリックスと乗算されます。
エンタープライズオファリングについてご興味を持たれていますか? ハードウェアベンダー、スマートフォンメーカー、OEM、ボードパートナーなどに対して、最適なパフォーマンスの実現をご支援しています! お問い合わせ
評議員会メンバーシップとアート・ソースコードアクセス
ネットワークの推論と訓練
最も単純なニューラルネットワークの一つである多層パーセプトロン(MLP)は、線形レイヤーと活性化関数のシーケンスとして構築されます。各レイヤーの計算は、単一の行列対行列またはベクトル対行列演算、バイアスの加算、そして ReLU などの活性化関数の適用によって実行できます。
推論
1 レイヤーの実行:$x$ は入力ベクトル、$\theta$ は重み行列、$b$ はバイアス、$h$ は活性化後の結果を表します。推論では、重み行列に対して行優先/列優先レイアウトまたは MulOptimal(推論オプティマル)のいずれかを使用できます。当然ながら、過半数のケースではマルチプライ最適レイアウトの方が高速であるため推奨されます。実験では、小型マトリックスであっても有意な違いが確認されました。
MulOptimal マトリックスの埋め方: MulOptimal マトリックスに正しいデータを埋めるためには、まずデータを行優先/列優先レイアウトに書き込み、その後行列変換によってオプティマルレイアウトに変換する必要があります。ここで注意すべきは、
ID3D12Device::GetLinearAlgebraMatrixConversionDestinationInfo を使用してオプティマルレイアウトのマトリックスを割り当てる前に、CPU 側で宛先のサイズをクエリしなければならない点です。これは、サイズが実装依存(ベンダー、ドライバなど)であり、予想より多くのメモリを必要とする可能性があるためです。このクエリと割り当てが行われれば、ID3D12GraphicsCommandList::ConvertLinearAlgebraMatrix を用いて変換を実行できます。
- 注: この変換は本質的に、データをハードウェアが好むフォーマットに並べ替えるコピー操作です。
推論は MatMul(または MatrixVectorMul)、あるいは MatMulAdd によって行われます。後者はバイアスとして別のロングベクトル(Dx 側)またはマトリックス(Vulkan 側)を受け入れます。
訓練
ネットワーク最適化のための勾配計算。単一レイヤーの訓練には、入力に関する勾配 ($\nabla x$)、重みに関する勾配 ($\nabla \theta$)、およびバイアスに関する勾配(オプション:$\nabla b$)の 3 つを計算する必要があります。レイヤー出力 $h$ に関する損失関数の勾配 $\nabla h$ を計算した後、これを後方伝播させ、協同ベクトルを用いて以下の勾配を計算できます:
-
入力に関する勾配 ($\nabla x$):
- これには、 incoming グラデーション $\nabla h$ を転置した重み行列 $\theta^T$ で乗算する処理が必要です。
- 幸运的是、MatMul 演算は MulOptimal(推論オプティマル)レイアウトに対して転置フラグをサポートしているため、重みの別個の転置コピーを保持する必要はありません。
-
重みに関する勾配 ($\nabla \theta$):
- これは $\nabla h$ と入力 $x$ の外積(outer product)として計算できます。
- ここで
が用いられ、バッチ全体にわたって勾配を蓄積します。ここでいう各バッチ行は協同ベクトルです。OuterProductAccumulate - これを行列乗算でも計算可能ですが(一部のシナリオではより効率的である可能性もある)、今回は協同ベクトルが提供するすべての機能を活用することに焦点を当てています。
-
バイアスに関する勾配 ($\nabla b$):
- バイアスが存在する場合、その勾配はサンプル全体にわたって蓄積された $\nabla h$ に等しくなります。
- これには
を用いた協同ベクトルを使用でき、これは単純な原子性加算操作です。VectorAccumulate
OuterProductOptimal レイアウト: もう一つのオプティマルレイアウトである OuterProductOptimal(訓練または外積オプティマル)は、本来行優先/列優先からオプティマルへの明示的な変換を必要としません。これは通常、重みの勾配を格納するために使用されるためです。一方、このレイアウトを使用する場合、最終的に OuterProductOptimal から読みやすいいわゆる行優先/列優先レイアウトに勾配を変換する必要があるでしょう。
OuterProductOptimal は OuterProductAccumulate 関数(Vulkan 版は coopVecOuterProductAccumulateNV)と併用されます。これは 2 つのベクトルを受け取り、外積を計算してマトリックスを生成します。このマトリックスは、ターゲットマトリックスに蓄積され、このターゲットマトリックスは OuterProductOptimal レイアウトでなければならない のです。
- この操作は本質的に原子性加算/蓄積であり、各エレメントがターゲットマトリックスの対応するエレメントに対して原子性地追加されます。
- 訓練データセット内のすべてのバッチについてこれを完了した後、OuterProductOptimal から読みやすいレイアウト(行優先/列優先など)への変換操作を行ってデータをコピーして移動することができます。
マトリックスレイアウト変換パイプライン
残された課題は、学習率を掛け合わせた勾配を加算し、前の重み(行優先/列優先)を更新することです。注意すべきは、この行列対行列演算は現時点では協同ベクトル内部機能では不可能であるということです:
- 行列対行列操作へのサポートは、DirectX の将来のリリースで計画されています。
- Vulkan 側にはこれに似た Cooperative Matrix という機能が存在しますが(現時点ではオプティマルレイアウトや協同/ロングベクトルと互換性がなかったようです)。
現在は、これを CPU でまたは通常のシェーダーコードで処理する必要があります。これが行優先/列優先レイアウトに移られた後、推論時に使用できるように再度 MulOptimal への変換を行うことができます。
API 変更に関する注記
- DirectX: Cooperative Vector プロポーザルを撤退し、代わりに異なる名称「Linear Algebra」の下にこれらの機能を統合して実装する方針に変更されました。「Linear Algebra」は協同ベクトルと協同行列を組み合わせたものです。この記事で議論された内容自体は、Linear Algebra 導入後も基本的に有効ですが、API や名称がやや異なっている点にご注意ください。
- Vulkan: Cooperative Matrix が KHR に昇格しましたが、Cooperative Vector は引き続き NVIDIA 独自エクステンションです。