170万円の自宅AI環境のうち、統合メモリ128GBのGMKtec EVO-X2(Ryzen AI Max+ 395)は、これまでローカルLLM担当でした。ところが最近、別の仕事が増えました。音声合成(TTS)です。
きっかけは、動画や読み上げに使う「自分好みの声」をローカルで作りたくなったこと。クラウドの音声APIは便利ですが、生成した音声を今後の実験(他モデルの学習データ)に使いたいので、ライセンスが明快なローカルモデルで揃えたかったのです。
最初に触ったのはAlibabaの多言語TTS「Qwen3-TTS」。ボイスデザイン(文章で声を作る)とボイスクローン(数秒の参照音声から声を写す)を一通り試せるアプリを、Claude Codeと一緒にStreamlitで組みました。ここまでは半日。
問題はその先です。「せっかくGPUがあるんだから使いたい」と思ったところから、AMD統合GPU特有の沼が始まりました。
この記事は環境構築編です。日本語特化TTS「Irodori-TTS」をWindows + ROCmで動かし、CPUの4倍速で推論・7.7倍速で学習できるようになるまでの記録と、途中でデスクトップが2〜3秒おきに真っ暗になった事故の話。同じRyzen AI Max(Strix Halo)ユーザーには、たぶん有益です。 Qwen3-TTSとIrodori-TTSのどちらが良いかを115票のブラインド聴き比べで決めた比較編は別記事にしました。
先に結論

