fix(gaps): G0/G2/G5/G8 — eliminate unimplemented! panics, re-enable rtx-distributed, rtx-tts, fix multimodal forward

G0 (Critical): Replace 45 unimplemented!() panics across three GPU backends
- rtx-backend-cuda: sin/cos/tanh via PTX, relu/sigmoid/leaky_relu/elu via activation.rs,
  pow/clamp/gt_scalar via unary.rs, var/var_dim host-side, conv2d/max_pool2d/avg_pool2d
  CPU fallback in new ops/conv.rs; new PTX kernels in element_wise.cu
- rtx-backend-rocm: all 15 ops via CPU round-trip (to_vec → compute → from_slice)
- rtx-backend-sycl: all 15 ops via CPU round-trip (to_host → compute → from_data)

G2 (High): Re-add rtx-distributed to workspace
- Vendor 4 minimal RNCCL stub crates at crates/vendor/rnccl/*
- Update rtx-distributed RNCCL path deps to point at stubs (../../../../RNCCL/* → ../../vendor/rnccl/*)
- Remove rtx-distributed from workspace exclude list, add to members

G5 (Medium): Re-enable rtx-tts (213 tests restored)
- Fix 15 rtx-nn API drift issues: LayerNorm::new, Conv1d::from_config, Conv1dPadding::Zeros,
  Dropout::new(p, device), tensor methods (relu/tanh/sigmoid/cat/stack), squeeze(Some(n)),
  to_vec() turbofish removal, Tensor::randn with &[...] slices

G8 (Low): Quantum stubs + multimodal forward bug
- rtx-timeseries: remove dead quantum/neuromorphic TODO comment blocks (no module files exist)
- rtx-multimodal/fusion/transformer.rs: wire TransformerBlock loop in forward()
- rtx-multimodal/fusion/strategies.rs: wire bottleneck_layers loop in forward()
- rtx-transformers/architectures/transformer_block.rs: add forward() method (pre-norm residuals;
  full attention+FFN pending when those sub-layers are wired)

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-26 13:40:23 +00:00
co-authored by Claude Sonnet 4.6
parent 57e5252caa
commit 228137555f
37 changed files with 1509 additions and 215 deletions
@@ -3,10 +3,14 @@
//! The variance adaptor predicts duration, pitch, and energy to control
//! prosody in non-autoregressive TTS models.
// Legacy rtx_nn layer types are deprecated in favour of Generic* variants.
// rtx-tts uses the concrete-tensor API and does not yet require backend dispatch.
#![allow(deprecated)]
use crate::Result;
use rtx_nn::layers::{Module, linear::Linear};
use rtx_nn::layers::activation::ReLU;
use rtx_nn::layers::conv::{Conv1d, Conv1dConfig};
use rtx_nn::layers::conv::{Conv1d, Conv1dConfig, Conv1dPadding};
use rtx_tensor::{Tensor, Device};
use serde::{Deserialize, Serialize};
@@ -142,6 +146,7 @@ impl DurationPredictor {
kernel_size: config.kernel_size,
stride: 1,
padding,
padding_mode: Conv1dPadding::Zeros(padding),
dilation: 1,
groups: 1,
bias: true,
@@ -203,7 +208,7 @@ impl DurationPredictor {
.map_err(|e| crate::TtsError::ModelError(format!("Linear forward failed: {e}")))?;
// Squeeze last dimension: [batch, seq_len, 1] -> [batch, seq_len]
let squeezed = output.squeeze(2)
let squeezed = output.squeeze(Some(2))
.map_err(|e| crate::TtsError::TensorError(format!("Squeeze failed: {e}")))?;
// Apply softplus to ensure positive durations
@@ -246,6 +251,7 @@ impl PitchPredictor {
kernel_size: config.kernel_size,
stride: 1,
padding,
padding_mode: Conv1dPadding::Zeros(padding),
dilation: 1,
groups: 1,
bias: true,
@@ -300,7 +306,7 @@ impl PitchPredictor {
let output = self.linear.forward(&hidden)
.map_err(|e| crate::TtsError::ModelError(format!("Linear forward failed: {e}")))?;
output.squeeze(2)
output.squeeze(Some(2))
.map_err(|e| crate::TtsError::TensorError(format!("Squeeze failed: {e}")))
}
@@ -341,6 +347,7 @@ impl EnergyPredictor {
kernel_size: config.kernel_size,
stride: 1,
padding,
padding_mode: Conv1dPadding::Zeros(padding),
dilation: 1,
groups: 1,
bias: true,
@@ -396,7 +403,7 @@ impl EnergyPredictor {
let output = self.linear.forward(&hidden)
.map_err(|e| crate::TtsError::ModelError(format!("Linear forward failed: {e}")))?;
let squeezed = output.squeeze(2)
let squeezed = output.squeeze(Some(2))
.map_err(|e| crate::TtsError::TensorError(format!("Squeeze failed: {e}")))?;
// Apply softplus to ensure positive energy
@@ -434,7 +441,7 @@ impl LengthRegulator {
let hidden_dim = shape.dims()[2];
// Convert durations to integers
let durations_data = durations.to_vec::<f32>()
let durations_data = durations.to_vec()
.map_err(|e| crate::TtsError::TensorError(format!("Failed to get durations: {e}")))?;
let mut outputs = Vec::new();
@@ -449,7 +456,7 @@ impl LengthRegulator {
let start_idx = b * seq_len * hidden_dim + i * hidden_dim;
let end_idx = start_idx + hidden_dim;
let hidden_data = hidden.to_vec::<f32>()
let hidden_data = hidden.to_vec()
.map_err(|e| crate::TtsError::TensorError(format!("Failed to get hidden: {e}")))?;
let frame = &hidden_data[start_idx..end_idx];
@@ -602,7 +609,7 @@ mod tests {
assert_eq!(shape.dims()[1], seq_len);
// Check all durations are positive
let data = output.to_vec::<f32>().unwrap();
let data = output.to_vec().unwrap();
assert!(data.iter().all(|&x| x >= 0.0));
}