AMD Ryzen AI Max+ 395 (Radeon 8060S / gfx1151 / Strix Halo) 上で動かしている
自作の「RealtimeDepth」(Depth Anything V2 Small で USB カメラ映像をリアルタイム深度化し、
MJPEG で Chrome に流すデモ) を、Ubuntu 24.04 + ROCm 7.2.1 から Ubuntu 26.04 + ROCm 7.14 へ
移行した記録です。
結論から言うと、ONNX Runtime + MIGraphX 経路は 7.14 では復旧不能で、
PyTorch (ROCm) 直接推論に載せ替えることで GPU 実行が復活しました。
しかも速くなりました (CPU フォールバック約 10 FPS → 推論単体 79.9 FPS)。
前半は動く手順、後半はどこで詰まって何で解決したかを並べます。
同じ gfx1151 で ROCm 7.14 に上げて MIGraphX が無くて困っている方の参考になれば。
環境
| 項目 | 移行前 | 移行後 |
|---|---|---|
| OS | Ubuntu 24.04 | Ubuntu 26.04 (resolute) |
| ROCm | 7.2.1 (/opt/rocm) |
7.14.0 (/opt/rocm) ※アプリからは使わない
|
| GPU | Radeon 8060S (gfx1151, 48GB VRAM) | 同左 |
| 推論エンジン | ONNX Runtime + MIGraphX EP | PyTorch 2.9.1 (ROCm 7.13 wheel) |
| モデル形式 | depth_anything_v2_vits_518.onnx |
depth_anything_v2_vits.pth (公式チェックポイント) |
| Python / venv | 3.10 / .venv
|
3.14 / .venv-torch
|
HSA_OVERRIDE_GFX_VERSION |
11.5.1 が必要
|
設定してはいけない |
| 起動時間 | 初回 ~110 秒 (MIGraphX AOT コンパイル) | 約 7 秒 |
移行の一番大きな効果は速度ではなく、システム ROCm のバージョンから構造的に切り離せたことです。
PyTorch の gfx1151 wheel は依存として rocm-sdk-libraries-gfx1151 を引き込み、
自前の ROCm ランタイムを同梱します。動いている必要があるのはカーネルドライバ
(KFD/amdgpu、26.04 は in-tree で十分新しい) だけで、/opt/rocm が 7.14 だろうが何だろうが無関係です。
最新のGitHub
前半: 動作するステップ
1. なぜ ONNX を捨てるのか
Depth Anything V2 は もともと純 PyTorch モデル (DINOv2 バックボーン + DPT ヘッド) です。
ONNX export はあくまで「ONNX Runtime + MIGraphX で回すため」の中間層でした。
PyTorch で直接回せば、
- ONNX export に伴う op 非互換 (Resize まわりなど) の罠が消える
- MIGraphX という「システム ROCm と密結合したコンポーネント」への依存が消える
-
.migraphx_cache/(753MB) と初回 ~110 秒の AOT コンパイルが消える -
config.yamlを書き換えて再起動するだけで入力サイズや精度を変えられる
(ONNX 経路は再 export + 再コンパイルが必要だった)
というわけで、中間層ごと削除します。
2. Python の準備
gfx1151 の wheel は cp312 / cp313 / cp314 のみです。
旧 .venv は onnxruntime-migraphx の cp310 wheel に合わせて Python 3.10 で作っていたので、
再利用できません。Ubuntu 26.04 標準の 3.14 で作り直します。
cd ~/RealtimeDepth
python3.14 --version # 3.14.x
uv venv --python 3.14 .venv-torch
3. PyTorch (gfx1151) のインストール
ここが最重要です。 wheel の入手元を間違えると実行時に落ちます。
https://repo.amd.com/rocm/whl/gfx1151/ ← これを使う
https://download.pytorch.org/whl/rocm... ← 使わない
VIRTUAL_ENV=$PWD/.venv-torch uv pip install \
--index-url https://repo.amd.com/rocm/whl/gfx1151/ \
--extra-index-url https://pypi.org/simple \
--index-strategy unsafe-best-match --prerelease allow \
torch==2.9.1+rocm7.13.0 torchvision==0.24.0+rocm7.13.0
VIRTUAL_ENV=$PWD/.venv-torch uv pip install flask opencv-python pyyaml
torch と torchvision はバージョン組で固定すること。
index には torchvision 0.24.0 / 0.25.0 / 0.26.0 が横並びで置かれていますが、
torch 2.9.1 に対応するのは 0.24.0 だけです。詳しくは後半へ。
torch torchvision 2.9.1 0.24.0 2.10.0 0.25.0 2.11.0 0.26.0
torchvision は省略できません。depth_anything_v2/dpt.py が
from torchvision.transforms import Compose を無条件に import しています。
GPU 認識の確認:
.venv-torch/bin/python -c "
import torch
print(torch.cuda.is_available())
print(torch.cuda.get_device_properties(0).gcnArchName)"
# → True / gfx1151
![]()
HSA_OVERRIDE_GFX_VERSIONは設定しないこと。
旧 MIGraphX 経路では11.5.1が必要でしたが、repo.amd.comの gfx1151 wheel は
gfx1151 ネイティブビルドなので override は有害です。
古い手順書をコピーしてこれを export すると壊れます。
4. モデル (.pth) の取得
ONNX ではなく公式チェックポイントをそのまま使います。
cd ~
git clone https://github.com/DepthAnything/Depth-Anything-V2.git
# checkpoints/depth_anything_v2_vits.pth を配置 (HuggingFace から取得)
cd ~/RealtimeDepth
ln -s ~/Depth-Anything-V2 Depth-Anything-V2 # リポジトリからは symlink 経由で参照
5. config.yaml の書き換え
ONNX ファイルパス指定を、リポジトリ + encoder + チェックポイントの 3 点指定に置き換えます。
model:
- path: depth_anything_v2_vits_518.onnx
+ repo: Depth-Anything-V2
+ encoder: vits # vits / vitb / vitl / vitg
+ checkpoint: Depth-Anything-V2/checkpoints/depth_anything_v2_vits.pth
+ # DPT ヘッドの制約で 14 の倍数であること (518 = 14 x 37)
input_size: 518
runtime:
- # MIGraphX のコンパイル結果をキャッシュ (2回目以降 ~110s のコンパイルをスキップ)
- compile_cache_dir: .migraphx_cache
+ device: cuda # ROCm の HIP 層が CUDA API を受けるので gfx1151 でも "cuda"
+ precision: fp16 # fp16 / fp32
+ compile: false # torch.compile。初回 1〜2 分かかるが数割速い
device: cuda で動くのは、ROCm の HIP レイヤーが CUDA API を翻訳するためです。
6. アプリ側の差し替え
onnxruntime を撤去して DepthAnythingV2 を直接ロードします。
カメラのステートマシン・MJPEG・Flask・スレッド設計はまったく触っていません。
モデルのロード
sys.path.insert(0, DAV2_REPO) # config の model.repo (symlink)
from depth_anything_v2.dpt import DepthAnythingV2
ENCODER_CONFIGS = { # 公式 app.py の model_configs と同一
'vits': {'features': 64, 'out_channels': [48, 96, 192, 384]},
'vitb': {'features': 128, 'out_channels': [96, 192, 384, 768]},
'vitl': {'features': 256, 'out_channels': [256, 512, 1024, 1024]},
'vitg': {'features': 384, 'out_channels': [1536, 1536, 1536, 1536]},
}
model = DepthAnythingV2(encoder=ENCODER, **ENCODER_CONFIGS[ENCODER])
model.load_state_dict(torch.load(CHECKPOINT, map_location='cpu'))
model = model.to(device=DEVICE, dtype=DTYPE).eval()
前処理 — 正規化は GPU 側でやる
ONNX 経路では CPU で float32 に展開してから渡していましたが、
uint8 のまま転送して GPU 上で正規化する形に変えました。
def preprocess(bgr):
rgb = cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB)
resized = cv2.resize(rgb, (518, 518), interpolation=cv2.INTER_CUBIC)
t = torch.from_numpy(np.ascontiguousarray(resized)).to(DEVICE) # uint8 HWC のまま転送
t = t.permute(2, 0, 1).unsqueeze(0).to(DTYPE).div_(255.0) # GPU 上で CHW / fp16 化
return (t - MEAN) / STD
# MEAN = [0.485, 0.456, 0.406], STD = [0.229, 0.224, 0.225] (fp16, shape (1,3,1,1))
CPU 側で float32 に展開すると 518×518×3×4 ≒ 3.2 MB ですが、
uint8 のままなら 1/4 の約 0.8 MB で済みます。正規化自体は GPU では実質ゼロコストです。
推論
@torch.inference_mode()
def infer(bgr):
depth = model(preprocess(bgr)) # forward は (B, H, W) を返す
return depth[0].float().cpu().numpy()
DepthAnythingV2.forward() は末尾で squeeze(1) するのでチャネル次元がありません
(ONNX 経路の out[0][0] と同じものを指します)。fp16 推論なので、
カラーマップに渡す前に .float() します。
ウォームアップを Flask 起動「前」に済ませる
初回 forward() では HIP カーネルの JIT、MIOpen の畳み込みアルゴリズム選択、
アロケータのプール確保が同時に走って数秒かかります。
def warmup():
dummy = np.zeros((INPUT_SIZE, INPUT_SIZE, 3), dtype=np.uint8)
for _ in range(3):
infer(dummy)
torch.cuda.synchronize()
これを Flask 起動前にやっておかないと、最初の数フレームだけ極端に低い FPS が表示されます。
7. 起動スクリプトの修正
-source .venv/bin/activate
-export HSA_OVERRIDE_GFX_VERSION=11.5.1
+source .venv-torch/bin/activate
+# repo.amd.com の gfx1151 wheel はネイティブビルドなので override すると壊れる
+unset HSA_OVERRIDE_GFX_VERSION
-echo "waiting for ready (cold start ~110s, cached ~3s)..."
+echo "waiting for ready (model load + warmup ~10s; torch.compile 有効時は 1〜2 分)..."
シェルプロファイル側で HSA_OVERRIDE_GFX_VERSION を export している環境があるので、
export を消すだけでなく明示的に unset しています。
8. 実測
Radeon 8060S / gfx1151 / vits / 518² / fp16:
| 項目 | 値 |
|---|---|
| 推論単体 | 12.5 ms / frame (79.9 FPS) |
| アプリ全体 (取得+推論+カラーマップ+JPEG) | 26 FPS |
| 起動時間 (モデルロード + ウォームアップ) | 約 7 秒 |
| 参考: 旧 ONNX Runtime CPU フォールバック | 約 10 FPS |
現在のボトルネックはカメラ側です。推論が 13 ms なのに対しカメラは 30fps (33 ms/frame)
でしか出さないので、パイプライン全体はカメラの供給レートに張り付いています。
推論をこれ以上速くしても表示 FPS は上がりません。逆に言えば GPU に余力があるので、
vitb / vitl や高解像度に振ってもリアルタイム域を維持できる見込みです。
torch.compile (runtime.compile: true) も用意しましたが、既定は off です。
fp16 eager で既に 79 FPS 出ていて、起動のたびに 1〜2 分払う価値がないためです。
9. 旧経路の後片付け
移行完了後、以下を削除しました (合計 約 2.2 GB)。
-
depth_anything_v2_vits_518.onnx(95MB) -
.migraphx_cache/(753MB、.mxr1 ファイル) - 旧
.venv(1.4GB、Python 3.10 + onnxruntime-migraphx)
後半: 詰まったところと解決策
ここからは移行に至るまでに踏んだ地雷です。順番は実際に踏んだ順です。
詰まり 1: onnxruntime が import した瞬間に落ちる (exec-stack)
Ubuntu 26.04 に上げた直後、まず ONNX Runtime 自体が import できなくなりました。
原因は venv 内の onnxruntime_pybind11_state.so が 実行可能スタック
(GNU_STACK = RWE) を要求していること。26.04 のカーネルはこれを拒否します。
解決策: ELF ヘッダの PF_X ビットを落として RWE → RW に変える。
# 事前にバックアップを取ること
python - <<'EOF'
# GNU_STACK program header の p_flags から PF_X (0x1) を落とす
EOF
これで import は通るようになりましたが、動くのは CPU 実行だけでした (約 10 FPS)。
本題はここからです。
PyTorch 直接推論に移行するとこのパッチ自体が不要になります。
ORT を再導入する場合は同じ手当てが再び必要になる点だけ覚えておいてください。
詰まり 2: gfx1151 / ROCm 7.14 向けの MIGraphX が存在しない
ROCm 7.1 で ROCMExecutionProvider が廃止され、AMD は
MIGraphXExecutionProvider に一本化しました (ORT 1.23 で ROCm EP はコードごと削除)。
つまり ONNX 経路で GPU を使うには MIGraphX が必須です。
ところが探しても無い。以下を全部確認して、gfx1151 / 7.14 向け MIGraphX は
AMD のどのチャネルにも配布されていませんでした。
-
repo.amd.com/rocm/whl/gfx1151/— migraphx なし - nightlies — なし
-
repo.amd.com/rocm/packages-multi-arch/ubuntu2604— なし - PyPI の
onnxruntime-rocm— ROCm 6.x ビルドなので 7.x ではlddの時点で解決不能
詰まり 3: MIGraphX 7.2.1 の汎用 deb を載せても実行時 JIT で死ぬ
唯一入手できるのが ROCm 7.2.1 世代の汎用 deb です。これを 7.14 環境に入れると、
soname は解決できてライブラリのロードまでは通ります。「いけるか?」と思ったところで死にます。
error: __hmax is ambiguous
error: [[clang::lifetimebound]] ... (-Werror)
terminate called after throwing an instance of 'std::bad_alloc'
MIGraphX は GPU カーネルを 実行時にシステムの comgr/clang で JIT します。
そのため migraphx のバージョンと ROCm ツールチェイン (clang/HIP ヘッダ) の版が
揃っていないと動きません。7.14 の LLVM 23 系ヘッダに対して 7.2.1 のソースが
通らない、本物のソースレベル非互換で、-Wno-error では回避できません。
教訓: リンク ABI (soname) が一致していても、実行時 JIT するコンポーネントは
ツールチェインの版まで揃っていないと動かない。
詰まり 4: MIGraphX のソースビルドは「できるが割に合わない」
版が揃っていないのが問題なら、rocm-7.14 タグからソースビルドすれば揃うはずです。
実際に着手して、依存ライブラリのビルドまでは通りました。
# 重量級コンポーネントを無効化して現実的な時間に収める
-DMIGRAPHX_ENABLE_MLIR=OFF # rocMLIR 回避
-DMIGRAPHX_USE_COMPOSABLEKERNEL=OFF
-DMIGRAPHX_USE_EIGEN=OFF
-DGPU_TARGETS=gfx1151
-DCMAKE_CXX_COMPILER=/opt/rocm/lib/llvm/bin/clang++
ハマりどころとして、ビルドツール (rbuild + cget) は Python 3.10 が必要でした。
3.14 では cget が FancyURLopener 廃止で動きません。
ただしここで手を止めました。理由は、
- MLIR / CK を無効化した状態でモデルがコンパイルできなければ rocMLIR 有効化が必要になり、
さらに 1 時間以上のビルドが積み増しになる - そもそも PyTorch 直接推論なら 5 分で終わる
解決策 = 方針転換。ONNX という中間層を捨てました。
代替案として TheRock の 7.14 世代マルチアーキ wheel も検討しましたが、
gfx1151 向け配布物に migraphx コンポーネントが実際には含まれていない報告があり
(AURrocm-gfx1151-bin, therock-dist 7.13)、まだ不安定と判断しています。
最終フォールバックとしては ncnn + Vulkan の DAv2 ポート (ROCm 完全非依存) がありますが、
今回は不要でした。
詰まり 5: hipErrorInvalidImage / kpack_load_code_object failed with error: 13
PyTorch に移行して最初に踏むのがこれです。
hipErrorInvalidImage
kpack_load_code_object failed with error: 13
原因: download.pytorch.org の ROCm wheel を入れた。あちらはマルチアーキの
kpack ビルドで、gfx1151 ではバンドルされた code object をロードできません。
解決策: gfx1151 専用 index から入れ直す。
VIRTUAL_ENV=$PWD/.venv-torch uv pip install --reinstall \
--index-url https://repo.amd.com/rocm/whl/gfx1151/ \
--extra-index-url https://pypi.org/simple \
--index-strategy unsafe-best-match --prerelease allow \
torch==2.9.1+rocm7.13.0 torchvision==0.24.0+rocm7.13.0
(これは WhisperX を gfx1151 で動かしたときにも踏んだのと同じ罠です)
詰まり 6: RuntimeError: operator torchvision::nms does not exist
原因: torch と torchvision のバージョンが噛み合っていない。
gfx1151 の index には torchvision 0.24.0 / 0.25.0 / 0.26.0 が横並びで置かれているので、
バージョン指定を省くと最新 (0.26.0) が入って torch 2.9.1 と食い違います。
torchvision の C++ 拡張が別バージョンの libtorch に対してビルドされているため、
カスタム op の登録が済まないまま register_fake が走って落ちます。
解決策: 上表の組で固定する (cp314 なら torch 2.9.1 ↔ tv 0.24.0)。
詰まり 7: torch.cuda.is_available() が False
チェック順:
-
ls /dev/kfd /dev/driが通るか (通らなければカーネル側の問題) - ユーザーが
render/videoグループに入っているか (id) HSA_OVERRIDE_GFX_VERSIONが export されていないか-
python -c "import torch; print(torch.version.hip)"で HIP ビルドか確認
3 が今回の本命です。旧 MIGraphX 手順では HSA_OVERRIDE_GFX_VERSION=11.5.1 が必要
だったので、シェルのプロファイルに残っていたり、古い手順書をコピペしたりで
生き残りがちです。gfx1151 ネイティブ wheel に対して override をかけると壊れます。
解決策: 起動スクリプトで明示的に unset。
詰まり 8: 旧 venv が再利用できない
原因: 旧 .venv は onnxruntime-migraphx の cp310 wheel に合わせて Python 3.10 で
作っていましたが、gfx1151 の PyTorch wheel は cp312 / cp313 / cp314 のみで cp310 がありません。
解決策: 素直に .venv-torch を新規作成 (Python 3.14)。
詰まり 9: ValueError: model.input_size は 14 の倍数である必要があります
DPT ヘッドが入力を 14×14 のパッチに分割するための制約です。
既定の 518 は 14 × 37。392 / 280 なども可。起動時に弾くようにしました。
詰まり 10: load_state_dict が size mismatch で落ちる
model.encoder と model.checkpoint の組み合わせが食い違っています。
vits なら depth_anything_v2_vits.pth、vitl なら depth_anything_v2_vitl.pth と、
両方を揃えてください。
無害なので気にしなくていい警告
起動ログに以下が出ますが、動作に影響ありません。
-
xFormers not available— DINOv2 が xformers を optional import しているだけ warning: xnack 'Off' was requested for a processor that does not support it!-
MIOpen(HIP): Warning [ParseAndLoadDb] File is unreadable: ...gfx1151_20.HIP.fdb.txt
— MIOpen の事前チューニング DB が同梱されていないだけ。畳み込みアルゴリズムは
初回実行時に自動選択され、結果はユーザーキャッシュに保存されます
まとめ
| 論点 | 結論 |
|---|---|
| ROCm 7.14 で ONNX Runtime + MIGraphX は使えるか | gfx1151 では実質不可。配布物が無く、7.2.1 汎用ビルドは実行時 JIT で死ぬ |
| MIGraphX をソースビルドすべきか | できるが割に合わない。PyTorch 直の方が速くて短い |
| PyTorch の gfx1151 wheel はどこから |
https://repo.amd.com/rocm/whl/gfx1151/ 一択 |
HSA_OVERRIDE_GFX_VERSION |
設定しない。旧 MIGraphX 手順との最大の差分 |
| torch / torchvision | 必ず組で固定 (2.9.1 ↔ 0.24.0) |
システム /opt/rocm のバージョン |
無関係になる。これが移行の一番の収穫 |
一般化すると、**「システム ROCm に密結合したコンポーネント (MIGraphX / ORT EP) に
依存する構成は、ROCm のバージョンが動くたびに壊れる」**ということです。
gfx1151 のように配布物が薄いアーキでは特に厳しい。
PyTorch の ROCm wheel がランタイムを同梱してくれる構成のほうが、
少なくとも当面は圧倒的に維持コストが低いと感じています。
なお、いつでも比較できるよう、リポジトリには
ROCM_7_2_1 (ONNX/MIGraphX 構成の最終コミット) と
ROCM_7_14_0 (PyTorch 直接推論構成) の git タグを打ってあります。