| CPU (fp32) | GPU (bf16) | 倍率 | |
|---|---|---|---|
| 参照なし生成(RTF) | 2.19〜2.37 | 0.54 | 約4倍 |
| ボイスクローン(RTF) | 2.48〜2.57 | 0.84 | 約3倍 |
| 話者埋め込みの学習(秒/サンプル) | 2.71 | 0.35 | 約7.7倍 |
RTF 0.54というのは「10秒の音声を5.4秒で作る」速さ。CPUだと23秒かかっていたので、体感がまるで違います。学習は1000ステップ(8,000サンプル)が46分。CPUなら6時間。公式レシピ相当の48,000サンプルでも、CPUの36時間が4〜5時間になり、一晩で回せる範囲に入りました。
ただし、これはTransformer本体だけをGPUに載せ、音声コーデックはCPUに残すハイブリッド構成での数字です。なぜそうなったかは後半で。
Qwen3-TTSはGPUの方が遅かった
順番に話します。まずQwen3-TTS。AMDは2026年時点でWindows向けにROCm 7.2対応のPyTorch(torch 2.9.1)を公式配布しており、torch.cuda.is_available() は True を返します(ROCmでも呼び方は cuda です。慣れるまで気持ち悪い)。統合メモリは99.7GBがGPUから見えました。
ここまでは順調。ところが実測すると、GPUの方がCPUより2倍遅い。
| Qwen3-TTS 1.7B | CPU | GPU (ROCm 7.2.1) |
|---|---|---|
| 1文ずつ生成(RTF) | 5.09 | 10.34 |
| 4文バッチ(RTF) | 1.58 | 8.63 |
Qwen3-TTSは自己回帰型、つまり音声トークンを1個ずつ順に生成します。1トークンごとに小さなGPUカーネルを何十個も起動するので、内蔵GPUではカーネル起動のオーバーヘッドが支配的になる。加えてWindows ROCmではFlash Attention / Memory-Efficient Attentionがまだ experimental で、警告を出しながら素のattentionで動きます。そういうわけで、Qwen3-TTSはCPUで運用することにしました(ここで一度、諦めています)。
Irodori-TTSに出会う
日本語の読み間違いや抑揚に不満があって探していたところ、Aratakoさんが公開しているIrodori-TTSを見つけました。日本語特化、0.8Bパラメータ、48kHz出力、MITライセンス。しかもRectified Flow DiT、つまり非自己回帰です。音声全体を40ステップの反復で一気に生成する方式で、1ステップが大きな行列積の塊。これは内蔵GPUと相性が良いはず、と踏んで再挑戦しました。
結果は冒頭の表の通りですが、そこまでに5つの壁がありました。
壁1: torch 2.10が要る。公式Windows ROCm版は2.9.1
Irodori-TTSは torch>=2.10 を要求します。AMD公式のWindows向けPyTorchは2.9.1で、満たせません。
解決策は、AMDがTheRockプロジェクトで公開しているnightly indexです。https://rocm.nightlies.amd.com/v2/gfx1151/ に、Radeon 8060S(アーキテクチャ名 gfx1151)向けの torch 2.10.0+rocm7.13.0a がありました。
pip install --pre --index-url https://rocm.nightlies.amd.com/v2/gfx1151/ "torch==2.10.*" "torchaudio==2.10.*"
nightly なので明日動く保証はありませんが、2026年5月2日ビルドで問題なく動いています。
壁2〜4: 依存関係がWindows ROCmを想定していない
Irodori-TTSはLinux + CUDA前提で作られています(責める気は全くありません、自然なことです)。Windows ROCm nightly のtorchには含まれていないものがあり、そこで次々と落ちます。
| 壁 | 症状 | 対処 |
|---|---|---|
| 2 | 音声コーデック dacvae がPyPIに無い | GitHubの特定コミットから直接インストール |
| 3 | torch.distributed が無く、依存ライブラリ(audiotools)がimport時に dist.ReduceOp を参照して落ちる | sitecustomize.py でダミーの ReduceOp を注入(単一プロセスでは使われない属性) |
| 4 | torchaudio.load が torchcodec を要求するが、ROCm版には無い | 音声の読み書きを soundfile に差し替えるパッチ |
| おまけ | sentencepiece<0.2 にPython 3.12用wheelが無い / 依存パッケージがprotobufを3.xに下げてStreamlitが起動しなくなる | 0.2系を使用 / protobufを再アップグレード |
一つ一つは小さいのですが、全部を自力で調べて潰すのは、正直かなりしんどい。エラーメッセージから「torch.distributedがnightlyビルドに入っていない」→「でも実際には使われない属性参照だけ」→「sitecustomize.pyで補えばIrodori側のコードを一切変えずに済む」という判断を、深夜に一人でやる気力は私にはありません。この話は最後にもう一度書きます。
壁5: 画面が2〜3秒おきに真っ暗になる
依存関係が通り、いざGPUで生成。デスクトップ全体がブラックアウトし、2〜3秒後に再描画され、また真っ暗になる、を繰り返し始めました。TTSアプリのタブではなく、OSの画面全体です。
内蔵GPUは表示と計算を同じシリコンでやっているので、GPU側の異常がそのままデスクトップに出ます。dGPU機なら「計算が落ちた」で済むところが、統合メモリ機では「画面が死ぬ」になる。これはStrix Halo特有の怖さです。
原因を追うと、音声コーデック(DACVAE)の畳み込み層がMIOpen(AMD版cuDNN)で失敗していました。fp32ではカーネル起動失敗、bf16ではJITコンパイル失敗。しかも失敗したプロセスがドライバ内でハングし、タスクマネージャーからも殺せない。イベントログにTDR(Event 4101)は記録されておらず、ドライバリセットではなく、ハングしたカーネルがコンポジタを巻き込んでいるように見えました。
対処は割り切りました。Transformer本体はGPU、コーデックはCPUというハイブリッド構成にし、ROCm環境ではコーデックをGPUに置く選択肢自体をアプリから消しました。
コーデックをCPUに固定した状態で、GPU推論50秒・GPU学習70秒を連続で回して、画面の異常は再現せず。それ以降、数時間のGPU学習を何度も回していますが、一度も起きていません。

コーデックがCPUに残る代償は、ボイスクローンで参照音声のエンコードがCPUで走ること(RTF 0.54 → 0.84)。これは参照音声の潜在表現を一度計算して保存しておく「事前計算」機能で解消できました。
その後: 話者埋め込みの学習もGPUで
Irodori-TTSにはSpeaker Inversionという機能があります。複数のクリップから16トークンの話者埋め込みを学習し、以後は参照音声なしでその声を再現するもの。CPUでは1サンプル2.7秒、200ステップで18分かかっていたのが、GPU bf16では0.35秒。バッチ8で1000ステップを45分44秒で回せました。

