Changelog#
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.2.1] - 2026-08-09#
A follow-up to 0.2.0 that removes the mv/mm split from the just-in-time
connectivity (JITC) families, restores the daily JAX compatibility matrix to
green, and brings the API reference back in sync with the public surface.
JITC. 0.2.0 exposed the fact that the mv and mm light kernels drew
different connectivity for the same (prob, seed, shape) by making the
difference explicit: a required matrix_mode keyword and mat.mv / mat.mm
materialization views. 0.2.1 removes the difference instead. Every JITC entry
point — scalar, normal and uniform, float and binary, dense, CSR and dt2t —
now draws the 32-lane mv matrix on every backend, so matrix_mode and the two
views are gone and todense() / tocsr() / tocsc() / tocoo() are
unambiguous again. Signatures return to their 0.1.2 shape (#190).
Compatibility. The Daily CI matrix now pins 0.10.0 alongside 0.8.0 and
0.9.0, and the operator test that broke on pinned JAX ≤ 0.9 has been made
independent of JAX’s traceback-filtering behaviour.
Requirements: unchanged from 0.2.0 — Python ≥ 3.11, jax ≥ 0.8.0
(validated through 0.11.x), brainunit ≥ 0.0.8, numpy ≥ 2.0.
⚠️ Breaking changes & migration#
0.2.0 shipped the mv/mm split to PyPI, so the removal below is a breaking
change for code written against that release. Code written against 0.1.2 or
earlier needs no changes.
|
|
|---|---|
|
drop the keyword: |
|
drop the keyword |
|
|
|
removed; there is no mode to annotate |
Matrix-matrix JITC results recorded with 0.2.0 change. The mm kernels
drew a 4-lane residue-class matrix; they now draw the 32-lane mv matrix, so
jitsmm / jitnmm / jitumm and their binary_* counterparts return
different — not merely reordered — values for the same (weight, prob, seed, shape, corder). Matrix-vector results are bit-identical to 0.2.0. Re-record
any golden outputs captured from an mm path; as in 0.2.0, seeds are not
portable across the change.
The upside is the invariant that motivated the work: for a given (weight, prob, seed, shape, corder), jits, jitsmv, jitsmm, binary_jitsmv,
binary_jitsmm, jits_to_csr and jitsmv_dt2t — and the jitn / jitu
equivalents — now materialize one matrix, identically on numba and
cuda_raw. A model that moves between the matrix-vector and matrix-matrix
paths, or between CPU and GPU, keeps its connectivity.
Changed#
JITC connectivity is mode-free.
matrix_modeis removed from every public and internal JITC entry point, and the mm generation path is folded onto the mv walk (_LANE_STRIDE= 32) in both thenumbakernels and the CUDA sources (#190).todense()/tocsr()/tocsc()/tocoo()work directly onJITCScalarR/C,JITCNormalR/CandJITCUniformR/Cagain. In0.2.0they raisedNotImplementedErrorand directed callers tomat.mv/mat.mm.Daily CI covers every supported JAX minor. The
jax-versionmatrix is[ "0.8.0", "0.9.0", "0.10.0", "" ]; the empty entry continues to track the newest release.
Fixed#
Daily CI Tests failed on the pinned-JAX legs.
test_f17_kernel_generator_failure_is_wrapped_with_alternativesasserted that the kernel-generator exception was the direct__cause__of the raisedKernelCompilationError.jax._src.traceback_util.api_boundarysplices a synthetic frame (UnfilteredStackTraceon JAX 0.10,JaxStackTraceBeforeTransformationon 0.8/0.9) into the cause chain, demoting the real cause by one level; whether it does so depends on the defaultjax_traceback_filteringmode, which differs across JAX minors. The assertion now walks the whole chain, so it holds regardless of how many frames JAX inserts. Library behaviour was correct throughout — only the test was over-specific.
Removed#
matrix_modekeyword, themat.mv/mat.mmmaterialization views, theMatrixModetype alias, and theNotImplementedErrorguards that the split required (#190).The mm-specific CUDA generation kernels and their
numbacounterparts: the JITC.cusources shed 3,439 lines against 468 added, since one drawn matrix needs one walk.
Documentation#
API reference re-synchronized with
brainevent.__all__. 41 staleautosummaryentries were removed — symbols retired in0.2.0(csr_solve,IndexedBinary1d/IndexedBinary2d,IndexedEventRepresentation,indexed_binary_dense*,binary_array_index,BenchmarkReport,register_cuda_kernels) and 30lfsr*/get_numba_*helpers that live in a private module and never resolved. 44 public exports gained a reference page, among themBitPackedBinary,CompactBinary,bitpack,Dense,binary_csrm{v,m}_indexed, the CSC and fixed-connectivity plasticity operators, theCompilerBackendhierarchy, the primitive-registry accessors and the hybrid-CSR scheduling knobs.Exception hierarchy documented in one place.
BrainEventErrorand its nineteen subclasses now appear inerrors.rst, grouped by subtree and preceded by the inheritance tree;operator.rstcross-references it instead of documenting four of them separately.Two broken snippets fixed. The quickstart and the E/I-network how-to constructed
JITCScalarRandFixedPostNumConnfromnum_pre=/num_post=/conn_num=/weight=/seed=keywords that these constructors have not accepted since at least0.1.2, so both raisedTypeErroras written; the quickstart also built aCSRfrom undefined names. Both are rewritten against the real constructors and were executed end to end.Deprecated aliases replaced throughout the prose docs and tutorials.
FixedPreNumConn→FixedNumPerPostandFixedPostNumConn→FixedNumPerPre(the mapping is crossed) across the explanation pages, how-to guides and the two data-structure notebooks; the removedIndexedBinary1d/IndexedBinary2dgive way toBitPackedBinary/CompactBinary.docs/specs/release-0.2.1.mdrecords the CI root cause and the reference audit.
Internal#
brainevent/__init___test.pyguards the reference against future drift: everyautosummaryentry must resolve on itscurrentmodule, every name inbrainevent.__all__andbrainevent.config.__all__must be documented exactly once, and deprecated aliases must stay undocumented.The full suite was re-run against pinned
jax0.8.0, 0.9.0 and 0.10.x before release.
[0.2.0] - 2026-08-08#
A correctness release spanning three layers of the stack.
Data structures. The just-in-time-connectivity (JITC) families now draw the
same matrix on CPU and GPU: the numba kernels were rebuilt on the CUDA
light-RNG walk, replacing the LFSR generators that silently produced different
connectivity per platform. The compressed-sparse representations validate their
structure at construction and support int64 indptr for matrices whose nnz
exceeds the int32 range, and a first-class Dense representation joins the
data-representation family (#179).
Operator machinery. A hardening pass over brainevent._op fixes the 19
defects catalogued in the 2026-07-16 operator-registration audit
(dev/2026-07-16-op-registration-audit.md): stale backend dispatch after runtime
backend switches, silently dropped JVP rules, incomplete compilation-cache keys,
order-dependent FFI target names, and incorrect vmap execution of numba.cuda
kernels, among others (#187).
CUDA kernels. A scan of the whole .cu tree fixes an out-of-bounds
shared-memory request that aborted the CUDA context for float64
binary_csrmm, widens 54 index expressions that wrapped past INT32_MAX,
restores the missing warp-per-row CSRMV dispatch tier (up to 3.4× on the row
lengths typical of sparse connectivity), and retires 154 unreachable kernel
entry points (#185, #188).
The retired pararnn subpackage is removed (#177).
Requirements: Python ≥ 3.11, jax ≥ 0.8.0 (validated through 0.11.x),
brainunit ≥ 0.0.8, numpy ≥ 2.0. (The jax ≥ 0.8 and numpy ≥ 2.0 floors
were raised during 0.1.2 by #171; the 0.1.2 notes below understate them.)
⚠️ Breaking changes & migration#
Old usage |
New usage |
|---|---|
|
|
|
|
|
values change: the CPU kernels now draw the CUDA matrix. Re-record any CPU golden outputs; seeds are not portable across |
|
now raises |
|
raises — |
|
raises |
Explicit CUDA entry points |
the auto-dispatching wrappers ( |
|
removed, with no replacement |
Three of these deserve a note.
JITC CPU/GPU parity changes CPU numbers. In 0.1.x the numba kernels
generated connectivity with an LFSR stream while the cuda_raw kernels used the
light-RNG chunk/lane walk, so the same (prob, seed, shape) described a
different matrix on each platform. The numba kernels now reproduce the CUDA
walk exactly, so a model moved between CPU and GPU keeps its connectivity — but
CPU results recorded against 0.1.x will not reproduce. Only the drawn matrix
changed; the operator semantics did not.
mv and mm are genuinely different matrices. The light kernels walk 32
lanes for matrix-vector and 4 threads (AW-T4) for matrix-matrix, and the stride
is part of the drawn matrix. Bare materialization was therefore ambiguous and
silently returned the mv matrix even when the caller was about to use mm; it
now raises, and the mat.mv / mat.mm views select explicitly.
The removed CUDA entry points were already unreachable from Python. A
reachability pass over every // @BE annotation against every kernel-name
template in the package found that no Python path could name them; the
__global__ kernels behind the auto-dispatched families are retained and still
launched internally.
Added#
Dense— an explicit dense data representation (brainevent.Dense). The dense counterpart toCSR/CSC/FixedNumPerPre/FixedNumPerPost, holding the full weight matrix as its single pytree leaf while exposing the same representation contract: unit-awaredata,shape,backend, namedbuffers, event-driven binary matmul dispatch (@withBinaryArray/BitPackedBinary), and theupdate_dense_on_binary_pre/_postplasticity helpers. It is a registered pytree, so it passes throughjax.jitin the same style as the sparse families.int64indptrsupport forCSR/CSC. The constructors andCSR.fromdensetakeindptr_dtype:"auto"(default) keepsint32and promotes toint64only whennnzexceeds theint32range; an explicitint32raisesOverflowErrorrather than truncating.int64offsets requirejax_enable_x64— the library refuses with an actionable error instead of toggling the global config on your behalf, since JAX would otherwise silently downcast.indicesstayint32in every case: they are secondary-axis coordinates bounded by the matrix dimension, so widening them would cost bandwidth for nothing.Tunable CSR hybrid CUDA scheduler (
HybridConfig,get_hybrid_config,init_csr_config). The four hybrid kernels (binary_csrmv_hybrid.cu,binary_csrmm_hybrid.cu, and theirbinary_indexed_*siblings) exposeblock_size,fixed_scatter_blocks,tpr_threshold, andtask_nnzas-DBE_HYBRID_*compile-time constants.init_csr_config()benchmarks candidate configurations by compiling the production kernel and persists the winner per GPU model to<cache_dir>/csr_hybrid_config.json; later processes pick it up throughget_hybrid_config(). Resolution order is$BRAINEVENT_CSR_HYBRID_CONFIG(a JSON object, for CI and one-off overrides) → the per-device_kindentry in the cache file → the defaults baked into the.cusources. The same function sizes the host-side task workspace, so the compiled.soand the Python allocation can no longer drift apart.init_csr_configis GPU-only, never runs automatically, and must not be called inside a JIT closure.'cublas'GPU backend forbinary_densemv/binary_densemm. A cuBLAS dense path (float32weights,boolspikes) alongside the event-drivencuda_rawdefault and thejax_rawreference; useful as a dense-throughput baseline at high spike rates.libcublasis located in the installednvidiaCUDA Python packages at load time.mat.mv/mat.mmmaterialization views on every JITC family. Each view exposestodense/tocsr/tocsc/tocoofor the matrix that mode actually uses. For column-oriented matrices (JITCScalarCand siblings) the view also applies the swapped generation shape, so the dense form matches the matvec — the light kernels’chunk_sizedepends onshape[1], which made the old direct materialization shape-inconsistent.numbaCPU kernels for the JITC CSR anddt2tpaths.jits_csr_count/jits_csr_filland theirjitn_*/jitu_*siblings, plus the fusedjitsmv_dt2t/jitnmv_dt2t/jitumv_dt2tfill primitives, previously had CUDA-only backends;.tocsr()and the eligibility-trace operators now run on CPU.Light-RNG helpers in the numba random utilities —
light_rng_uniform01,light_rng_normal01, andget_numba_light_rng_funcs(), the CUDA-compatible(seed, row, col)weight hashes and the njit dispatch table backing the kernels above. Listed in the Utilities API reference.matrix_modeon the JITC CSR materialization entry points (jits_to_csr,jitn_to_csr,jitu_to_csr, defaulting to'mv').jax 0.11.x is now a validated version (#182). The numba XLA FFI bridge raises its validated ceiling (
_MAX_VALIDATED_JAX) from0.10to0.11, so installingbraineventalongside jax 0.11 no longer emits the “untested jax”RuntimeWarning. jaxlib 0.11 reports the sameXLA_FFI_APIversion (0.3) as 0.10, meaning the hand-mirroredffi.hstruct layout is unchanged; the full test suite passes on jax 0.11.0 on both the CPU and CUDA backends. Thejax>=0.8.0floor is unchanged.
Fixed#
binary_csrmmno longer aborts the CUDA context withfloat64weights (#188). The CSRMM non-transpose block kernels stage one accumulator per(strip, lane)pair — 8 strips × 32 lanes — but requested only8 * sizeof(ACC_T)bytes of dynamic shared memory, a 32× under-request. The 1 KiB overrun of the 32-bit instantiations goes unnoticed on sm_86 because the per-block shared-memory window is rounded up;float64needs 2 KiB and faults, sobinary_csrmmwithfloat64weights andavg_nnz > 512(wherent_autoselects the block kernel) died withCUDA_ERROR_ILLEGAL_ADDRESS. Fixed across 26 instantiations inbinary_csrmm.cuandbinary_indexed_csrmm.cu.CSRMM and JIT index arithmetic no longer wraps past
INT32_MAX(#188). The CSRMM kernels computedB[indices[j] * n + c]andC[row * n + c]in 32-bit arithmetic; sinceBis usually abool/int8event matrix, 2 GiB of allocation is enough to cross the boundary and read out of bounds. The JIT connectivity families had the same defect inchunk_counts[row * n_chunks + chunk_id], reachable once the indexed buffer passes ~8.6 GB. Widened 30 CSRMM subscripts and 24 JIT chunk sites tosize_t. Shared-memory subscripts with a literal* 32are deliberately unchanged — they are bounded by the block size.Backend switches now take effect immediately (#187).
XLACustomKernel.set_default,brainevent.config.set_backend, andclear_backendsinvalidate JAX’s dispatch and executable caches (jax.clear_caches()) whenever the effective setting changes. Previously, eager calls and warmjax.jitfunctions kept executing the previously selected backend. Note the invalidation is process-global: the next call of every jitted function recompiles.defjvprejects mismatched rule arity (#187). Registering a number of JVP rules different from the primitive’s number of inputs now raisesValueErrorat differentiation time instead of silently dropping trailing gradients (previouslyziptruncation produced wrong, silent results). A multi-result JVP rule returning a bare array instead of a sequence now raisesTypeError. One latent in-tree mismatch (binary_fcnmm_p: four rules for three inputs) was corrected.vmapovernumba.cudakernels computes correct results (#187). Batched calls now execute one kernel launch per batch slice with the kernel’s original launch configuration, instead of reusing the launch grid of the unbatched shape over folded buffers (which silently corrupted any kernel that couples rows, e.g. stencils and reductions). Kernels wrapped with an explicitgrid=cannot be batched; combininggrid=withvmap_method=raisesValueErrorat wrap time. Only onevmaplevel is supported: nestedvmapnow raises a clear error instead of returning uninitialized memory for all but the first slice.Compilation-cache keys cover everything that affects codegen (#187). The kernix (inline C++/CUDA) cache key now includes the resolved
FunctionSpecs and the content of user-provided extra include headers (key schema v2 — old cache entries are recompiled once, not misused). ThenumbaCPU FFI memo no longer keys on array shapes, so one kernel serves all shapes of the same dtype signature.FFI target names are content-derived (#187). CPU and CUDA numba kernels register under a fingerprint of the kernel’s bytecode, constants, closure values, and referenced globals rather than a process-order counter, making
jax.exportartifacts stable across processes. Kernels whose content cannot be fingerprinted deterministically fall back to per-process counter names.Unknown, packed sub-byte (
S1–S4,U1–U4,F4E2M1FN), and FP8 buffer dtypes now raise a descriptiveValueErrorinstead of being reinterpreted as raw bytes;bfloat16is rejected explicitly on the numba paths. XLA FFI extension chains are walked fully, and FFI error objects are destroyed after use (#187).CUDA output buffers for kernels that accumulate are zero-filled on XLA’s stream (previously uninitialized memory could leak into results). Transient CUDA probe failures no longer permanently disable the
numba.cudabackend for the process (#187).Kernel construction/compile failures during lowering now raise
KernelCompilationError(with the original exception as__cause__and the remaining registered backends listed); calling a kernel on a platform with no registered backend raisesKernelFallbackExhaustedErrornaming the platforms that are registered. Both are exported frombrainevent(#187).
Performance#
Restored the warp-per-row CSRMV tier (#188).
float_csrmv.cudocuments a three-tier row mapping (thread / warp / block), but the three binary CSRMV dispatchers only had two — every row length from 16 to 512, the normal range for sparse neural connectivity, ran the thread-per-row kernel, where the 32 lanes of a warp each walk a different row and everyindices[j]load is uncoalesced. Measured on sm_86 (m = k = 65536, f32 hetero, bool spikes), thread vs warp: 0.088 vs 0.043 ms atavg_nnz32, 0.209 vs 0.076 at 64, 0.950 vs 0.277 at 256. Thresholds follow the crossovers: thread below 16, warp to 512, block above.Packed every one-warp-per-block launch into 256-thread grid-strided blocks (#188). A block holds a scheduler slot regardless of its size, so
<<<m, 32>>>wasted 7/8 of it. Applied to the CSRMV warp kernels (3.3× atavg_nnz8, 2.5× at 32, parity from 128), thefloat_csrmmwarp kernels (2.05× at 2, 1.19× at 64), and thecsr_slice_rows/dt2trow-warp kernels. The last group is not a uniform win: it gains 2.5× belowavg_nnz32 and regresses ~20% near 512, which was taken deliberately because real sparse connectivity sits well below 256 non-zeros per row. No<<<..., 32>>>launch remains in the tree.
Changed#
JITC
numbakernels rebuilt on the CUDA light-RNG walk (#179). The dense, matvec, matmat, CSR, anddt2tgenerators across_jit_scalar,_jit_normal, and_jit_uniformnow share the CUDAlight_rng_init_wpr/stationary_initial_qinitialization, lane strides, and chunking, and sample weights with the same(seed, row, col)hash, sonumbaandcuda_rawmaterialize bit-identical matrices. See the Breaking changes note above.CSR/CSCvalidate their structure at construction (#179).indicesmust be integral, non-negative, in bounds for the secondary axis, and are coerced toint32;indptrmust be 1-D,int32/int64, of length primary dimension + 1, start at0, be monotonically non-decreasing, and end atnnz. Value checks are host-side and therefore skipped under tracers, where only the static dtype and shape invariants are enforced. Structure-preserving paths (with_data,transpose,apply,tree_unflatten, data-only binary ops) reuse the already-validated structure, so they add no host readback insidejax.jit/jax.vmap.FixedNumPerPre/FixedNumPerPostcoerce their connection indices toint32(#179), matching the compressed-sparse families; bounds are still validated by the existing invalid-index check.Re-registering an FFI target with different content now raises
KernelRegistrationErroron every platform (#187) (includingload_cuda_inline(..., replace=True)/force_rebuild=Truewith changed source). Live re-pointing of an already-registered XLA FFI target is not supported by JAX (CPU raises; CUDA silently keeps the old handler), so brainevent refuses deterministically instead of silently dispatching stale code — register under a newname=to iterate on a kernel within one process. Re-registration of unchanged source (e.g.force_rebuild=Truetwice) is an idempotent no-op: registration identity is the deterministic compilation cache key, not the compiler’s output bytes.Registering a second primitive under an existing name emits a
UserWarning(the new registration still wins, as before) (#187).Duplicated internals consolidated (#183). The dtype→CUDA-suffix table had 31 verbatim copies across 22 files and now lives in
_op/util.pyasdtype_suffix()/spike_suffix()(the lenient'_f32'fallback is preserved, documented, and tested). The JIT families’_normalize_chunk_size,_normalize_matrix_mode,_MV_STRIDE/_MM_STRIDE,_is_static_zero,_n_chunks, and_mode_infixmove to_misc.py, andMatrixModeto_typing.py. This duplication was the riskiest kind:chunk_sizeparticipates in the RNG stream keying, so a divergent default would not raise — it would silently make one operator draw a different connectivity matrix than its siblings.CSR binary task capacity is single-sourced (#179). The host-side workspace sizing moved out of
_csr/main.pyintohybrid_config.hybrid_task_capacity, the same function that emits the kernel’s compile flags.The three
_jit_uniformFFI module names are prefixedjit_uniform_*to match_jit_scalarand_jit_normal(#185); the registry is process-global and unprefixed names risked aKernelRegistrationErrorclobber. TheXLACustomKernelprimitive names are deliberately unchanged.CONTRIBUTING.mdrewritten (#182). It previously described BrainPy and linked to a page that returns HTTP 404. It is now a self-containedbraineventguide covering development setup, the test/mypy/pre-commit gates, docs builds, code style, the pull request checklist, and GPU kernel contributions.SECURITY.mdrewritten (#182). Vulnerability reports now go through GitHub private vulnerability reporting or email instead of public issues, and the policy documents supported versions, response targets, and the trust boundary around the runtime C++/CUDA compilation APIs (load_cpp_inline,load_cuda_inline, and friends).CODE_OF_CONDUCT.mdupgraded from Contributor Covenant 2.1 to 3.0 (#182)..gitattributesexpanded to cover the header, reStructuredText, notebook, YAML, TOML and image file types actually present in the tree, with language-aware diff drivers, explicit binary markers, GitHub language-statistics hints, andexport-ignorerules for development-only infrastructure (#182).
Removed#
The
brainevent.pararnnsubpackage (#177). The parallel-RNN training module — diagonal GRU/LSTM cells, the Newton solver, the parallel-prefix reduce, and their fused CUDA kernels — is deleted along with its tests and benchmark. It was never re-exported frombrainevent/__init__.pyand nothing else in the package imported it, so the top-level API is unaffected;import brainevent.pararnnno longer resolves.154 unreachable CUDA entry points (#185, #188). Every
// @BEannotation costs a generated XLA FFI wrapper, an nvcc compile, and a registration at first lowering, whether or not Python can name it. Two reachability passes removed 102 and then 52 entry points — the explicit_nt_thread/_nt_warp/_nt_blockandt_warpCSR families, thecsr_slice_rowstier wrappers, thebinary_fcnmm_araw_*family, the floatbinary_fcnmv_scatter_*variants, and thedt2ttier wrappers. Device kernels reachable through an_autodispatcher were kept; the genuinely orphaned ones went with their wrappers, which also retired a below-sm_70 compile trap (atomicAddcalled directly on__half*/__nv_bfloat16*instead of the arch-guarded helpers).Orphan headers and dead helpers (#185, #183).
include/brainevent/attrs.h(a self-declared placeholder) andinclude/curand_common.h(no.cufile uses cuRAND) are deleted, along with the unusedcuda_common.hsymbolswarp_reduce_max/min_f32/f64andACC_T_*. On the Python side, nine never-called_misc.pyhelpers (~412 lines: the block-sparse subsystem,_coordinate_index_dtype, and theis_known_typeduplicate), the never-registered_csrmv_dt2t_transpose_rule, the phantom'SRAW_MM_kernel'backend string, and 24 unused imports are removed.
Internal#
Every test is now co-located with the module it tests (#184, #186). Rule 11 of
AGENTS.md— each modulefoo.pykeeps its tests in a siblingfoo_test.py, notests/directory and notest_*.pyprefix — is applied to the remaining violations:_csr/test_util.py(which matched pytest’s default collection glob) is renamed_csr/_test_util.py, and eleven orphan test files are merged or split into their target modules. The only shipping-code change is that the__getattr__deprecation shim moves from__init__.pyto a newbrainevent/_deprecation.py, storing rename targets as name strings resolved against a caller-supplied namespace rather than live objects; public behaviour is unchanged. Three module-levelpytestmark = pytest.mark.slowdeclarations became per-item decorators, which would otherwise have dropped 152 fast tests out of the default lane.CLAUDE.mdis renamedAGENTS.md, with aCLAUDE.mdstub importing it for backward compatibility (#181).Bumped
mypyfrom 2.1.0 to 2.3.0 (#175).Test-suite fixes for the new CSR initialization module (#180).
[0.1.2] - 2026-07-03#
A consolidation release. Three threads land together: the DT2T / DT_to_T
naming convention is folded into a single, consistently-cased dt2t name;
batched (mm) variants of the dt2t operators are added for D-RTRL
eligibility traces; and the GPU cuSPARSE SpMV/SpMM backends are consolidated
under one cusparse name. Alongside these, several GPU-only autodiff and
output-shape defects in the event-driven CSR and fixed-connection-number
kernels are fixed.
Requirements: unchanged from 0.1.1 — Python ≥ 3.11, jax ≥ 0.5.0,
brainunit ≥ 0.0.8, numpy, absl-py.
⚠️ Breaking changes & migration#
No compatibility aliases are kept for this release — update call sites directly:
Old name |
New name |
|---|---|
|
|
|
|
|
|
|
|
|
removed from the public API (see Removed below) |
|
|
|
removed — use |
Added#
Batched (
mm) variants of the per-synapsedt2toperators, implementing the batchedDᵗ εᵗ⁻¹term of the D-RTRL eligibility-trace updateεᵗ ≈ Dᵗ εᵗ⁻¹ + diag(D_fᵗ) ⊗ xᵗ. Both operands carry a shared leading batch axis:yholds the per-neuron factorDᵗwith shape(n_batch, n_hidden)and the weight operand holds the per-synapse traceεᵗ⁻¹with shape(n_batch, ...).csrmm_dt2t/cscmm_dt2t/csrmm_dt2t_p— CSR/CSC layouts;wis(n_batch, nse)and the output matchesw. The primitive shipsnumba(CPU),cuda_raw(GPU, default; batched row-thread/row-warp/ nz-thread kernels auto-dispatched onavg_nnz, non-transpose path), andjax_raw(CPU/GPU/TPU) kernels plus JVP rules.fcnmm_dt2t— fixed-connection-number (ELL) layout;weightsis(n_batch, rows, n_conn)(or a size-1 homogeneous value) and the output is(n_batch, rows, n_conn). Pure JAX, fully differentiable.
Changed#
DT2Trenamed todt2tacross the public API, and the JIT-connectivity variants additionally gain anmvinfix matching theirjitnmv/jitsmv/jitumvsiblings. Every function using theDT2Tnaming convention —csrmv_DT2T,cscmv_DT2T,csrmv_DT2T_p,fcnmv_DT2T— is now spelled with the lowercasedt2tsuffix;jitn_DT2T/jits_DT2T/jitu_DT2Tbecomejitnmv_dt2t/jitsmv_dt2t/jitumv_dt2t. Purely a rename; behavior is unchanged.DataRepresentation.DT_to_T/DT_to_T_transposedrenamed to.dt2t/.dt2t_transposed. These are the per-synapsey-to-W-shaped conversion methods declared on the baseDataRepresentationcontract and overridden by every concrete representation that supports them directly (CSR,CSC,FixedNumPerPre,FixedNumPerPost,JITCScalarR/C,JITCNormalR/C,JITCUniformR/C); theJITCMatrixbase class’sUnsupportedOperationErrorfallback is renamed identically. Purely a rename; behavior and signatures are unchanged.GPU cuSPARSE backend for
binary_csrmv/binary_csrmmrenamed'JAX_cusparse'→'cusparse'. Thejax.experimental.sparse-backed SpMV/SpMM kernels are now selected withbackend='cusparse'. The default GPU backend remains'cuda_raw', so code that does not pin a backend is unaffected.
Removed#
*_fill_pfill-primitive exports.jitn_csr_fill_p,jits_csr_fill_p,jitu_csr_fill_p,jitnmv_dt2t_p,jitsmv_dt2t_p, andjitumv_dt2t_p(renamed fromjitn_DT2T_fill_p/jits_DT2T_fill_p/jitu_DT2T_fill_p) are no longer re-exported frombrainevent.jit_normal/jit_scalar/jit_uniformor top-levelbrainevent. They were internalXLACustomKernelprimitives backingjitnmv_dt2t/jitsmv_dt2t/jitumv_dt2tand.tocsr(), never meant to be called directly; they remain defined in their respective submodules.'BCOO_cusparse'GPU backend forbinary_csrmv/binary_csrmm. The redundant BCOO/BCSR-based cuSPARSE kernel path is removed; the equivalentjax.experimental.sparsepath remains available asbackend='cusparse'.
Fixed#
Gradients of
binary_csrmv/binary_csrmmno longer fail on GPU-only backends. The autodiff (JVP / transpose) rules form tangents and cotangents with the floatcsrmv/csrmmprimitive while forwarding the binary primitive’s backend name; a GPU-only backend such as'cusparse'is not registered on the float primitive, so the backward pass raisedKernelFallbackExhaustedError. The rules now fall back to automatic backend selection whenever the float primitive cannot service the requested backend, leaving'cuda_raw'/'jax_raw'/'numba'behaviour unchanged.binary_fcnmmreturns its documented logical shape oncuda_raw. Withtranspose=Trueon thecuda_rawbackend the high-level wrapper leaked the kernel’s internal “batch-first”(n, num_post)layout instead of the documented(num_post, n)shape that every other backend already returns. The wrapper now normalises the output, matching the dense reference and thejax_rawpath.
[0.1.1] - 2026-06-18#
A maintenance release focused on the correctness and cross-version compatibility
of the JAX custom-operator / FFI layer. There are no public API changes and no
new deprecations; code written against 0.1.0 runs unchanged.
Requirements: unchanged from 0.1.0 — Python ≥ 3.11, jax ≥ 0.5.0,
brainunit ≥ 0.0.8, numpy, absl-py.
Fixed#
Hardened the JAX custom-op / FFI layer against silent wrong answers and process crashes (#164). An audit of
brainevent/_opand the C++/CUDA FFI headers (brainevent/include) fixed ~30 defects, most of which produced silently-incorrect output or killed the host process instead of raising a clean Python error. Notable fixes:numba CPU/CUDA callbacks no longer swallow exceptions and return a NULL
OkStatus(which left the output buffer uninitialized); they now build a realXLA_FFI_Error*so JAX raises.fp16/bf16/complexdtypes are handled via raw byte-views andml_dtypes.bfloat16instead of indexing aNoneentry in the dtype map.The GPU callback binds the XLA-assigned device before allocating device arrays and streams, closing a multi-GPU data race.
BE_CHECK/BE_CUDA_CHECKraise C++ exceptions that propagate asxla::ffi::Errorrather than callingabort()and sendingSIGABRTto the host process.FFI targets are memoized per
(kernel, shapes, dtypes, platform, launch config)instead of being re-registered on every call, and the compile cache key now incorporates header byte-contents, the jaxlib version, and the include paths so any header edit triggers a rebuild.
Corrected
indptrand CSC construction (#166). Fixes index-pointer and CSC building along with related dtype handling, covered by new regression tests.numba FFI bridge now works on
jax/jaxlib0.7–0.9, not only 0.10+ (#167). The XLA FFI metadata handshake reported a hardcoded API version (0.3), which only the jaxlib bundled withjax0.10+ accepts. Older jaxlib builds advertise a lower framework version (0.1for 0.7/0.8,0.2for 0.9) and rejected every numba CPU/numba_cudakernel registration with anINVALID_ARGUMENT … incompatible API versionerror, failing ~180 tests on those versions. The bridge now detects the installed jaxlib’s FFI API version from its bundledxla/ffi/api/c_api.hheader and reports that, so registration succeeds across the supportedjax >= 0.5range.Restored compatibility with newer JAX (#168). Recent JAX removed the public
jax.interpreters.batching.not_mappedsymbol, breaking the unpinned-JAX CI job with anAttributeError. The all-unbatched branch ofgeneral_batching_rulenow returns a bareNonebatch dimension, which every supported JAX (0.7.2+) treats identically.Aligned the JITC test suite with the
saiunit≥ 0.4 unit contract (#165).saiunit≥ 0.4 correctly rejects a unit-bearing relative tolerance; the JIT-connectivity unit tests now passrtolas a dimensionless value and keep the physical unit only onatol, matching the documentedallclosecontract.
Internal#
Bumped
codecov/codecov-actionfrom 6 to 7 (#163).
[0.1.0] - 2026-06-07#
First stable feature release of BrainEvent on PyPI. It consolidates the
event-driven data structures (binary / bit-packed / compact events; CSR / CSC,
fixed-number connectivity, and just-in-time connectivity matrices) behind a
single, uniform API, ships inline type information, and retires the legacy names
accumulated during the 0.0.x series.
Not to be confused with the historical
V0.1.0git tag (2025-05-02), which was tagged on GitHub but never published to PyPI. The PyPI line ran0.0.1.postN→ … →0.0.7; this0.1.0is the first0.1.0distributed on PyPI. See the[V0.1.0]section below for the historical note.
Requirements: Python ≥ 3.11, jax ≥ 0.5.0, brainunit ≥ 0.0.8, numpy,
absl-py.
⚠️ Breaking changes & migration#
This release standardizes naming, but retains a backward-compatibility shim so
every public name exported by v0.0.7 stays importable (see Deprecated below).
Renamed symbols forward to their replacement with a DeprecationWarning; names
whose underlying functionality was removed raise an AttributeError that names the
replacement. Recommended updates:
Deprecated / changed name |
Replacement / migration |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
(removed — use the canonical representations) |
|
|
|
now returns row |
|
materialize with |
import brainevent no longer pulls in brainstate.
Added#
Uniform common-API contract on
DataRepresentation: every concrete data representation now exposes (or deliberately refuses) a single conversion and neural-plasticity surface —fromdense,todense,tocoo,tocsr,tocsc,yw_to_w,yw_to_w_transposed,update_on_pre,update_on_post. The base class declares stubs so a missing override fails loudly rather than silently inheriting an unrelated implementation (#161).Format conversions
tocsr/tocsc/tocooforCSR,CSC,FixedNumPerPre,FixedNumPerPost, and the JIT-connectivity matrices (the latter materialize eagerly viatocsrand delegate the rest). CSR/CSC conversions arejax.jit-safe (#153, #161).FixedNumPerPre.fromdense/FixedNumPerPost.fromdense: build a fixed-num-connection matrix from a dense array. Withnum_conn=Nonethe dense matrix must have a uniform per-row (per-column) non-zero count; passingnum_connpads short rows with in-range zero-weight sentinels and raisesValueErroron overflow. Physical units are preserved (#161).Sparse row slicing for
CSR,CSC,FixedNumPerPre, andFixedNumPerPost: a dense__getitem__returning row(s) of the logical matrixWwith full NumPy index semantics (int/list/tuple/array/ Pythonslice, negative-index wrapping, concrete out-of-bounds raisingIndexError), plus a sparseslice_rows(index)returningW[rows, :](CSR→CSR,CSC→CSC,FixedNumPerPre→FixedNumPerPre,FixedNumPerPost→CSR).FixedNumPerPre.slice_rowsisjax.jit-safe; the otherslice_rowspaths have a data-dependent number of non-zeros and must run outsidejax.jit(#145).UnsupportedOperationError(subclass ofBrainEventError): raised when an operation is structurally meaningless for a representation, distinct fromNotImplementedError. The JIT-connectivity matrices (JITCScalar*,JITCNormal*,JITCUniform*) raise it forfromdense,yw_to_w,yw_to_w_transposed,update_on_pre, andupdate_on_post, pointing callers to.tocsr()for a materialized, plastic representation (#161).PEP 561 inline type information: ships a
py.typedmarker so downstream type checkers consumebrainevent’s annotations. Public-API type hints and NumPy-style docstrings were completed across the package, guarded by a mypy CI ratchet (#151).
Changed#
FixedNumConnconversion methods renamed to the no-underscore canonical form (scipy /saiunitconvention):to_csr→tocsr,to_csc→tocsc,to_dense→todense. Breaking — no aliases are kept (#148, #161).CSC.__getitem__now returns rowiofW(NumPy semantics) instead of columni. Breaking for code relying on the previous column-indexing behavior (#145).brainstatedropped from the core import path: importingbraineventno longer importsbrainstate, removing it as an implicit runtime dependency of the core package (#159).Documentation reorganized into the Diátaxis structure (tutorials / how-to / reference / explanation); the README was updated to match the current public API (#149, #152, #155).
Internal CSR / JIT kernel layout:
_jit_conn_csrsplit into per-distribution submodules, with JIT-matrix.tocsr()backed by dedicated CPU / CUDA operators (#153, #160).
Deprecated#
Backward-compatibility shim for every v0.0.7 public name. A module-level
__getattr__keeps the entire v0.0.7 import surface resolvable. Renamed symbols emit aDeprecationWarningand forward to their replacement (slated for removal in a future major release):EventArray→BinaryArray;JITCHomoR/JITCHomoC→JITCScalarR/JITCScalarC;FixedPostNumConn/FixedPreNumConn→FixedNumPerPre/FixedNumPerPost;csr_on_pre/csr2csc_on_post/dense_on_pre/dense_on_post→ the correspondingupdate_*_on_binary_*functions. Names whose functionality was removed — theCOOclass & operators, thebitpack_/compact_FCN kernels, andEllLayout/CscLayout— raise anAttributeErrorthat names the replacement instead of failing silently.
Removed#
COOsparse format class and its operators removed; accessing them now raises a guidedAttributeError. UseCSR/CSCtogether with thecoo2csrhelper and the*_indexconversion utilities (csr_to_coo_index,coo_to_csc_index,csr_to_csc_index,csc_to_csr_index) for index manipulation (#124).Explicit
bitpack_/compact_FCN kernels removed; they were unified intofcnmv/fcnmm, which dispatch on the input event type. Wrap spikes withBitPackedBinary/CompactBinaryand callfcnmv/fcnmm.FixedNumConn.to_csr/to_csc/to_dense(added and renamed within the 0.1.0 cycle, never shipped in a release) standardized totocsr/tocsc/todense(#148, #161).cuSPARSE-based CSR SpMV / SpMM kernel implementations removed in favor of the native CUDA / JAX kernel paths (internal; no public-API change).
[0.0.7] - 2026-03-12#
Added#
CUDA kernel compilation pipeline (
cuda_rawbackend): Native nvcc-based compilation system. Compile.cufiles on-the-fly with source-hash caching, automatic XLA FFI registration, and multi-dtype dispatch (f16, bf16, f32, f64). Key APIs:load_cuda_file,load_cuda_inline,load_cuda_dir,load_cpp_file,load_cpp_inline(#88)BitPacked binary event representations:
BitPackedBinarycompresses 32 spike values into a single uint32 word (32x memory reduction).CompactBinarycombines bitpacking with stream compaction to skip inactive rows in scatter kernels. Factory methods:BitPackedBinary.from_array(x),CompactBinary.from_array(x), and standalonebitpack()utility (#97)BitPack FCN kernels:
bitpack_binary_fcnmv,bitpack_binary_fcnmm,compact_binary_fcnmv,compact_binary_fcnmmwith both Numba CPU and CUDA GPU backends for event-driven matmul on packed spike representations (#97)Parallel RNN training (
brainevent.pararnn): O(log T) parallel training via Newton’s method and parallel prefix reduction. Includesparallel_rnn()single-function API,AutoRNNCellwith automatic Jacobian structure detection (diagonal, block-diagonal, dense), pre-built cells (GRUDiagMH,LSTMCIFGDiagMH), fused CUDA kernels for GRU/LSTM forward and backward passes, and configurable Newton solver (#85)Warp kernel support for CSR matrix-vector multiplication and various binary/sparse operations across COO, CSR, Dense, and FCN modules (#86)
Shared CUDA headers (
brainevent/include/):common.h(BE::Tensor,BE::DType, error-check macros),cuda_common.h(warp reductions, dtype macros, atomics),dispatch.h(type dispatch macros) for consistent CUDA kernel developmentCUDA compilation diagnostics:
print_diagnostics(),get_cache_dir(),set_cache_dir(),clear_cache()for cache management;CompiledModule,register_ffi_target,list_registered_targetsfor FFI target managementTutorials for custom GPU operators with Warp and Numba CUDA (#83)
Changed#
CUDA raw as default GPU backend: All operations (COO, CSR, Dense, FCN, JIT*) now default to
cuda_rawbackend on GPU, with automatic fallback to numba/pallas when CUDA is unavailable (#94)Namespace migration:
brainevent.kernixnamespace moved intobrainevent._opand re-exported directly underbrainevent.*(e.g.,brainevent.load_cuda_file). Oldkernixnamespace removed (#96)Backend rename:
"tvmffi"backend renamed to"cuda_raw"throughout the codebase (#87, #96)Versioned cache directory: Compiled kernel cache moved from
~/.cache/brainevent/to~/.cache/brainevent/<version>/to prevent cross-version incompatibilitiesFCN kernel launch optimization: Scatter/gather kernels switched from block-per-row (
<<<n_pre, 256>>>) to thread-per-row (<<<ceil(n_pre/256), 256>>>) strategy for moderate n_conn (33–512), yielding up to 6.4x speedup on COBA benchmarks (#84, #97)FCN interface streamlining: Unified
fcnmv/fcnmmdispatch to optimal kernel based on input type (dense, bitpacked, or compact) (#96)JAX >= 0.9.1 compatibility: Added JAX Zero init helper and refactored JVP utilities for forward compatibility (#93)
JIT/CSR CUDA module splitting: Reorganized CUDA kernel files for JIT and CSR operations into separate modules with updated Warp kernel implementations (#86)
Removed#
sparse_floatmodule and all related operationsIndexedBinary1d,IndexedBinary2d,IndexedSpFloat1d,IndexedSpFloat2dclasses (replaced by bitpack/compact representations)brainevent.kernixnamespace (absorbed intobrainevent._op, re-exported at top level)ell_mvfunction (superseded by FCN operations)
Fixed#
Binary FCN CUDA kernel correctness: Fixed kernel launch parameter issues causing incorrect results in scatter/gather operations (#87)
Warp tile operation bug in JIT modules: Cooperative tile ops produced diagonal-like output when launch dimensions < 32; replaced with scalar loops (#86)
CSR matrix-vector multiplication tolerance: Enhanced assertion tolerance for numerical stability in tests
[0.0.6] - 2026-02-14#
Added#
DataRepresentationbase class with buffer registry for mutable named state on sparse matrices (register_buffer,set_buffer,buffers), plusJITCMatrixwith full operator overloading (__mul__,__add__,apply,apply2, etc.) (#81)CSR/CSC row slicing via
csr_slice_rowswith full autodiff support (JVP, transpose, batching) and three backends (numba, warp, pallas); enablescsr[row_indices]andcsc[col_indices]indexing (#80)SDDMM helpers (
sddmm_indices,sddmm_coo_indices,sddmm_bcoo) for Sampled Dense-Dense Matrix Multiplication built onjax.experimental.sparse(#75)Primitive registry (
get_registry,get_primitives_by_tags,get_all_primitive_names) with automatic registration of allXLACustomKernelinstances (#65)User backend configuration (
brainevent/config.py) with JSON persistence, per-primitive default backend selection, Numba threading config, and LFSR algorithm selection (#65, #74)CLI tool (
brainevent benchmark-performance) for automated benchmarking across backends with tabular output and automatic optimal-default persistence (#65)Configurable LFSR RNG for both Numba (
_numba_random.py) and Pallas (_pallas_random.py) with three algorithm families: LFSR88 (~2^88 period), LFSR113 (~2^113 period), LFSR128 (~2^128 period) (#74)TPU backend support for CSR operations (#72)
Event representation classes:
IndexedBinary1d/2d,IndexedSpFloat1d/2dfor indexed subsets of events, withbinary_array_index()extraction functionFixed-connection matmul helpers (
binary_fcnmv/mm,fcnmv/mm) and JITC matmul helpers for scalar/normal/uniform connectivity (#61)namescopeJAX decorator for per-backend JIT compilation caching (#62)Custom error types:
KernelNotAvailableError,KernelCompilationError,KernelFallbackExhaustedError,KernelExecutionErrorTutorial on BinaryArray usage and optimization techniques (#64)
Changed#
Major codebase restructuring: flat modules reorganized into coherent subpackages (
_coo/,_csr/,_dense/,_fcn/,_jit_scalar/,_jit_normal/,_jit_uniform/,_event/) (#59, #69)Consistent function naming convention across all operations:
binary_*mv/mm,*mv/mm,update_*_on_binary_pre/post, with_psuffix for raw primitives (#62)EventArrayrenamed toBinaryArrayacross the entire codebase (backward-compatible alias retained)JITC class renames:
JITCHomoR/C→JITCScalarR/C; module renames_jitc_homo→_jit_scalar,_jitc_normal→_jit_normal,_jitc_uniform→_jit_uniformPallas RNG class renames:
LFSR88RNG→PallasLFSR88RNG,LFSR113RNG→PallasLFSR113RNG; new factoryPallasLFSRRNG(seed)Plasticity function renames:
csr_on_pre→update_csr_on_binary_pre,coo_on_pre→update_coo_on_binary_pre, etc. (backward-compatible aliases for CSR/dense variants)Configuration system: replaced
_config.pysingleton withconfig.pymodule using JSON file persistenceXLACustomKernelenhanced withdef_tags(),def_benchmark_data(),benchmark(),available_backends(),set_default(), andKernelEntrydataclasscsrmv_yw2ymoved to its own module_csr/yw2y.py(#79)Unified sparse-float dense matmul operations across all formats (#77)
Project description updated to “Enabling Event-driven Computation in CPU/GPU/TPU”
Added Python 3.14 support; dropped Python 3.10 from classifiers
Core dependency
jax>=0.5.0now explicitly required
Fixed#
Pallas GPU
binary_densemmkernel corruption:pl.ds()out-of-bounds reads whenblock_dim > mcorrupted adjacent GPU memory; fixed with scalarpl.program_id()indexing andjnp.whereinstead ofjax.lax.cond(#71)Warp tile operation bug: cooperative tile ops (
tile_load,tile_store,tile_atomic_add) produced diagonal-like output when launch dimensions < 32 threads; replaced with scalar loops in_jit_normal/float.py(#71)Backend passthrough in AD rules: JVP/transpose/batching rules now correctly forward
backend=parameter to*_p_call()functions, preventing silent use of wrong backend for tangent computation (#72)Fixed-connection matmul return values (#62)
Bool-to-float conversion added in
binary_densemm_p_callbefore passing to primitive (#71)
Removed#
BlockCSRclass and_block_csrmoduleBlockELLclass and_block_ellmoduleBaseArray,BinaryArrayIndex,MaskedFloat,MaskedFloatIndexclasses (replaced by new event representations)GPUKernelChoice,pallas_kernel,warp_kernelfrom_op_primitives.pymodule (replaced by_registry.py)
[0.0.5] - 2025-12-25#
Added#
SDDMM (Sampled Dense-Dense Matrix Multiplication) functionality with COO indices
Numba FFI backend for CPU custom kernels (#56)
Warp FFI backend for GPU custom kernels (#56)
STDP (Spike-Timing-Dependent Plasticity) tutorial documentation (#53)
Changed#
Refactored package layout and module organization (#56)
Updated package structure for improved modularity
Refactored binary and float implementation modules
Removed#
Original BrainPy content that was deprecated (#55)
Fixed#
Updated image source in README to use raw.githubusercontent.com for proper display
[0.0.4] - 2025-08-07#
Added#
Centralized primitives registry module for managing JAX primitives (#45)
BlockCSR class with matrix multiplication, transpose, and other methods (#42, #47)
Synaptic weight update operations for sparse matrices in COO, CSR, and CSC formats (#44)
Sparse indexed arrays:
BinaryArrayIndexandMaskedFloatIndexclasses (#43)__hash__method to ArrayBase for supporting hashable arguments (#46)Weighted sparse matrix-vector multiplication
csrmv_yw2yfor CSR/CSC (#41)Diagonal position handling and updates for CSR/CSC matrices (#40)
CSR/CSC sparse solve operations (#36)
Support for warp-lang 1.9.0+ (#52)
Daily CI workflow for improved testing coverage (#27)
Changed#
Refactored BaseArray from classes to pure functions (#43)
Updated BlockCSR methods for improved clarity and performance (#47)
Enhanced type hints throughout the codebase (#27)
Improved weight and dtype checking with relaxed test tolerances (#35, #37)
Updated EINet class to use brainpy and braintools
Updated logo and branding (#50)
Fixed#
CSR solve test tolerances for numerical stability (#37)
CI configuration to use development requirements for CPU installation
[V0.1.0] - 2025-05-02 — GitHub tag only, never published to PyPI#
Historical note: The
V0.1.0git tag was published on GitHub on 2025-05-02 but was never released to PyPI. The PyPI distribution line continued as0.0.1.postN→0.0.2…0.0.7; the first0.1.0published to PyPI is the entry dated 2026-06-07 at the top of this file. This section is retained for historical accuracy.
Added#
Just-In-Time Connectivity (JITC) matrix operators for CSR format (#18)
JITCHomoR,JITCHomoC: Homogeneous weight matricesJITCNormalR,JITCNormalC: Normal distribution weight matricesJITCUniformR,JITCUniformC: Uniform distribution weight matrices
Pallas kernel implementations for GPU/TPU backends (#28, #30)
Tiled Pallas kernels for JITC operators (#30)
JVP/transpose rules for JITC
todense()operations on random matrices (#29)Fixed connection number matrix operations (#25, #31)
FixedPostNumConn: Fixed number of post-synaptic connectionsFixedPreNumConn: Fixed number of pre-synaptic connections
BinaryArray and MaskedFloat classes with optimized dense/sparse operations (#34)
Event-driven dense matrix operations (#24)
COO (Coordinate) sparse matrix implementation with spmv and spmm operators (#7, #15)
CSR (Compressed Sparse Row) and CSC (Compressed Sparse Column) implementations (#26)
Load-balanced CSR/CSC classes (
CSR_LB,CSC_LB) for improved performance (#11)Lazy-loading for ‘nn’ submodule (#16)
Enhanced CSR implementation with Pallas and improved benchmarks (#26)
Changed#
Unified kernel API with direct functions instead of classes (#33)
Unified configuration management with Config singleton (#32)
Improved GPU/TPU backend selection for JITC operators (#28)
Refactored COO and CSR implementations with new type aliases for readability (#14)
Integrated general batching rule for all operator implementations (#13)
Enhanced BinaryArray with additional built-in functions (#5, #24)
Restructured brainevent module documentation (#21)
Improved code formatting and replaced deprecated references (#22)
Added - Infrastructure#
Compatibility layer for JAX version handling and custom call registration (#12)
Development dependencies: absl-py for enhanced functionality
DOI badge from Zenodo (10.5281/zenodo.15324450)
Removed#
Deprecated code for improved JAX compatibility (#19)
Unnecessary files from project structure
Fixed#
Event handling and linear computation for improved performance and readability (#17)
Updated documentation and CI configuration (#20)
[0.0.1] - Initial Release#
Added#
Initial project structure and setup
Basic CSR matrix operations
CSR float tests
CSRMM (CSR Matrix-Matrix multiplication) VJP and JVP rules (#1)
Basic BinaryArray implementation
FixedPostNumConn event and float implementations (#4)
BinaryArray built-in functions
CSR spmv gradient computation (#5)
README and project documentation (#3, #6)
Changed#
Upgraded project structure (#2)
Updated FixedPostNumConn implementation (#4, #5)