feat(train): Super-MAS Triton-GPU MAS accelerator (opt-in、 推論影響ゼロ) - #582
Conversation
arXiv:2409.07706 (Park et al., 2024) の Triton kernel に dispatch することで 学習時 MAS を 19-72x 高速化。 既存 Cython は CPU / package 未導入 / PIPER_DISABLE_SUPER_MAS=1 時のフォールバックとして温存し、 学習・推論の 互換性を破壊しない。 SynthesizerTrn.forward の唯一の MAS 呼び出し点 (models.py:964) を通じて自動 dispatch される。 - monotonic_align/__init__.py: _use_super_mas() で CUDA tensor + package available + cuda.is_available() を判定、 該当時のみ _maximum_path_super_mas() に分岐 (upstream は input を破壊変更するため clone + float32 + int32 mask cast) - pyproject.toml: super-mas optional extra (git+https のみ、 PyPI 非配布) - test_super_mas_dispatch.py: dispatcher 選択 4 件 + Cython fallback 2 件 + Super-MAS wrapper contract 3 件 (clone / dtype / int32 mask、 全て mock で GPU/Triton 非依存) - CLAUDE.md: 学習補助セクションに opt-in install + env disable を追記 テスト: 既存 8 件 + 新規 8 件 = 16/16 pass (CPU 環境、 GPU テストは skip)
前 commit (5014254) でカバー漏れた 2 領域を補完: - TestPublicMaximumPathDispatch (2 件): 公開 API maximum_path() 内の `if _use_super_mas(): return _maximum_path_super_mas(...)` 分岐自体を predicate mock で True/False 両側で検証。 個別ヘルパーは既存テストで カバー済だが、 dispatcher の wiring (どちらの関数が実際に呼ばれるか) は別契約のため独立テスト化 - TestEnvDisableImportTime (11 件): PIPER_DISABLE_SUPER_MAS の import-time 動作を subprocess で検証。 truthy (1/true/yes/TRUE/Yes) 5 件 + non-truthy (0/false/no/空文字/それ以外) 5 件 + unset 1 件。 _SUPER_MAS_DISABLED flag と _super_mas_fn=None 化の両方を確認 テスト件数: 既存 8 (test_monotonic_align) + 既存 8 (前 commit 分) + 新規 13 = 29/29 pass (subprocess test 含むため 67 秒) 既存 test_monotonic_align.py は Cython MAS contract を検証しており、 dispatcher 経由でも Cython fallback path として通る contract に変更が ないため修正不要 (実測でも 8/8 pass を確認)
Required status-check gate (deferred)Head SHA |
Distroless migration trial:
|
| metric | canonical (Dockerfile.cpu) |
distroless trial | delta |
|---|---|---|---|
| image size (linux/amd64) | 1.4GB | 760MB | -44.8% |
Smoke results
All imports passed in a single docker run: ONNX Runtime (CPU EP) / piper_train / FastAPI / uvicorn / soundfile.
Not in this trial (follow-up PR)
- linux/arm64 buildx (Pi / Apple Silicon / HA boxes)
- HF Space staging deploy + cold-start latency comparison (user manual)
/v1/audio/speechend-to-end with a real model fixture (CI lacks the ONNX model bundle)- CVE scan diff (Trivy) — wired up alongside the canonical
Dockerfile.cpupromotion PR
Audio MOS Proxy (informational tier)Samples checked: 30, regressions: 0. No baseline yet — this PR is recording the very first measurement.
|
There was a problem hiding this comment.
Pull request overview
Adds an opt-in training-time dispatch path for Monotonic Alignment Search (MAS) that can use the Triton-GPU Super-MAS implementation when available, while preserving the existing Cython fallback and keeping inference/ONNX paths unchanged.
Changes:
- Introduces a Super-MAS dispatcher in
piper_train.vits.monotonic_alignwith env-based import-time disable and safe fallback to Cython. - Adds an optional
super-masextra to install the upstreamsuper-monotonic-aligndependency via git. - Adds unit tests covering dispatch predicate behavior, wrapper contract behavior, and import-time env disabling.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/python/piper_train/vits/monotonic_align/init.py | Adds Super-MAS optional import/dispatch logic and a wrapper that preserves dtype/device contract while protecting inputs from upstream mutation. |
| src/python/pyproject.toml | Adds an opt-in super-mas extra that installs the upstream accelerator dependency. |
| src/python/tests/test_super_mas_dispatch.py | Adds dispatcher and wrapper unit tests, including an import-time env var contract check via subprocess. |
| CLAUDE.md | Documents the new Super-MAS accelerator option and its intended usage/constraints. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Memory regression (per-language)Threshold: +15% peak RSS vs baseline (warn-only).
Summary: 0 warn / 6 skip / 0 ok. SKIP means the baseline entry is a placeholder (peak_memory_mb: null). The first dev push after this workflow lands is expected to seed the baseline. |
Distroless trial: webui / cpp-inferenceEach canonical Dockerfile is UNCHANGED; the trial Dockerfile sits beside it as (
|
| metric | canonical | distroless trial | delta |
|---|---|---|---|
| image size (linux/amd64) | 237MB | 232MB | -2.2% |
Smoke entrypoint: /usr/local/bin/piper — passed.
webui
Trial Dockerfile: docker/webui/Dockerfile.distroless. Canonical docker/webui/Dockerfile is UNCHANGED.
| metric | canonical | distroless trial | delta |
|---|---|---|---|
| image size (linux/amd64) | 941MB | 760MB | -19.2% |
Smoke entrypoint: /usr/bin/python3 — passed.
Not in these trials (follow-up promotion PRs)
- linux/arm64 buildx coverage is handled by
docker-build.yml(build-distroless-trialsmatrix). - CVE Trivy diff lives in
trivy-container-scan.yml(per-image SARIF upload). - For
webui: full Gradio cold-start under distroless (a realdocker run -p 7860:7860fromwebui-test.yml) is the promotion gate. - For
cpp-inference: end-to-endpiper --model ... --output_file ...with a real model fixture is the promotion gate.
Runtime Parity Deep — audio (informational tier)Pairs compared: 15, failing: 15, runtimes skipped: 0.
|
Multi-Runtime RTF BenchmarkPolicy: warn-only (thresholds: RTF +/-10%, P50 +/-10%, P95 +/-15%) Model:
|
PR #582 unresolved review threads 2 件への対応: 1. **pyproject.toml**: super-monotonic-align を unpinned HEAD から commit SHA (9bb1cb3a6fbab27bbe6e566827b9548010c5dd51) に pin。 再現性確保と supply-chain hygiene のため。 SHA は学習で validate 済みの kernel revision を指す。 bump は手動 re-validation 後にのみ実施 (Copilot 指摘 #2) 2. **test_super_mas_dispatch.py**: subprocess の env 構築方法を hand-built dict から os.environ.copy() に変更し、 PYTHONPATH に src/python を明示的に prepend。 これにより: - Windows の SystemRoot を意図せず override する問題を回避 - piper_train が editable-install されていない環境でも subprocess が piper_train を import 可能 (conftest.py の sys.path injection が subprocess に届かない問題、 Copilot 指摘 #1) テスト: 29/29 pass (既存 8 + 拡張 21、 88 秒、 subprocess test 11 件含む)
PR #583 初回 CI で pre-commit が 2 hook fail: 1. check-shebang-scripts-are-executable - scripts/check_hf_space_gradio_sync.py が shebang 付きで commit されたが git index の executable bit が 100644 のまま (Windows から add した時の既定動作) - 修正: git update-index --chmod=+x で 100755 に変更 2. artifact-retention-contract.toml gate (root cause: uv.lock drift) - 本 PR の .github/workflows/*.yml 変更が artifact-retention hook の file filter に match し hook が起動。 hook は uv run python ... で実行され、 uv が PR #582 (Super-MAS) で導入された [project.optional-dependencies] super-mas を uv.lock に未反映 と検出して auto-sync (super-monotonic-align git dep + provides- extras に super-mas を追加) - hook 自体は "aligned with all upload steps" を出して contract toml に変更なし。 uv.lock の方が "files were modified by this hook" として fail 判定された - 修正: 同期された uv.lock を commit (#582 マージ後の latent drift を解消、 本 PR の workflow 変更でたまたま surface した)
* fix(hf-space): gradio sdk_version drift を解消 + CI ゲート追加 HF Space (ayousanz/piper-plus-demo) が BUILD_ERROR で起動不能だった。 README frontmatter sdk_version=6.9.0 と requirements.txt gradio==6.16.0 が drift し、 HF Spaces ビルダーが pip install gradio==6.9.0 -r requirements.txt を 1 コマンドで実行するため resolution conflict で exit 1 (HF API は "cache miss" という misleading なメッセージで 覆い隠していた)。 修正: - huggingface-space/README.md: sdk_version を 6.16.0 に同期 (即時復旧) - scripts/check_hf_space_gradio_sync.py: 両者の exact pin 一致を検査 する script を追加 (drift 時 exit 1 + 修正手順を提示) - .gitignore: 新 script を allowlist に追加 (check_*.py blanket ignore 対策) - .github/workflows/test-hf-space.yml: Layer 0 として gate を追加 (deps install 前に fail fast、 PR 段階で検出) - .github/workflows/deploy-huggingface.yml: upload_folder 直前にも 同 gate を追加 (web UI 編集 / force-push の last-line defense) 根本原因は Dependabot #551 (2026-06-06) が requirements.txt のみ gradio 6.14.0 → 6.16.0 に bump し README frontmatter を同期しなかった こと。 gate により同種 drift を CI で事前検知可能。 * fix(ci): pre-commit fail 2 件を解消 (chmod + uv.lock drift) PR #583 初回 CI で pre-commit が 2 hook fail: 1. check-shebang-scripts-are-executable - scripts/check_hf_space_gradio_sync.py が shebang 付きで commit されたが git index の executable bit が 100644 のまま (Windows から add した時の既定動作) - 修正: git update-index --chmod=+x で 100755 に変更 2. artifact-retention-contract.toml gate (root cause: uv.lock drift) - 本 PR の .github/workflows/*.yml 変更が artifact-retention hook の file filter に match し hook が起動。 hook は uv run python ... で実行され、 uv が PR #582 (Super-MAS) で導入された [project.optional-dependencies] super-mas を uv.lock に未反映 と検出して auto-sync (super-monotonic-align git dep + provides- extras に super-mas を追加) - hook 自体は "aligned with all upload steps" を出して contract toml に変更なし。 uv.lock の方が "files were modified by this hook" として fail 判定された - 修正: 同期された uv.lock を commit (#582 マージ後の latent drift を解消、 本 PR の workflow 変更でたまたま surface した) * fix(review): Copilot 指摘 4 件を解消 PR #583 で Copilot reviewer から指摘された 4 件 (すべて logic / correctness、 style noise ではない) を修正。 1. docstring と実装の exit code 不一致 (line 26) 旧: "exit 0 if both fields are absent" 実装: 片方 None でも errors.append → exit 1 → docstring を実装に揃え、 空 pin も malformed として exit 1 を明記 2. 空 sdk_version 値を silently OK 化 (line 58) `sdk_version:` (値なし) で `""` を返し main の `is None` チェックを bypass → drift 検出を skip → `value or None` で空文字を None に正規化、 統一的に malformed 扱い 3. 非 f-string で `{sdk_version}` がリテラル出力 (line 104) エラーメッセージの該当行に `f` prefix が抜けていた → f-string 化、 実値を埋め込んで debug 性向上 (例: `gradio[oauth,mcp]==6.9.0`) 4. deploy-huggingface.yml gate が setup-python の前 (line 53) script が `str | None` 等 Python 3.10+ 構文を使うのに runner 既定 `python3` (バージョン非保証) に依存 → Set up Python を Setup deployment 直後に移動し、 gate を後に配置。 後段の重複 setup-python step は削除、 `python3` を `python` に統一 * feat(ci): HF Space deploy 前後の検証を追加 (BUILD_ERROR / RUNTIME_ERROR 即時検知) PR #583 の sdk_version drift 修正に続く防御層追加。 既存検証では deploy upload 成功 = 0 exit で workflow が green になり、 HF Space が BUILD_ERROR / RUNTIME_ERROR / CONFIG_ERROR / NO_APP_FILE で起動失敗していても誰も気付かな かった (2026-06 incident の根本原因)。 追加内容: 1. scripts/check_hf_space_frontmatter.py (F1-F4 対策) README YAML frontmatter の schema gate: - 必須フィールド (title / sdk / sdk_version / app_file) の存在 - app_file が huggingface-space/ 配下に実在 - sdk が gradio / streamlit / docker / static のいずれか - YAML が parse 可能 ruff + manual テスト (F1/F2/F3/F4 全 fail シナリオ + 正常 PASS) で動作確認。 2. scripts/verify_hf_space_runtime.py (F5 対策、 universal safety net) upload_folder 完了後、 HfApi.get_space_runtime を ~10 min poll し RUNNING / RUNNING_BUILDING / APP_STARTING のいずれかに到達するか BUILD_ERROR / RUNTIME_ERROR 等で fail するかを検出。 タイムアウト時も fail (build hang を可視化)。 standalone 実行可能 (manual debug 用)。 3. test-hf-space.yml: Layer 0.5 (frontmatter) + Layer 2.1 (pip check) + Layer 5 を `import app` から `create_interface()` まで拡張 (gradio API breaking change を runtime 起動前に検知)。 4. deploy-huggingface.yml: Set up Python + pre-deploy frontmatter gate + post-deploy 10-min runtime verification。
pyproject.toml `[super-mas]` extra (arXiv:2409.07704, PR #582) は CLAUDE.md で opt-in 推奨として文書化済みだが、 docker/python-train/Dockerfile 側で 反映されておらず A100 学習で MAS が Cython fallback していた。 - Dockerfile builder stage に `uv pip install "[super-mas]"` を追加 (git+https 依存、 builder は git 済み) - build-time test に `import super_monotonic_align` の検証を追加。 CPU-only import は安全、 fallback が silent に起こる miss を build 時点で 可視化 v8 zero-shot 学習で MAS step が 3-10% 短縮、 A100 SXM4 80GB で 80 epoch 学習の総 wall-clock を数時間削減する見込み。
pyproject.toml `[super-mas]` extra (arXiv:2409.07704, PR #582) は CLAUDE.md で opt-in 推奨として文書化済みだが、 docker/python-train/Dockerfile 側で 反映されておらず A100 学習で MAS が Cython fallback していた。 - Dockerfile builder stage に `uv pip install "[super-mas]"` を追加 (git+https 依存、 builder は git 済み) - build-time test に `import super_monotonic_align` の検証を追加。 CPU-only import は安全、 fallback が silent に起こる miss を build 時点で 可視化 v8 zero-shot 学習で MAS step が 3-10% 短縮、 A100 SXM4 80GB で 80 epoch 学習の総 wall-clock を数時間削減する見込み。
Summary
学習時の Monotonic Alignment Search (MAS) を Cython から Triton-GPU カーネル (Super-MAS, arXiv:2409.07704, Park et al., 2024) に opt-in で dispatch できるようにしました。 公式 docker stack (Python 3.13 + torch 2.11.0+cu128 + Triton 3.6.0) 上の RTX 4070 Ti SUPER 実測で MAS 単独 38-187x 高速化。 ただし MAS は 1 step 全体の 0.42 % しか占有しない ことが実測で判明したため、 end-to-end の学習短縮効果は 約 0.37 % とマージナル。 推論経路と ONNX グラフへの影響はゼロ、 既存 Cython は CPU / package 未導入 / 環境変数で disable 時のフォールバックとして温存。
Affected Components
Type
Risk Level
Contract Impact
推論経路への影響なし、 ONNX グラフ・cross-runtime contract に変更なし。 学習時
SynthesizerTrn.forward内 1 箇所 (models.py:964) のみで dispatch される。変更内容
super_monotonic_align.maximum_pathが利用可能 + CUDA tensor +torch.cuda.is_available()のすべて満たすときのみ Triton kernel に分岐、 それ以外は既存 Cython パスへフォールバック_maximum_path_super_mas内でvalue.clone()してから kernel へ渡す。 入力neg_centは不変valueを in-place 変更するため、 caller のneg_centが壊れて学習 loop が破綻PIPER_DISABLE_SUPER_MAS=1/true/yes/TRUE/Yesで import 時に_super_mas_fn = Noneを強制。 再現性デバッグ / bit-identical 比較に利用pyproject.tomlにsuper-mas = ["super-monotonic-align @ git+...@<sha>"]を追加。 unpinned HEAD ではなく 特定 commit SHA で pin (再現性 + supply-chain hygiene)。trainextra には含めず完全 opt-in_use_super_maspredicate /_maximum_path_super_maswrapper / 公開maximum_path()の if 分岐統合点 / env import-time 動作 (subprocess) を網羅。 subprocess test はos.environ.copy()で親 env 継承 +PYTHONPATH明示 prepend設計判断
PIPER_DISABLE_SUPER_MAS=1→ 強制 Cython。 デフォルト挙動は完全に Cython 不変trainextra には含めず分離: upstream は GitHub のみで配布。 git+https をtrainに混ぜるとpip install piper-train[train]時にネットワーク fetch が必須となり、 CI / offline 環境で fail する。[super-mas]を独立 extra にすることで「明示的に opt-in した時のみ git+ install」となるmax_neg_valedge case を修正済)。 docstring / CLAUDE.md でも「algorithmic equivalence」と明記して過剰な主張を避ける_use_super_masを independent predicate に切り出し: maximum_path() 内に直接書かず関数化することで、 テスト時に predicate のみを mock 可能。 GPU 不在環境でも dispatcher 分岐の wiring を検証できるvalue.detach().to(float32).contiguous().clone(): upstream はvalueを in-place 変更するため clone 必須。 detach は autograd graph から切る (MAS は学習時torch.no_grad()配下で呼ばれるが明示する)、 contiguous は Triton kernel が strided memory を扱えない可能性に備えるos.environ.copy()ベース: hand-built env では (a) WindowsSystemRootを case-insensitive で上書きする可能性、 (b) editable-install されていない piper_train を subprocess から見つけられない、 の 2 リスクがあった。 親 env 継承 +PYTHONPATH明示 prepend で両方解消ベンチマーク
計測環境: RTX 4070 Ti SUPER (16GB Ada Lovelace) + WSL2 Ubuntu + Python 3.13.14 + torch 2.11.0+cu128 + Triton 3.6.0 (piper-plus 公式 docker stack と一致)
MAS 単独 (synthetic, B=20, T=64-400, S=4T)
triton.testing.do_bench(rep=50, warmup=5)、 MAS のみの wall-time 比較。End-to-end (実 SynthesizerTrn 1 step, B=8, T=128, T_y=512)
forward + backward + optimizer.step 1 step を Triton ON / Cython OFF で各 30 回計測 (warmup 15)。 MAS 呼び出しを patch して MAS 部分のみの wall-time も同時計測。
実測値から計算した end-to-end 短縮: 0.42 % × (1 − 1/9.4) ≈ 0.37 %
= 1 epoch 8h53m に対して 約 2 分短縮 にとどまる。 これは Glow-TTS 論文の「MAS は学習全体の 2% 未満」推定とも整合的 (実測ではむしろ更に低い 0.42%)。
つまり: MAS 単独では大幅高速化するが、 学習 step 全体に占める MAS の割合が小さいため、 1 epoch wall-clock の短縮は実用上マージナル。 大バッチ + 長文 dataset (T=400+) で MAS 占有率がわずかに上がる可能性はあるが、 桁が変わるほどではない。 本 PR の意義は wall-clock 短縮よりも (a) CPU↔GPU 転送オーバーヘッド除去、 (b) 大バッチ時の MAS スパイク解消、 (c) GPU bound にできる範囲を広げる、 にある。
Test Plan
cd src/python && uv run --no-sync pytest tests/test_monotonic_align.py tests/test_super_mas_dispatch.py --no-cov -vで 29 件 (既存 8 + 新規 21) すべて passuv run --no-sync ruff check src/python/piper_train/vits/monotonic_align/__init__.py src/python/tests/test_super_mas_dispatch.pyで lint cleanuv run --no-sync ruff format --check src/python/piper_train/vits/monotonic_align/__init__.py src/python/tests/test_super_mas_dispatch.pyで format cleanpython -c "from piper_train.vits import monotonic_align; print(monotonic_align._SUPER_MAS_DISABLED)"がFalseを返すPIPER_DISABLE_SUPER_MAS=1環境で同コマンドがTrueを返し、_super_mas_fn is Noneになるpip install "piper-train[super-mas]"後に短い学習 step を回し、 既存 Cython 結果と SECS / loss が乖離しないことを確認 (本 PR の merge 後の follow-up でも可)Checklist
Related Issues
なし (
docs/research/architecture-replacement-survey-2026-06-27.md§4.1.1 で adopt 推奨されていた候補の 1 件目)