fullseye

GPU 最適化デザインパターン・カタログ(RTX 5090 / Blackwell sm_120 向け)

対象 GPU(確認済み): NVIDIA RTX 5090、Blackwell、compute capability sm_120、VRAM 32GB、driver 610.74。 現状(確認済み): torch 2.11.0+cpujax 0.7.1(CpuDevice)しか入っておらず、いま GPU では走らない。sm_120 は CUDA 12.8+ 世代のビルドが要る。 このカタログの性格: Web 検索は使わず、RAD コーパス(D:/docs/*_corpus_v2/、実在確認済み)+ 知識ベースで書いた。推測は「(推測)」と明示する。実コード(physarum_search.py / shapematch.py / afterman/eco_world.py)を読んで各ワークロードに紐づけた。

出典表記:


0. 我々の3ワークロードの構造(コード実測)

# ワークロード 計算の核 いまのボトルネック バッチ次元 精度要件
1 粘菌ソルバ physarum_search.py ラプラシアン L(D)p=b の線形ソルブ × 時間反復(伝導率 D を毎反復更新) dense n×n を毎反復 torch.linalg.solve(O(n³))。しかも毎反復 Atorch.zeros(n,n) で作り直す 多数の迷路 × 多数のパラメータ(μ, dt, D_init) fp64(コード実測: torch.float64 固定。ラプラシアンは条件数が悪くなりやすい)
2 形状マッチング shapematch.py テンプレートのエッジ勾配ベクトルと画像勾配の内積を、多数の位置 × スケール × 角度で評価 Python 二重ループ _scan_flat / _score_at(fancy-index の内積)。scale/角度も Python ループ 位置 × スケール × 角度 × 複数インスタンス fp32 で十分(勾配方向の内積。相関のダイナミックレンジは狭い)
3 Afterman 進化 afterman/eco_world.py 個体群の並列前進評価(RNN 政策) + 構造進化 すでに JAX で綺麗にバッチ化済(個体ごと重み w_in/w_rec/w_outeinsum("nij,nj->ni")lax.scan で T ステップ、jit(static_argnums=1)) 個体数 n(集団) fp32/bf16 で十分(進化 fitness は近似で足りる)

重要な非対称性: 3 番はすでに GPU-ready の書き方(SoA + batched einsum + scan)。1・2 は「Python ループ + 逐次 dense ソルブ」で GPU 化の伸びしろが最大。着手優先度は 1・2 が上、3 は wheel を入れれば jax.devices() が cuda になるだけでほぼ動く(詳細は §5)。


1. デザインパターン・カタログ

各パターン = 名前 / いつ使う / 落とし穴 / 我々のどれに効くか

並列の型

P1. Data-parallel(SIMT 素直な並列)

P2. Batched-kernel(多数の小問題を1カーネルにまとめる) ★最重要

P3. Warp 協調(shared memory + warp shuffle での縮約)

P4. パイプライン並列

メモリ階層

P5. Coalesced access(隣接スレッドが隣接アドレスを読む)

P6. Shared memory tiling

P7. Host↔Device 転送を減らす(結果だけ返す)★落とし穴の常連

P8. Occupancy(SM を空けない)

バッチ化の定石

P9. ループを batch 軸に畳む

P10. 相関/畳み込みの GPU 化(FFT vs 直接 vs im2col)

P11. 可変長を padding + mask

P12. AoS → SoA(構造体配列 → 配列の構造体)

数値ライブラリの使い分け

P13. 「既製 API → cupy/torch batched → Triton/CUDA を書く」の順で登る

P14. Tensor Core に乗せる(GEMM 化)

P15. カーネル融合(torch.compile / Triton / CUDA Graphs)

P16(落とし穴). dense 化でメモリ爆発

精度

P17. 精度の使い分け(fp64 が要る所と fp32/bf16/TF32 で足りる所)

反復ソルバの定石(1 に直結)

P18. Matrix-free(行列を作らず作用だけ与える)

P19. プリコンディショニング

P20. Warm start(前ステップ解を初期値に)★時間反復に直結


2. 落とし穴・チェックリスト(まとめ)

落とし穴 症状 対策 該当
小問題を1個ずつ GPU 投入 CPU より遅い batched-kernel(P2)でまとめる 1・2
反復中の .item()/float()/.cpu() GPU が毎反復待つ 収束判定を K 反復まとめ、history は device に貯める(P7) 1
dense A を毎反復確保 OOM / 帯域律速 疎 + matrix-free(P16/P18) 1
全 scale×角度×位置を同時 materialize VRAM 爆発 ピラミッドで段階化(P9) 2
安易な fp32 化 収束せず/経路が変わる 混合精度反復改良、fp64 基準と照合(P17) 1
動的形状で再コンパイル jit/compile が毎回走る 形状固定 + padding/mask(P11/P15) 2・3
warp 発散する分岐 実効並列度が落ちる バッチ全体で同じ枝(P1) 全部
Triton を書いてから既製で足りたと気づく 労力の無駄 ベースライン測定 → 段階的に登る(P13) 全部

3. 数値ライブラリ早見表

やりたいこと 第一候補 代替 出典
dense バッチ線形系 (B,n,n) torch.linalg.solve(バッチ対応) cuSOLVER batched, cupy.linalg [知識]
バッチ線形系(共有/個別 sparsity) torch-sla(cuDSS/CuPy/torch-iterative 自動ディスパッチ) cupyx.scipy.sparse.linalg.cg/spsolve [コーパス: arXiv 2601.13994]
疎 CG/BiCGSTAB + プリコンディショナ cupyx.scipy.sparse.linalg torch-sla iterative backend [知識/コーパス]
三角ソルブ(プリコンディショナ適用)を速く 既製で測る → 足りねばサブドメイン化 自作 Triton/CUDA [コーパス: arXiv 2508.04917]
相関/畳み込み(形状マッチ) F.conv2d(小テンプレ) FFT(大テンプレ)、im2col+GEMM [知識]
集団の並列前進 + scan JAX vmap/lax.scan/jit(3 は既実践) torch.vmap + torch.compile [知識]
乱数(集団・確率イベント) jax.random.split(3 は既実践、eco_world.py:244) torch.Generator per-stream [知識]
elementwise 融合が律速 torch.compile / Triton CUDA Graph(固定反復) [コーパス: mlops doc_0717/0521]
混合精度反復改良 fp32 内側 + fp64 補正(rescaling で fp16 も可) [コーパス: arXiv 2602.14450]
TF32 有効化(fp32 GEMM 高速化) torch.set_float32_matmul_precision("high") allow_tf32=True [知識]

JAX の要点(3 向け) [知識]:


4. CUDA ビルド導入メモ(調査のみ。実インストールはしない)

現状 torch 2.11.0+cpu / jax 0.7.1 CpuDevice。sm_120(Blackwell)は CUDA 12.8+ 世代が要る。以下は当たりであり、入れる前にリリースノートで sm_120 対応を確認すること。

PyTorch(推測ベース、要確認):

# 既存 CPU 版を外してから CUDA 12.8 wheel を入れる想定(バージョンは要確認)
py -3.11 -m pip uninstall torch
py -3.11 -m pip install torch --index-url https://download.pytorch.org/whl/cu128
# cu129 系が出ていればそちらの方が Blackwell 対応が新しい可能性(推測)

JAX(推測ベース、要確認):

py -3.11 -m pip install -U "jax[cuda12]"

共通の落とし穴(知識):


5. 「まず何から GPU 化すべきか」優先順位と根拠

着手順(費用対効果)

第1手: 粘菌ソルバ(1)の「dense 直接 → 疎 + matrix-free 反復 + warm start」への書き換え。ただし CPU/numpy でまず疎化して正しさを固定してから GPU。

第2手: 形状マッチング(2)の「Python 二重ループ → conv2d/im2col バッチ」化。

第3手: Afterman(3)は wheel を入れるだけ。コード変更はほぼ不要。

一言サマリ

最初の1手は「粘菌ソルバを疎 + matrix-free 反復 + warm start に作り替える(まず CPU で正しさ確定)」。 現状の dense O(n³)・毎反復再確保・毎反復同期という3重の構造欠陥を潰し、時間反復と warm start の相性・batched 疎 solve ライブラリ(torch-sla)の存在という追い風が全部そろっているため、GPU 化の投資回収が最も速い。


付録: このカタログで実在確認できた RAD コーパス出典

すべて D:/docs/numerical_methods_corpus_v2/D:/docs/mlops_corpus_v2/ 配下で grep により実在確認(ファイルパスは本文脚注のクラスタ)。

TF32/FP8/Blackwell sm_120 の具体・wheel バージョン・fp64 レートはコーパス外の知識ベース + 推測であり、実インストール時にリリースノート/実測で確認すること。 </content> </invoke>


付録2: 粘菌ソルバ GPU 化の実測(2026-08-26、RTX 5090 で実行)

上のカタログで挙げた「第1手」を実装し、実際に GPU(loco venv の torch 2.11.0+cu128、 CUDA 12.8、RTX 5090)で回した結果。packages(imgevolve ルート)の physarum_search.py / tests/test_physarum_search.py

やったこと(適用したパターン)

実測(honest)

| 規模 | CPU 逐次疎(基準) | GPU 最良(FP32+CUDA graph) | 倍率 | |—|—|—|—| | k=64 (n=4,096, B=16) | 27.9 s | 1.12 s | 24.9x | | k=128 (n=16,384, B=16) | 89.1 s | 1.09 s | 82.2x | | k=200 (n=40,000, B=16) | 230.7 s | 1.42 s | 162.3x |

残る手(未着手)