nx_sparse_tensor.nx
buildroot/runtime/nx_sparse_tensor.nx
about
nx_sparse_tensor.nx -- compressed sparse row tensor + sparse matmul.
FIRST algo-led-not-brute-force kernel per the
min-hardware-floor cardinal. Post-softmax attention is mostly zero;
LLM weights after pruning are mostly zero; world-model frame deltas
are mostly zero. Skipping those zeros is 10-100x speedup on the
substrate AND 10-100x memory reduction -- both essential for the
"$50 SBC beats Genie 3 in coherence" trophy.
CSR (Compressed Sparse Row) format:
row_ptr[m+1] -- row_ptr[i+1] - row_ptr[i] = nnz in row i
col_idx[nnz] -- column index of each non-zero
values[nnz] -- the non-zero values themselves
For an M x N dense matrix with NNZ non-zeros:
dense storage = M * N * 8 bytes
CSR storage = (M+1) * 8 + NNZ * 16 bytes
crossover = NNZ < M * N / 2 (sparsity > 50%)
typical attention = NNZ ~ M * N / 100 (>99% sparse)
Operations shipped:
dense_to_csr -- materialise a dense tensor as CSR
csr_to_dense -- back-convert (audit + numeric_oracle gate)
csr_matmul_dense -- C[m, n] = sum over non-zero entries of row m
times dense column n. Skips ZERO ROWS entirely.
O(NNZ * N) instead of O(M * K * N).
Future variants (gated on oracle):
AlphaTensor 2022 / AlphaEvolve 2025 sparse-matmul algorithms
register here as alternative dispatch entries.
genealogy_id: tinkham_1969_sparse_matrices + bell_garland_2009_csr +
pissanetzky_1984 + alphatensor_2022
lineage_id: substrate_sparse_tensor_v1
dependencies 3 imports · 1 importers
imports: nx_syscalls.nxnx_tier.nxnx_tensor.nx
imported by: nx_sparse_tensor_test.nx
structs
| 82 | struct NxSparseTensor |
consts
| 46 | const NX_MAGIC_1024: i64 = 1024 |
| 52 | const NX_SP_FMT_CSR: nx_int = 0 // Compressed Sparse Row |
| 53 | const NX_SP_FMT_COO: nx_int = 1 // Coordinate (queued) |
| 54 | const NX_SP_FMT_CSC: nx_int = 2 // Compressed Sparse Column (queued) |
| 55 | const NX_SP_FMT_BSR: nx_int = 3 // Block Sparse Row (queued; matches Goto's block-tiling) |
| 56 | const NX_SP_FMT_N_KINDS: nx_int = 4 |
| 66 | const NX_SP_OK: nx_int = 0 |
| 67 | const NX_SP_ERR_BAD_DTYPE: nx_int = 1 |
| 68 | const NX_SP_ERR_BAD_NDIM: nx_int = 2 |
| 69 | const NX_SP_ERR_SHAPE_MISMATCH: nx_int = 3 |
| 70 | const NX_SP_ERR_NNZ_OVERFLOW: nx_int = 4 |
| 71 | const NX_SP_ERR_UNSUPPORTED: nx_int = 5 |
| 72 | const NX_SP_N_VERDICTS: nx_int = 6 |
| 93 | const NX_SP_BYTES: nx_int = 64 // 8 fields * 8 |
functions
| 58 | func nx_sp_fmt_is_valid(f: nx_int) -> nx_int called by 1: main |
| 74 | func nx_sp_verdict_is_valid(v: nx_int) -> nx_int called by 1: main |
| 101 | func nx_sp_alloc(n_rows: nx_int, n_cols: nx_int, max_nnz: nx_int, |
| 126 | func nx_sp_dense_to_csr(t: *NxTensor, s: *NxSparseTensor) -> nx_int called by 1: main |
| 159 | func nx_sp_csr_to_dense(s: *NxSparseTensor, out: *NxTensor) -> nx_int |
| 193 | func nx_sp_csr_matmul_dense(a: *NxSparseTensor, b: *NxTensor, c: *NxTensor) -> nx_int |
| 234 | func nx_sp_sparsity_ratio_q10(s: *NxSparseTensor) -> nx_int called by 1: main |
| 245 | func nx_sp_estimated_speedup_q10(s: *NxSparseTensor) -> nx_int called by 1: main |