pltobing commited on
Commit
5f75b85
Β·
1 Parent(s): 9fab525

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
- # self._codec_decoder_sess = _sess(codec_decoder_model_path, graph=self._enable_cuda_graph)
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
- # b.bind_input_device("codes", self._codec_codes_ov)
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
- # Re-bind the two small dynamic inputs (H→D copy, ~4 KB total)
1323
- b.bind_input_cpu("codes", chunk_tokens)
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} chunk_tokens {chunk_tokens} {chunk_tokens.shape}"
 
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
- wav = self._run_codec_decoder(chunk_tokens, pos).copy()
 
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)