Frequently Asked Questions#
Do I need a GPU to use brainevent?#
No. Event-driven array and sparse-matrix operations run on CPU, GPU, and TPU. A GPU (and a host C++ compiler) is only required when you compile custom C++/CUDA kernels. See Installation.
Do I need to install the CUDA Toolkit separately?#
No. Installing jax[cuda12] or jax[cuda13] pulls in the nvidia-* pip packages,
which already bundle nvcc, ptxas, and the CUDA runtime and headers. You still need the
NVIDIA driver and a host C++ compiler (g++/clang++). Details in
Installation.
How does the event-driven optimization actually work?#
When you multiply a BinaryArray by a connectivity structure,
brainevent dispatches a kernel that iterates only over the active spike indices and
accumulates their contributions. Work scales with the number of spikes, not the size of the
matrix. See What is event-driven computation?.
Which connectivity format should I use?#
Large random connectivity → JITC (memory independent of synapse count).
Fixed number of connections per neuron →
FixedPreNumConn/FixedPostNumConn.
See Choose a connectivity format and Sparse format trade-offs.
Can I learn or inspect individual JITC weights?#
No. JITC connectivity is regenerated from a seed inside the kernel and never materialised, so
individual weights are not addressable. Use an explicit CSR matrix when
you need plastic or inspectable weights. See Just-in-time connectivity.
Are computations reproducible?#
Yes. JITC connectivity is fully determined by its seed — the same seed reproduces the
same matrix across processes and devices. Combine with JAX’s own PRNG-key discipline for
end-to-end reproducibility.
Can I attach physical units to weights?#
Yes. brainevent integrates with BrainUnit, so
weights and currents can carry units and be dimensionally checked, with no runtime cost. See
Compute with physical units.
Which custom-kernel backend should I use?#
Numba (CPU) / Numba-CUDA, Warp (GPU) — convenient, decorator-based, no separate compiler step.
Raw C++/CUDA — maximum control, or to reuse existing native code.
For raw CUDA kernels, brainevent compiles your source via nvcc, registers XLA FFI
targets, and caches compiled artifacts on disk for fast reloads. See
The custom-kernel architecture and Compile a raw CUDA/C++ kernel.
How do I ship a custom CUDA kernel with my project?#
Place the kernel in a co-located .cu file and load it at import time:
# my_module/my_kernels.py
from pathlib import Path
from brainevent import load_cuda_file
_module = load_cuda_file(
Path(__file__).parent / "my_kernels.cu",
target_prefix="my_module.my_kernels",
)
Annotate each entry point in the .cu file with // @BE:
// @BE my_kernel arg arg ret stream
void my_kernel(const BE::Tensor& input,
const BE::Tensor& weights,
BE::Tensor& output,
int64_t stream) {
// kernel launch code
}
load_cuda_file compiles the kernel on first use, caches the .so to disk, and registers
it as a JAX FFI target. Subsequent imports skip recompilation (see
Caching).