効果音を作るモデル MOSS-SoundEffect v2.0 が ROCm で動くかを技術検証したところ、1 step に 70 秒かかりました。エラーは出ず、GPU の使用率は 0% のまま時間だけが経ちます。壊れているのか、待てば終わるのかが分からない、見分けにくい症状です。

結論

  • 原因は、MOSS-SoundEffect のコードにある @torch.compile でした。ROCm では極端に重く、約 270 倍遅くなりました。
  • TORCH_COMPILE_DISABLE=1 TORCHDYNAMO_DISABLE=1 を立てて走らせます。
  • 「GPU が遊んでいるのに遅い」なら、まずこれを疑います。GPU が動いていて最初の1回だけ遅いのは、カーネルの自動調整で、ハングではありません。
  • 立て忘れを防ぐため、効果音を起こすスクリプトの中で立てるようにしました。

試した環境

  • GPU: AMD Radeon RX 7900 XT(gfx1100、VRAM 20 GiB)
  • OS と ROCm: Ubuntu、ROCm 7.2.4
  • ライブラリ: torch 2.13.0+rocm7.2
  • モデル: MOSS-SoundEffect v2.0(効果音)

何が起きたか

効果音を1つ作らせると、1 step に 70 秒かかりました。GPU の使用率は 0% のまま動かず、プロセスは落ちもしません。ふつうに動くときと比べて、約 270 倍の遅さでした。

困るのは、ROCm ではもともと「最初の1回だけ数分止まって見える」ことがある点です(カーネルの自動調整。後で触れます)。そのつもりで待っていると、いつまでも終わりません。逆に、自動調整で遅いだけのときにハングだと思って止めてしまうこともあります。私たちも、初回の遅さをハングと誤診したことがあります。

助け手が滑車と重りの仕掛けを外し、身軽になった走者が走り出している絵

止め方

MOSS-SoundEffect のコードには @torch.compile が付いています。この経路が ROCm では極端に重く、そのあいだ GPU の使用率は 0% のままでした。コードを書き換えなくても、2つの環境変数で止められます。

TORCH_COMPILE_DISABLE=1 TORCHDYNAMO_DISABLE=1 python <効果音を作るスクリプト> ...

私たちの環境で、1つのプロセスの中で効果音を作ったときの所要は、初回 125.7 秒、2回目以降 35.2 秒でした。初回のうち約 90 秒は MIOpen の自動調整で、これはキャッシュがあってもプロセスごとに毎回かかります。そのため検証では、一組の効果音を1つのプロセスでまとめて作りました。

自動調整と見分ける

ROCm で「遅い」「止まって見える」ときの、私たちの見分け方です。手がかりは GPU の使用率で、amdgpu が出す gpu_busy_percent で見ました。

遅いときの見分け方

2つの違いを表にすると、次のとおりです。

torch.compile自動調整
遅い所毎 step(70 秒/step)最初の1回
GPU の使用率0% のまま動いている
いつ起きるか変数を立てない限り毎回新しいプロセス・利用者・解像度のとき(MOSS はプロセスごとに約 90 秒)
どうする環境変数で止める待つ

GPU が動いていれば、待てば終わります。GPU が遊んでいるのに時間だけ経つなら、待つより先に compile を疑います。

立て忘れを防ぐ

この変数を手順書やプロンプトに書いても、生成を任せた AI のエージェントには守られませんでした。そこで、生成は薄いシェルの入口からだけ起こす約束にし、効果音のときだけ入口が変数を立てるようにしました。

[ "$cmd" = sfx ] && { export TORCH_COMPILE_DISABLE=1 TORCHDYNAMO_DISABLE=1; }

効果音以外のモデルでは、この変数は立てませんでした。立て忘れると 270 倍遅くなる物を、人の記憶に頼らずに済むようにしました。

確かめていないこと

  • MOSS-SoundEffect が、自動調整のキャッシュがあってもプロセスごとに約 90 秒払う理由。

おわりに

GPU が遊んでいるのに遅いなら、待つより先に torch.compile を疑ってください。GPU が動いているなら、それは最初の1回の自動調整で、待てば終わります。

※ ROCm と PyTorch の振る舞いは執筆時点の版(ROCm 7.2.4、torch 2.13.0+rocm7.2)で見た物で、いまは変わっている可能性があります。