松田研究室
FindingID: c32-gsplat-smoke
Status: stable / task A.3
← Findings Index
Phase 2a · gsplat V100 smoke

c32 V100 gsplat smoke — NFS 共有 env を異 sm 機へ持ち込み JIT 再 build 1 回で動作確認

Phase 2a。c33 (A6000, sm_86) で構築した gsplat-env を NFS 経由で c32 (V100, sm_70) に持ち込み、TORCH_CUDA_ARCH_LIST=7.0 で JIT 再 build (93s) → Lego 1k iter / 10.5s / val PSNR 19.81 dB。c33↔c32 間の env 共有運用が成立することを smoke で確認。

positiverank: midaccepted第 2 軸phase-2gsplatv100c32cudasmokenfsjit
Δ PSNR
19.81
Δ Wallclock
10.5s / 1k step
Δ Splats
10000 → 10522
Impact
NFS 共有 gsplat-env を異 sm 機 (c33 sm_86 → c32 sm_70) に持ち込み、TORCH_CUDA_ARCH_LIST=7.0 で JIT 再 build 1 回 (93s) → 即動作。Lego 1k iter で wallclock 10.5s / val PSNR 19.81 dB。30k full は Phase 2b。
01

本文

c33 (A6000, sm_86) で構築済の gsplat-env (NFS 共有ホーム) を c32 (Tesla V100-PCIE-32GB, sm_70) で そのまま activateTORCH_CUDA_ARCH_LIST=7.0 指定で JIT 再 build を経て NeRF Synthetic Lego を 1k iter 学習。train wallclock 10.5s / val PSNR 19.81 dB、env 共有運用と異 sm 切替が smoke で成立。

実施日
2026-05-23
対象機
matsudalab-c32 (compute-0-32, V100-PCIE-32GB × 2, driver 530.30.02, CUDA 12.1)
GPU 占有
GPU0 = 他ユーザ 100% util、GPU1 = 0% util / 32 GB free → CUDA_VISIBLE_DEVICES=1
env
~/miniconda3/envs/gsplat-env (NFS 共有、c33 構築済)
torch / gsplat
torch 2.4.1+cu121 / gsplat 1.5.3
sm
7.0 (V100) — TORCH_CUDA_ARCH_LIST=7.0 で JIT、初回 92.9s
dataset
~/datasets/nerf_synthetic/lego (NFS、c33 経由 rsync)
trainer
scripts/gsplat_lego_smoke.py (自前 Blender adapter)

TL;DR

項目
train wallclock10.5 s / 1000 step (≈95 step/s)
eval PSNR (val)19.81 dB (N_val=100)
init / final gauss10000 → 10522 (DefaultStrategy で +500、step 500 から refine 開始)
statussmoke 成功

c33 (NFS 共有 env) → c32 (異 sm) は JIT で再 build 1 回 + 即動作、追加 setup 不要。

1. rsync (Step 1)

ローカル m3 mac (/Users/otkrickey/dev/3dgs-workspace/datasets/nerf_synthetic/lego/、111 MB、309 ファイル) を c33 の NFS 共有ホーム ~/datasets/nerf_synthetic/lego/ へ。

rsync -avh --ignore-existing --progress \
  /Users/otkrickey/dev/3dgs-workspace/datasets/nerf_synthetic/lego/ \
  matsudalab-c33:~/datasets/nerf_synthetic/lego/
# → sent 116.28M bytes  received 5.91K bytes  10.11M bytes/sec  total 11.2s

NFS 共有ホームなので c32 (compute-0-32) から そのまま ~/datasets/nerf_synthetic/lego/ で見えるinit.ply も含めて 112 MB が見えた。

dataset 欠損 (要 follow-up)

transforms_test.json は 200 frame 参照だが、ローカル lego/test/164 frame が欠損 (r_0.png も含めて存在しない)。train (100 / 100)、val (100 / 100) は完整。今回の smoke は val で eval (Lego val は train と同一カメラ分布なので bench としてはやや甘い)。Phase 2b 30k full では nerf_synthetic.zip をオリジナル DL ソースから取り直すか、test/ のみ別途回収する必要あり。

2. gsplat trainer (Step 2)

blocker: simple_trainer.py は Blender 未対応

nerfstudio-project/gsplat HEAD (b5392fe) の examples/simple_trainer.pyCOLMAP / NCore データセットのみ対応で、NeRF Synthetic (transforms_*.json + RGBA PNG) を直接 load できない (advisor 経由で確認、examples/datasets/ に colmap.py / ncore.py のみ存在、examples/benchmarks/ にも Blender 用 script 無し)。

選択肢: (a) gsplat 旧 tag に戻す、(b) COLMAP 変換 (ns-process-data)、(c) 薄い Blender adapter を自作。本卒研は将来 wallclock 比較を細かく整えるため (b)/(a) は捨て、(c) の 200 行スクリプトで gsplat.rendering.rasterization + DefaultStrategy を直叩きする minimal trainer を書いた。