bf16とfp32で音質の差は、私の耳では分かりませんでした。
人間がやったこと、Claudeがやったこと
| 作業 | 人間(私) | Claude Code |
|---|---|---|
| 「GPUで速くならないか」「Irodoriを試そう」の判断 | ○ | 提案 |
| nightly indexの発見、依存関係5件の切り分けと回避策 | ○ | |
| ブラックアウトの目撃・報告(「画面全体がチラつく」) | ○ | |
| 原因の絞り込み(MIOpen / コーデック)とハイブリッド構成の実装 | ○ | |
| 「本当にもう出ないか」の確認試験 | 立ち会い | 実行 |
| 音質の判断(bf16に劣化があるか、クローンが似ているか) | ○ | |
| 進捗が見えない・チェックポイントが無いことへの指摘 | ○ | 実装 |
Windowsで os.kill(pid, 0) が生存確認ではなくプロセスを殺すバグ | 混入も修正も |
最後の行は正直に書きます。Claude Codeは、Linuxの常識をWindowsに持ち込んで、学習ジョブの生存確認のつもりでプロセスを殺すコードを書きました。私が「学習が勝手に止まる」と気づき、Claudeが調べて直しました。万能ではない。
それでも、この環境構築を人間だけでやるのはかなり厳しい、というのが率直な感想です。Windows ROCm nightlyという少数派の環境で、TTSモデルの依存関係を5層掘って、MIOpenの失敗をハイブリッド構成で回避する。一つ一つの情報はどこかに散らばっていますが、それを深夜に一人で繋ぐ体力は、五十路にはありません(断言
コーディングエージェントがあると「試す→落ちる→原因を読む→回避策を書く→再試行」のループが数分で回ります。私は判断と、耳と、目(画面が真っ暗になったのを見るのは人間の仕事です)を提供し、手数の多い部分はClaudeに任せる。この種のツールは便利どころか、もう必須だと思っています。
同じ構成の人へのメモ
- torch 2.10系の入手:Radeon 8060S / 8050S(gfx1151)なら、TheRockのnightly indexから入る。
--pre --index-url https://rocm.nightlies.amd.com/v2/gfx1151/ - 無いもの前提で:
torch.distributedとtorchcodecは無い。前者は属性スタブ、後者は soundfile で逃げる - 畳み込みは小さく試す:音声コーデックやVAEなど畳み込みを多用するモデルをGPUに載せる前に、まず短い入力で。MIOpenで失敗すると、内蔵GPU機では画面ごと巻き込まれる
- ハイブリッドで十分:Transformer部分だけGPU、畳み込み部分はCPU、でも4倍速い
- 自己回帰は伸びない:LLM系やQwen3-TTSのような自己回帰型は内蔵GPUで速くならないことがある。非自己回帰(DiT系)は伸びる
- 長時間ジョブの監視:ログの直書きと定期チェックポイントを最初に作る。後から欲しくなる
まとめ
- Irodori-TTSはWindows + ROCm nightlyで動き、Ryzen AI Max+ 395の内蔵GPUで推論4倍・学習7.7倍
- 壁は5つ。torchのバージョン、無いパッケージ3つ、そしてMIOpenでの画面ブラックアウト
- 内蔵GPUでは「計算が落ちる」が「画面が死ぬ」になる。コーデックはCPUに残す
- この手の環境構築は、コーディングエージェントと組むと現実的な時間で終わる
次回の比較編では、このIrodori-TTSとQwen3-TTSを、漢字の読み・自然さ・感情表現の3観点で、自動指標と115票のブラインド聴き比べで比べます。結論だけ先に言うと、私の耳は自分の思い込みに負けていました。
真っ暗な画面を見つめる五十路の夜は、正直、ちょっと不安だった。


コメント