Repository navigation
DPointNet: preserve projection rounding in fused current accumulation - #480
Merged
shixnya merged 2 commits intoOct 16, 2026
Conversation
Round each standalone current projection before adding the existing current once. Keep atomic projection storage separate and retain safe fixed-four elementwise forwarding, preserving the initial-current identity VJP and canonical weight/spike gradients. Add 92 CUDA value/VJP/recomputation regressions and document the numerical boundary without claiming deterministic atomic sums. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The regression suite does not detect omission of the intermediate FP16 projection rounding.
1 open issue
What changed in this PR
Corrects DPointNet fused forward-current accumulation so projections round to the compute dtype before adding the initial current.
Changes:
- Separates projection reduction from baseline addition.
- Adds 92 GPU value, gradient and recomputation cases.
- Documents numerical guarantees and limitations.
| File | Description |
|---|---|
| tests/simulator/dpointnet/test_current_accumulation_rounding.py | Adds accumulation and gradient regressions. |
| docs/autodocs/source/dpointnet_development.rst | Explains rounding boundaries and buffer handling. |
| bmtk/simulator/dpointnet/custom_ops/csr_spike_ops.cu.cc | Corrects fixed-four and atomic accumulation ordering. |
Review effort: Balanced
Cover fixed-four projections at the FP16 halfway value 1 + 2**-11 with an initial current of -1. Assert zero after standalone projection rounding, rather than the 2**-11 residual left by baseline-first FP32 arithmetic. Exercise batches 1, 4, 16 and 32 in eager and compiled repeated calls, checking the initial buffer remains unchanged. All eight controls fail at the intended assertion on the original operator; all 100 repaired tests pass on V10032. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Fix the numerical boundary of DPointNet fused forward current accumulation: round the standalone synaptic projection to the compute dtype, then add the initial current exactly once.
This is independent of
use_fused_recurrent_accumulation, the recurrent weight-gradient carrier; that option is not disabled by this fix.Why
Seeding a projection with an existing current reassociates every synaptic contribution with the baseline, allowing small contributions to disappear and changing threshold crossings even in FP32.
The original full-V1 batch32 failure reproduced before backward or Adam: first current difference at tick 1, voltage difference at tick 2, and spike difference at tick 301. Independent legal FP32 reduction trees reproduce the early current values; emulation of the original fixed-four seeded/FMA arithmetic matches captured GPU outputs bitwise. This establishes a numerical-association mechanism, not an indexing/buffer-corruption diagnosis or exhaustive proof of race freedom.
The repair does not make atomic projection deterministic or promise bitwise equality for arbitrary regroupings of multiple projections.
Validation
The completed receipts below belong to isolated
8381b54c-based qualification. This PR applies the byte-identical CUDA source, regression tests and developer RST to currentdevelop(b28e1cd, after #479). All native build inputs and the build script match the qualified snapshot. Integrated current-base GitHub CI results are separate and are not claimed green in advance.New tests cover FP16/FP32, batches 1/4/16/32, ordinary/fixed-four/active-row/device-queue/run-aggregation routes, eager/compiled repeated calls, distinct counted inputs, independent values, analytic VJPs and recomputation. The 92 GPU-only cases are included among CPU skips, not added to CPU pass totals.
Both native libraries were rebuilt for SM61/70/75/80/86/89/90 plus PTX90; execution here covers V10032 and L40S, not every compiled family. L40S full-V1 qualification retains native recurrent gradient accumulation ON; V100 auto selects it OFF.
Matched full-update timings (20 synchronized samples after 3 excluded warmups) are essentially unchanged against safe native current-accumulation-OFF controls: V10032 6.6161s vs 6.6384s (-0.34% time), L40S 3.0883s vs 3.0661s (+0.72%). No significant speedup is claimed.
Focused GPU reproduction
Rebuild both operators in an ABI-compatible environment, then run:
DPOINTNET_CUDA_ARCHS="61 70 75 80 86 89 90" \ python -m bmtk.simulator.dpointnet.custom_ops.build python -m pytest -q tests/simulator/dpointnet/test_current_accumulation_rounding.pyLimits
No complete GPU publication suite, repaired RTX3090 rerun, full-V1 mixed precision, distributed-training interaction, all-family or convergence qualification is claimed. Existing CPU CI disables fused CUDA and cannot replace hardware receipts. Local flake8 was unavailable; immutable environments were not modified.
Source-only fix: no generated binaries, private workload data, installed runtime migration or scientific-environment changes.