adapter: scripts/gsplat_lego_smoke.py

  • NeRF Synthetic の OpenGL カメラ規約 (y-up, z-back) を OpenCV 規約 (y-down, z-fwd) に変換 (diag(1,-1,-1,1) を c2w に右乗算)
  • RGBA を white background へ alpha compose (rgb*α + (1-α)、Kerbl baseline 慣例)
  • intrinsics は camera_angle_x から fx = 0.5 * W / tan(0.5 * angle)
  • init は init.ply (10k points、scripts/gen_init_ply.py 形式) を直接 load
  • sh_degree=3 (K=16)、L1 loss のみ (SSIM 無し)、DefaultStrategy 既定値
  • 6 optim group (means / quats / scales / opacities / sh0 / shN)、Adam 既定 lr

実行

ssh matsudalab-c32
source ~/miniconda3/etc/profile.d/conda.sh && conda activate gsplat-env
export CUDA_VISIBLE_DEVICES=1
export TORCH_CUDA_ARCH_LIST='7.0'   # V100 (sm_70)
python ~/gsplat_lego_smoke.py \
  --data-dir ~/datasets/nerf_synthetic/lego \
  --result-dir ~/runs/gsplat-lego-1k-smoke \
  --max-steps 1000

JIT build (1 回目だけ)

gsplat: CUDA extension has been set up successfully in 92.89 seconds.

TORCH_CUDA_ARCH_LIST=7.0 で sm_70 用に JIT。c33 でビルド済の sm_86 cache は再利用されず、約 93 秒で sm_70 用 .so が ~/.cache/torch_extensions/... に生成された (NFS 共有なので c32 専用キャッシュとして残る)。2 回目以降の起動は数秒

結果

[setup] GPU: Tesla V100-PCIE-32GB
[data] train: (100, 800, 800, 3), eval(val): (100, 800, 800, 3)
[data] HxW = 800x800, loaded in 7.5s
[init] N_gaussians=10000, sh_degree=3, K_sh=16

[step     0] loss=0.1769  N=10000
[step   100] loss=0.2007  N=10000
[step   200] loss=0.1482  N=10000
[step   300] loss=0.1082  N=10000
[step   400] loss=0.0870  N=10000
[step   500] loss=0.0774  N=10000        ← refine_start_iter
[step   600] loss=0.0704  N=9841         ← prune が走り一旦減
[step   700] loss=0.0433  N=9917
[step   800] loss=0.0473  N=10148
[step   900] loss=0.0496  N=10522
[step   999] loss=0.0341  N=10522

[train] done. wallclock=10.5s, final_N=10522
[eval] val PSNR mean=19.809 (N_val=100)
{
  "step": 1000,
  "psnr_val": 19.809,
  "eval_split": "val",
  "eval_split_note": "test split has 164/200 missing in local copy; switched to val",
  "train_wallclock_sec": 10.502,
  "final_n_gaussians": 10522,
  "init_n_gaussians": 10000,
  "gpu_name": "Tesla V100-PCIE-32GB",
  "data_dir": "/home/otake_26/datasets/nerf_synthetic/lego",
  "sh_degree": 3
}

数字の意味

  • wallclock 10.5 s / 1k step = 95 step/s: tqdm のリアルタイム rate は中盤 130 step/s 程度、step 500 (refine 開始) で一旦 30 step/s に落ち、refresh 後復帰。V100 32GB で memory はほぼ余裕 (10522 gauss / sh=3 は数十 MB レベル)。
  • PSNR 19.8 dB / 1k step: Kerbl 公式の Lego 30k baseline は ~35 dB。1k 段階の 19.8 はオーダーとして妥当 (10k init → 10k 強でほぼ未 densify、SSIM loss 無し)。30k で 30 dB 以上まで上がる確度は別途。
  • gsplat の DefaultStrategy が refine_start_iter=500 で動き始め、prune_opa=0.005 で一度減ってからグロースする挙動が観察できた。

3. 失敗箇所と原因 (途中で踏んだトラップ)

#失敗原因対処
F1simple_trainer.py --helpModuleNotFoundError: imageiogsplat/examples の deps 未 install (それ自体は想定内)要件確認して minimal deps だけ install (imageio[ffmpeg] tqdm numpy<2 torchmetrics[image] Pillow)
F2examples が COLMAP / NCore のみ、Blender 未サポートgsplat HEAD では Blender path 削除済 (advisor 検証)自作 adapter (gsplat_lego_smoke.py) で rasterization を直叩き
F3FileNotFoundError: 'r_0.png.png'NeRF Synthetic の file_path./train/r_0 (拡張子なし) だが、test split は ./test/r_0.png (拡張子付き) と inconsistentpath に .png を append する前に exists() チェックする 2-stage
F4eval の test PSNR で again FileNotFoundErrorローカル lego/test/ で 200 中 164 frame が物理欠損 (r_0.png 等が存在しない)smoke では val split で eval、Phase 2b で test を再取得

TORCH_CUDA_ARCH_LIST について

JIT cache の落とし穴

gsplat の JIT は TORCH_CUDA_ARCH_LIST を見て nvcc に -gencode arch=compute_70,code=sm_70 を渡す。c33 (A6000、sm_86) 用キャッシュをそのまま使うと V100 (sm_70) では no kernel image is available for execution on the device が出る可能性があった (今回は明示 export で回避)。NFS 共有 env で sm が異なる機を行き来する場合は必ず TORCH_CUDA_ARCH_LIST を指定するのが安全。

4. リモートファイル (c32 / NFS 共有)

/home/otake_26/                       (= NFS、c32/c33/c34 共通)
├── miniconda3/envs/gsplat-env/       ← c33 で構築、c32 でそのまま activate
├── datasets/nerf_synthetic/lego/     ← 今回 rsync 配置 (112M、init.ply 含む)
├── repos/gsplat-examples/            ← gsplat HEAD clone (b5392fe)
├── gsplat_lego_smoke.py              ← 自作 Blender adapter (scp 経由)
├── runs/gsplat-lego-1k-smoke/        ← 結果
│   ├── eval.json
│   └── log.txt
├── runs/gsplat-lego-50-dryrun/       ← API 検証 (50 step、消しても可)
└── gsplat_1k.log                     ← nohup 出力

GPU 占有 (run 中スナップショット): GPU1 14.0 GiB / 32.5 GiB、Util ~99% (train 中)。GPU0 は他ユーザ稼働中で踏まず。

5. Phase 2b への引き継ぎ

必須

  1. test/ 復元: nerf_synthetic.zip 公式 (Kerbl らが配布する google drive、または NeRF 公式) から lego/test/ を取り直し、200 frame 揃える。これが無いと paper baseline (Kerbl 35.78 dB on Lego) との比較が不可。
  2. 30k full run: --max-steps 30000、wallclock 推測 = 10.5s × 30 = ~5-6 分 (refine による減速考慮、おそらく 8-12 分) on V100 GPU1。tmux または nohup で SSH 切断耐性確保。
  3. L1 + SSIM loss: 現状は L1 only。Kerbl baseline (λ=0.2 で SSIM 合算) に合わせる場合は fused_ssim を追加 install して loss 合成。
  4. 三層対比表 (A.3 主目的): 同 Lego 30k を c33 (A6000) + c32 (V100) + m4 max (Metal) の 3 機 × gsplat / 原著 / brush で回し、wallclock + PSNR + VRAM を集計。

任意 / 推奨

  • adapter の random sampling は今回 numpy rng なので、再現性を取る場合は torch 側にも seed (torch.manual_seed は呼んでいるが、SH coeff のような 0 init のみだから影響薄)。
  • DefaultStrategy 既定値は scene_scale=1.0 で動かしているが、Lego は実 scene scale ~4 程度 (カメラ半径)。30k では scene_scale=4.0 を試した方が refine しきい値が realistic に。
  • adapter は 200 行で paper 標準 (l1+ssim, sh3, refine 500-15k) の 教育用 minimum にとどまる。本卒研の論文 Table としては gsplat 公式 simple_trainer を使う方が正統だが、それには COLMAP 変換 (pycolmap) が必須で、Lego の場合は transforms_*.json → COLMAP の reverse 変換 をするか、gsplat 公式が将来 Blender path を復活させるのを待つ必要あり。

sm 一覧 (確定)

GPUsmTORCH_CUDA_ARCH_LIST
c33A6000sm_868.6
c34A6000sm_868.6
c32V100sm_707.0

JIT cache はそれぞれ ~/.cache/torch_extensions/... 配下に sm 別 .so が残る。NFS 共有でも cache key に sm が入っているので衝突しない。

6. 再現コマンド (one-liner)

# m3 mac 側
rsync -avh --ignore-existing /Users/otkrickey/dev/3dgs-workspace/datasets/nerf_synthetic/lego/ \
  matsudalab-c33:~/datasets/nerf_synthetic/lego/
scp scripts/gsplat_lego_smoke.py matsudalab-c32:~/gsplat_lego_smoke.py

# c32 側
ssh matsudalab-c32 << 'EOF'
source ~/miniconda3/etc/profile.d/conda.sh && conda activate gsplat-env
export CUDA_VISIBLE_DEVICES=1 TORCH_CUDA_ARCH_LIST=7.0
python ~/gsplat_lego_smoke.py \
  --data-dir ~/datasets/nerf_synthetic/lego \
  --result-dir ~/runs/gsplat-lego-1k-smoke --max-steps 1000
EOF
03

関連 finding

© 2026 大竹律輝 — 松田研究室