fix: bind all inputs for codec decoder
Browse files- Similarly as previous commit, all inputs'
shapes to codec decoder are static
and can be bound.
- Using in-place to copy numpy array to
the buffers.
- The `chunk_tokens` need additional `.copy()`
before passed on to the function to run
the graph. Without this additional `.copy()`,
not using CUDA graph and/or not using IOBinding
is fine, but if we bind it and/or enable CUDA
graph, it has to use the additional `.copy()`,
otherwise the output is messed up.
- Right now, all main modules: talker, local,
local lm_head, and codec decoder are able
to be run with the accelerated CUDA graphs.
- Still need to further improve by removing
unnecessary `Ops`.
src/inference/qwen3_tts_inferencer_onnx.py
CHANGED
|
@@ -440,8 +440,7 @@ class Qwen3TTSInferencerONNX:
|
|
| 440 |
|
| 441 |
# Non-graphed utility sessions
|
| 442 |
log.info(f" codec decoder <- {codec_decoder_model_path}")
|
| 443 |
-
|
| 444 |
-
self._codec_decoder_sess = _sess(codec_decoder_model_path, graph=False)
|
| 445 |
log.info(f" speaker encoder <- {speaker_encoder_model_path}")
|
| 446 |
self._speaker_encoder = _sess(speaker_encoder_model_path, graph=False)
|
| 447 |
log.info(f" codec embed <- {talker_codec_embed_model_path}")
|
|
@@ -765,7 +764,7 @@ class Qwen3TTSInferencerONNX:
|
|
| 765 |
b.bind_output_device("current_hidden_state_cache", self._codec_hidden_cache_ov)
|
| 766 |
b.bind_output_device("current_pre_conv_hidden_state_cache", self._codec_pre_conv_cache_ov)
|
| 767 |
|
| 768 |
-
|
| 769 |
b.bind_input_device("cache_position", self._codec_cache_position_ov)
|
| 770 |
b.bind_input_device("hidden_state_cache", self._codec_hidden_cache_ov)
|
| 771 |
b.bind_input_device("pre_conv_hidden_state_cache", self._codec_pre_conv_cache_ov)
|
|
@@ -1319,17 +1318,12 @@ class Qwen3TTSInferencerONNX:
|
|
| 1319 |
) -> np.ndarray:
|
| 1320 |
"""Execute one Codec Decoder step via IOBinding and return wav as NumPy."""
|
| 1321 |
b = self._codec_decoder_bound
|
| 1322 |
-
#
|
| 1323 |
-
|
| 1324 |
-
# log.info(f"run_codec_decoder chunk_tokens {chunk_tokens.shape} {chunk_tokens.dtype}")
|
| 1325 |
-
# b.bind_input_cpu("cache_position", pos)
|
| 1326 |
-
# log.info(f"run_codec_decoder pos {pos.shape} {pos.dtype}")
|
| 1327 |
-
# _copy_numpy_to_ortvalue(chunk_tokens, self._codec_codes_ov)
|
| 1328 |
_copy_numpy_to_ortvalue(pos, self._codec_cache_position_ov)
|
| 1329 |
# All KV and output bindings are already wired statically
|
| 1330 |
b.run()
|
| 1331 |
# Copy wav to CPU
|
| 1332 |
-
# return b.get_output_numpy("wav")
|
| 1333 |
return self._codec_wav_ov.numpy()
|
| 1334 |
|
| 1335 |
# ββ Main autoregressive step ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -1481,8 +1475,8 @@ class Qwen3TTSInferencerONNX:
|
|
| 1481 |
None, :, :
|
| 1482 |
] # [1, 1, 16]
|
| 1483 |
|
| 1484 |
-
self._last_audio_tokens = audio_tokens
|
| 1485 |
-
self._generated_tokens = np.concatenate([self._generated_tokens, audio_tokens], axis=1)
|
| 1486 |
|
| 1487 |
# ββ Warmup (triggers CUDA graph capture) βββββββββββββββββββββββββββββββββ
|
| 1488 |
|
|
@@ -1753,7 +1747,8 @@ class Qwen3TTSInferencerONNX:
|
|
| 1753 |
axis=-1,
|
| 1754 |
)
|
| 1755 |
log.info(
|
| 1756 |
-
f"codec-idx-{self._codec_step_idx} len_pad_right {len_pad_right}
|
|
|
|
| 1757 |
)
|
| 1758 |
|
| 1759 |
# cache_position for the decoder transformer
|
|
@@ -1762,7 +1757,8 @@ class Qwen3TTSInferencerONNX:
|
|
| 1762 |
self._codec_step_idx += chunk_tokens.shape[-1]
|
| 1763 |
|
| 1764 |
# Run the wired graph
|
| 1765 |
-
|
|
|
|
| 1766 |
# new memory address, so that output wav not only the last repeated
|
| 1767 |
|
| 1768 |
# The decoder output already discards the upsampled left-context frames (25 frames)
|
|
|
|
| 440 |
|
| 441 |
# Non-graphed utility sessions
|
| 442 |
log.info(f" codec decoder <- {codec_decoder_model_path}")
|
| 443 |
+
self._codec_decoder_sess = _sess(codec_decoder_model_path, graph=self._enable_cuda_graph)
|
|
|
|
| 444 |
log.info(f" speaker encoder <- {speaker_encoder_model_path}")
|
| 445 |
self._speaker_encoder = _sess(speaker_encoder_model_path, graph=False)
|
| 446 |
log.info(f" codec embed <- {talker_codec_embed_model_path}")
|
|
|
|
| 764 |
b.bind_output_device("current_hidden_state_cache", self._codec_hidden_cache_ov)
|
| 765 |
b.bind_output_device("current_pre_conv_hidden_state_cache", self._codec_pre_conv_cache_ov)
|
| 766 |
|
| 767 |
+
b.bind_input_device("codes", self._codec_codes_ov)
|
| 768 |
b.bind_input_device("cache_position", self._codec_cache_position_ov)
|
| 769 |
b.bind_input_device("hidden_state_cache", self._codec_hidden_cache_ov)
|
| 770 |
b.bind_input_device("pre_conv_hidden_state_cache", self._codec_pre_conv_cache_ov)
|
|
|
|
| 1318 |
) -> np.ndarray:
|
| 1319 |
"""Execute one Codec Decoder step via IOBinding and return wav as NumPy."""
|
| 1320 |
b = self._codec_decoder_bound
|
| 1321 |
+
# Copy numpy inputs to buffer in-place
|
| 1322 |
+
_copy_numpy_to_ortvalue(chunk_tokens, self._codec_codes_ov)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1323 |
_copy_numpy_to_ortvalue(pos, self._codec_cache_position_ov)
|
| 1324 |
# All KV and output bindings are already wired statically
|
| 1325 |
b.run()
|
| 1326 |
# Copy wav to CPU
|
|
|
|
| 1327 |
return self._codec_wav_ov.numpy()
|
| 1328 |
|
| 1329 |
# ββ Main autoregressive step ββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 1475 |
None, :, :
|
| 1476 |
] # [1, 1, 16]
|
| 1477 |
|
| 1478 |
+
self._last_audio_tokens = audio_tokens.copy()
|
| 1479 |
+
self._generated_tokens = np.concatenate([self._generated_tokens, audio_tokens.copy()], axis=1)
|
| 1480 |
|
| 1481 |
# ββ Warmup (triggers CUDA graph capture) βββββββββββββββββββββββββββββββββ
|
| 1482 |
|
|
|
|
| 1747 |
axis=-1,
|
| 1748 |
)
|
| 1749 |
log.info(
|
| 1750 |
+
f"codec-idx-{self._codec_step_idx} len_pad_right {len_pad_right} "
|
| 1751 |
+
f"chunk_tokens {chunk_tokens} {chunk_tokens.shape}"
|
| 1752 |
)
|
| 1753 |
|
| 1754 |
# cache_position for the decoder transformer
|
|
|
|
| 1757 |
self._codec_step_idx += chunk_tokens.shape[-1]
|
| 1758 |
|
| 1759 |
# Run the wired graph
|
| 1760 |
+
# chunk_tokens need to be .copy(), otherwise it messed up if we bind input and/or use CUDA graph
|
| 1761 |
+
wav = self._run_codec_decoder(chunk_tokens.copy(), pos).copy()
|
| 1762 |
# new memory address, so that output wav not only the last repeated
|
| 1763 |
|
| 1764 |
# The decoder output already discards the upsampled left-context frames (25 frames)
|