Skip to content

Add graph-level BPTT tape (closes #39) - #55

Merged
w4ffl35 merged 1 commit into
masterfrom
fix/nir-bptt-tape
Oct 14, 2026
Merged

w4ffl35 merged 1 commit into
masterfrom
fix/nir-bptt-tape

Conversation

@w4ffl35

@w4ffl35 w4ffl35 commented Oct 14, 2026

Copy link
Copy Markdown
Member

Implements issue #39: nir_tape_t (tape.h/tape.c) retains per-step per-node summed inputs, values, and LI/LIF/IF/CubaLIF state across a multi-step forward, then backpropagates in reverse topological order.

Forward reuses the runtime's Delay-breaking scheduler (an internal nir_runtime_t, never stepped, supplies the exact order and cycle validation) and evaluates the same public layer ops, so its readout matches nir_runtime_run bit for bit; every forward starts from unprimed temporal state. Backward seeds grad/T per step for the Output time-average, routes Delay value gradients to the previous step's sources, unrolls LI state exactly, and wires LIF/IF/CubaLIF per the documented zero-gradient reset convention (CubaLIF cross-step synaptic credit is truncated: the op has no grad input for the synaptic current). Parameter gradients accumulate per node (Affine/Linear/Conv weights and biases, Scale constants); input-frame gradients are exposed per step. Inference APIs untouched: purely additive.

Acceptance criteria from #39:

  • Multi-step (T=4) LI+Delay topology gradients match central finite differences (max err ~1e-5, tol 1e-3), as do Conv2d/pool/flatten and Conv1d/Linear/Scale topologies; single-step Threshold/LIF/Scale and IF chains match float64 closed forms.
  • Scalar Delay test proves credit flows into earlier steps (frames 0-2 get w/T-scaled grads through the Delay edge only; last frame is exactly 0.0).
  • ASan+UBSan clean; no behavior change to any inference API (no existing file modified except the two CMake registrations).

Local evidence: 42/42 ctest green in Debug, Release, and ASan/UBSan builds, zero compiler warnings.

Notes for follow-ups (left untouched deliberately): README's training-scope section and the train.h header comment still list the tape as future work -- both were already stale for #40/#41/#45-#47 on master, so a doc refresh fits the #44 driver owner better. Spike-count sum accumulation (loss.h) still backprops through the caller, since the tape owns mean-averaging, not plain sums.

tape.h/tape.c: nir_tape_t retains per-step per-node summed inputs, values, and LI/LIF/IF/CubaLIF state across a multi-step forward that reuses the runtime's Delay-breaking scheduler and matches nir_runtime_run bit for bit, then backpropagates in reverse topological order: grad/T seeding for the Output time-average, Delay value gradients routed to the previous step's sources, exact LI state unrolling, and LIF/IF/CubaLIF wiring per the documented zero-gradient reset convention. Parameter gradients accumulate per node (Affine/Linear/Conv weights and biases, Scale constants); input-frame gradients are exposed per step.

Tests: test_tape (forward bit-exactness on a Delay+LI graph and the exported conv_net with Delay reset cycles; central-FD gradient checks on LI/Delay, Conv2d/pool/flatten, and Conv1d/Linear/Scale topologies; float64 closed forms for Threshold/LIF/Scale and IF chains; scalar Delay credit-flow proof; spiking smoke; error paths) plus seven graph fixtures. 42/42 ctest green in Debug, Release, and ASan/UBSan.
@w4ffl35
w4ffl35 merged commit 304adad into master Oct 14, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant