You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(training): centralize WGAN-GP + diffusion consumers through fused primitives (#1847)
Closes#1845 and #1846. Routes all four WGAN-GP critics through WganGpFusedStep
(the fused-plan primitive from PR #1843) and adds MultiSlotFusedStep wire-ups
to the three tabular diffusion consumers plus a base-class opt-in hook for
DiffusionModelBase subclasses.
## Optimizer config plumbing
Zero new API surface: IFusedOptimizerSpec.TryGetFusedOptimizerConfig already
exposes (OptimizerType, LR, Beta1, Beta2, Epsilon, WeightDecay, Schedule,
UseBf16Moments). Widened NeuralNetworkBase<T>.TryMapToFusedOptimizerConfig
from private to internal so the sibling generators in the same assembly can
reuse the existing helper.
## WGAN-GP consumers (#1845)
* CTGANGenerator, CopulaGANGenerator, TableGANGenerator, CausalGANGenerator —
each critic training method now attempts WganGpFusedStep.TryStep FIRST with
the discriminator's optimizer hyperparameters extracted via
TryMapToFusedOptimizerConfig, falls back to the existing
GpuResidentFusedStep path (secondary fused), then the eager tape (final
fallback). The ε ∈ [0, 1]^B epsilon sampler uses
Engine.TensorRandomUniformRange to match each critic's local
ComputeGradientPenalty behavior.
* Non-Adam optimizers (Lion, LBFGS) that don't implement IFusedOptimizerSpec
cleanly fall through — TryMapToFusedOptimizerConfig returns false and the
code path skips to GpuResidentFusedStep as before.
## Diffusion consumers (#1846)
* TabDDPMGenerator — refactored to expose a slot-based forward
(BuildTabDDPMSlots + DenoiserForwardFromTensors +
ComputeDiffusionLossTapeFromTensors). Per-row TrainBatch loop now attempts
MultiSlotFusedStep with (numNoisy, actualNoise, catNoisy, catClean,
rawSinusoidalTimeEmbed) as persistent slots. The learnable
_timestepProjection stays INSIDE the compiled forward closure so its
weights participate in the backward pass. Plan is compiled once on the
first row and replayed via slot-data refresh for subsequent rows.
* TabSynGenerator — TrainDiffusionBatch's per-row loop wired with
MultiSlotFusedStep on (noisyLatent, actualNoise, projectedTimeEmbed).
Matches the existing eager path's semantic that _timestepProjection is
NOT in _diffMLPLayers (kept detached in the eager path too), so the
projected embedding is precomputed host-side per row and passed as slot
data.
* Finance/Forecasting/Foundation/CSDI —
- ApplyInstanceNormalization rewritten with traceable engine ops
(ReduceMean + ReduceVariance + TensorSqrt + broadcast subtract/divide) —
same pattern as the TFC RevIN fix. The previous `.Data.Span` per-batch
loop froze at trace time.
- New BuildCsdiSlots + DenoiserForwardFromSlots express the DDPM x_t
formation and packed denoising input via TensorConcatenate + engine
scalar multiplies. Replaces the `.Data.Span[i] = xt[0, i]` fill that
baked the trace batch's x_t into the compiled plan.
- Train() attempts MultiSlotFusedStep first, falls back to the existing
eager ComputeDenoisingPairTape path when the fused path can't engage.
* Diffusion/DiffusionModelBase —
- New opt-in `protected virtual bool SupportsFusedDenoising => false;`
property. Base default is false so no existing subclass changes
behavior.
- Train() attempts MultiSlotFusedStep when SupportsFusedDenoising is true
AND the training optimizer maps cleanly to a fused config. Slots:
(noisySample, noise). Loss = MSE(pred, noise). QAT shadow restoration
is preserved on the fused-success path.
- Subclasses with fully-traceable PredictNoise / PredictNoiseBatched
(e.g. after auditing to remove `.Data.Span` host loops) can opt in via
a single-line override; no infrastructure changes needed elsewhere.
## Verification
* net8.0, net471, net10.0 all build clean.
* No API surface changes on IGradientBasedOptimizer<T> — the existing
IFusedOptimizerSpec interface (already implemented by all fuse-able
optimizers) provided everything needed.
* All consumers preserve eager fallback path for non-fuse-able optimizers
and non-GPU hosts.
Co-authored-by: franklinic <franklin@ivorycloud.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
0 commit comments