From ecc3f101526c8fe0b19cf4c412f3904c85e9366f Mon Sep 17 00:00:00 2001 From: tuna2134 Date: Thu, 2 Jul 2026 15:17:37 +0000 Subject: [PATCH] =?UTF-8?q?"/"=20=E3=81=AB=E3=83=95=E3=82=A1=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E3=82=92=E3=82=A2=E3=83=83=E3=83=97=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changes.patch | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 changes.patch diff --git a/changes.patch b/changes.patch new file mode 100644 index 0000000..316b6b8 --- /dev/null +++ b/changes.patch @@ -0,0 +1,169 @@ +diff --git a/scripts/convert/README.md b/scripts/convert/README.md +index 3dbf86d..60dc1c1 100644 +--- a/scripts/convert/README.md ++++ b/scripts/convert/README.md +@@ -25,6 +25,24 @@ + python convert_model.py --style_file "ここにstyle_vectors.npyの場所" --config_file "同様にconfig.json場所" --model_file "同様に.safetensorsで終わるファイルの場所" + ``` + ++TensorRT用のモデルを生成する場合は `--tensorrt` を追加します。 ++ ++```sh ++python convert_model.py --tensorrt --style_file "style_vectors.npy" --config_file "config.json" --model_file "model.safetensors" ++``` ++ ++TensorRTモードでは、非対応Opを含む確率的 Duration Predictor の代わりに決定論的 Duration Predictor を使用します。また、`RandomNormalLike` はTensorRT対応の要素演算による決定論的ノイズへ置換されます。 ++ ++### trtexecで検証 ++ ++変換したONNXからTensorRTエンジンをビルドし、実データ型のダミー入力で1回推論します。 ++ ++```sh ++uv run python test_tensorrt.py ../../models/model_名前.onnx --fp16 ++``` ++ ++`trtexec` がPATHにない場合は `--trtexec /path/to/trtexec` または環境変数 `TRTEXEC` で指定します。デフォルトの動的長プロファイルは1~256、最適値とテスト値は32です。必要に応じて `--min-length`、`--opt-length`、`--max-length`、`--test-length` を指定できます。追加の `trtexec` 引数は `--` の後ろへ渡します。 ++ + 4. `models/名前.sbv2`というファイルが出力されます。GUI版のモデルファイルに入れてあげたら使えます。 + + ## Deberta変換 +diff --git a/scripts/convert/convert_model.py b/scripts/convert/convert_model.py +index 689809b..d054f83 100644 +--- a/scripts/convert/convert_model.py ++++ b/scripts/convert/convert_model.py +@@ -4,6 +4,7 @@ from io import BytesIO + from style_bert_vits2.nlp import bert_models + from style_bert_vits2.constants import Languages + from style_bert_vits2.models.infer import get_net_g, get_text ++from style_bert_vits2.models import commons + from style_bert_vits2.models.hyper_parameters import HyperParameters + import torch + from style_bert_vits2.constants import ( +@@ -23,6 +24,11 @@ parser = ArgumentParser() + parser.add_argument("--style_file", required=True) + parser.add_argument("--config_file", required=True) + parser.add_argument("--model_file", required=True) ++parser.add_argument( ++ "--tensorrt", ++ action="store_true", ++ help="Export a TensorRT-compatible deterministic inference graph.", ++) + args = parser.parse_args() + style_file = args.style_file + config_file = args.config_file +@@ -94,20 +100,70 @@ model = get_net_g( + ) + + +-def forward(x, x_len, sid, tone, lang, bert, style, length_scale, sdp_ratio, noise_scale, noise_scale_w): +- return model.infer( +- x, +- x_len, +- sid, +- tone, +- lang, +- bert, +- style, +- sdp_ratio=sdp_ratio, +- length_scale=length_scale, +- noise_scale=noise_scale, +- noise_scale_w=noise_scale_w, ++def _tensorrt_noise_like(value, phase): ++ """Generate deterministic noise using TensorRT-supported elementwise ops.""" ++ indices = torch.arange( ++ value.numel(), dtype=value.dtype, device=value.device ++ ).reshape_as(value) ++ # A sum of independent-looking sinusoids has approximately normal variance. ++ return ( ++ torch.sin(indices * 12.9898 + phase) ++ + torch.sin(indices * 78.233 + phase * 1.37) ++ + torch.sin(indices * 37.719 + phase * 2.11) ++ ) * 0.816496580927726 ++ ++ ++def forward( ++ x, ++ x_len, ++ sid, ++ tone, ++ lang, ++ bert, ++ style, ++ length_scale, ++ sdp_ratio, ++ noise_scale, ++ noise_scale_w, ++): ++ if not args.tensorrt: ++ return model.infer( ++ x, ++ x_len, ++ sid, ++ tone, ++ lang, ++ bert, ++ style, ++ sdp_ratio=sdp_ratio, ++ length_scale=length_scale, ++ noise_scale=noise_scale, ++ noise_scale_w=noise_scale_w, ++ ) ++ ++ # The stochastic duration predictor contains NonZero and ScatterND, and ++ # torch.randn_like exports as RandomNormalLike. Those operators cannot be ++ # compiled by TensorRT. Use the deterministic duration predictor and create ++ # latent noise from elementwise operations instead. ++ g = model.emb_g(sid).unsqueeze(-1) ++ hidden, m_p, logs_p, x_mask = model.enc_p( ++ x, x_len, tone, lang, bert, style, g=g + ) ++ logw = model.dp(hidden, x_mask, g=g) ++ w = torch.exp(logw) * x_mask * length_scale ++ w_ceil = torch.ceil(w) ++ y_lengths = torch.clamp_min(torch.sum(w_ceil, [1, 2]), 1).long() ++ y_mask = commons.sequence_mask(y_lengths, None).unsqueeze(1).to(x_mask.dtype) ++ attn_mask = x_mask.unsqueeze(2) * y_mask.unsqueeze(-1) ++ attn = commons.generate_path(w_ceil, attn_mask) ++ m_p = torch.matmul(attn.squeeze(1), m_p.transpose(1, 2)).transpose(1, 2) ++ logs_p = torch.matmul(attn.squeeze(1), logs_p.transpose(1, 2)).transpose(1, 2) ++ # Keep both legacy controls as part of the deterministic phase so the ONNX ++ # input contract remains compatible with existing runtimes. ++ phase = noise_scale_w + sdp_ratio ++ z_p = m_p + _tensorrt_noise_like(m_p, phase) * torch.exp(logs_p) * noise_scale ++ z = model.flow(z_p, y_mask, g=g, reverse=True) ++ return model.dec(z * y_mask, g=g) + + + model.forward = forward +@@ -128,6 +184,9 @@ torch.onnx.export( + torch.tensor(0.8), + ), + f"../../models/model_{out_name}.onnx", ++ # Preserve the established Style-Bert-VITS2 ONNX graph. The dynamo exporter ++ # (the default in recent PyTorch) cannot lower the complete inference path. ++ dynamo=False, + verbose=True, + dynamic_axes={ + "x_tst": {0: "batch_size", 1: "x_tst_max_length"}, +@@ -153,7 +212,20 @@ torch.onnx.export( + ], + output_names=["output"], + ) +-os.system(f"onnxsim ../../models/model_{out_name}.onnx ../../models/model_{out_name}.onnx") ++onnx_path = f"../../models/model_{out_name}.onnx" ++os.system(f"onnxsim {onnx_path} {onnx_path}") ++ ++if args.tensorrt: ++ import onnx ++ ++ unsupported_ops = {"NonZero", "RandomNormalLike", "ScatterND"} ++ graph_ops = {node.op_type for node in onnx.load(onnx_path).graph.node} ++ remaining_ops = unsupported_ops & graph_ops ++ if remaining_ops: ++ raise RuntimeError( ++ "TensorRT-incompatible operators remain after export: " ++ + ", ".join(sorted(remaining_ops)) ++ ) + onnxfile = open(f"../../models/model_{out_name}.onnx", "rb").read() + stylefile = open(f"../../models/style_vectors_{out_name}.json", "rb").read() + version = bytes("1", "utf8")