Chunk (large-scale, anti-OOM)¶
chunk ¶
MemoryPressureError ¶
Bases: RuntimeError
Raised when available system RAM drops below the configured safety threshold. Catches the condition before the allocator attempts and crashes with jaxlib.xla_extension.XlaRuntimeError: RESOURCE_EXHAUSTED.
SafeMemoryGuard ¶
Monitors system RAM before every high-memory operation and blocks execution
if free RAM falls below threshold_pct of total physical memory.
Source code in dense_evolution/chunk.py
check_allocation ¶
Like check(), but sized: verifies that required_mb can be allocated while still leaving threshold_pct free afterwards — check() alone only looks at RAM free right now, independent of what's about to be allocated (needed for Chunk's multi-chunk path, where several chunk-sized simulators are held in RAM at once).
Source code in dense_evolution/chunk.py
MemoryChunker ¶
Geometry calculator for chunked simulation.
Attributes¶
n_qubits int — requested logical qubit count dtype — numpy/jax dtype for the statevector chunk_size_bits int — safe qubit-width that fits in RAM num_chunks int — number of statevector chunks required chunk_dim int — 2 ** chunk_size_bits
Source code in dense_evolution/chunk.py
geometry ¶
CircuitChunker ¶
CircuitChunker(
simulator_instance: Optional[DenseSVSimulator] = None,
memory_threshold: float = 0.15,
)
Transpile a circuit once, then execute it in fixed-size gate-slices so XLA sees the same trace shape on every compilation.
A SafeMemoryGuard is checked before every slice — if RAM drops below 15% the current slice is aborted with MemoryPressureError before JAX attempts the allocation.
Parameters¶
simulator_instance : DenseSVSimulator Physical simulator (sized to safe_qubits, not logical n_qubits). memory_threshold : float Passed to SafeMemoryGuard. Default 0.15 (15%).
Source code in dense_evolution/chunk.py
split_circuit ¶
Execute circuit in slices of chunk_size gates.
Raises¶
RuntimeError if no simulator instance is attached. MemoryPressureError if RAM drops below threshold before a slice.
Source code in dense_evolution/chunk.py
Chunk ¶
Chunk(
n_qubits: int,
chunk_size_gates: int = 500,
memory_threshold: float = 0.15,
use_gpu: bool = False,
use_float32: bool = False,
)
Anti-OOM wrapper for large-qubit simulation.
Does NOT subclass DenseSVSimulator directly — the parent init allocates 2**n_qubits elements immediately (17 GB for 30 qubits).
For n_qubits <= chunk_size_bits (the RAM-safe budget): a single inner simulator is allocated and the logical qubit count is stored separately.
For n_qubits > chunk_size_bits: num_chunks separate chunk_size_bits-qubit simulators are held in RAM simultaneously (see _dispatch_multi) — no disk/memmap paging, so this only covers a moderate overflow beyond the safe budget (as many chunks as actually fit in RAM at once, checked up front via SafeMemoryGuard.check_allocation before anything is allocated). Benchmark attributes (num_chunks, chunk_size_bits, dtype) are forwarded transparently from the embedded MemoryChunker.
A SafeMemoryGuard fires before any simulator is instantiated (pre-allocation check) and is also embedded in CircuitChunker for per-slice protection during execution (n_qubits <= chunk_size_bits path).
Parameters¶
n_qubits : logical qubit count of the target circuit chunk_size_gates : gate-slice size for JIT compilation (default 500) memory_threshold : free-RAM fraction below which execution is blocked (default 0.15 = 15%) use_gpu : forwarded to DenseSVSimulator use_float32 : forwarded to DenseSVSimulator
Source code in dense_evolution/chunk.py
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 | |
sv
property
writable
¶
Current statevector. For num_chunks==1, the physical (chunk-sized)
simulator's own array. For num_chunks>1, the chunks concatenated in
ascending order — valid because of the MSB-first correspondence
between chunk index and the top _m logical qubits (see
_dispatch_multi's docstring).
memory_mb ¶
RAM used by the physical statevector(s) in MB.
get_probabilities ¶
|amplitude|^2 for every basis state.
num_chunks==1: forwards to the inner DenseSVSimulator for parity with its own get_probabilities().
num_chunks>1: concatenates the RAW statevectors first and normalizes ONCE over the full array — NOT each chunk's own get_probabilities() (that would independently renormalize each chunk's partial mass to 1, summing to num_chunks overall and destroying the relative weighting between chunks).
Source code in dense_evolution/chunk.py
get_statevector ¶
Full complex statevector, num_qubits logical qubits long
(2**n elements). num_chunks==1: forwards to the inner
DenseSVSimulator. num_chunks>1: raw chunks concatenated in order
(see sv property).
Source code in dense_evolution/chunk.py
dispatch_distributed ¶
Executes circuit the same way _dispatch_multi does, but with each chunk pinned to its own physical JAX device instead of all chunks sharing one process's RAM — see _build_distributed_chunk_step/_build_distributed_chunk_runner for the kernel. Requires jax.device_count() >= num_chunks (v1 scope: exactly one chunk per device); raises RuntimeError otherwise rather than silently falling back to the single-process path, since that would silently give up the whole point of calling this method instead of run_chunk().
The (num_chunks, chunk_dim) logical array is never materialized on any single device here (unlike _dispatch_multi, where it's one process's RAM) -- each device holds and ever sees only its own (chunk_dim,) row, exchanging edge data with its stride-partner device via jax.lax.ppermute inside the kernel, not through this Python method.
Source code in dense_evolution/chunk.py
run_chunk_distributed ¶
Like run_chunk(), but dispatches across a real JAX device mesh (dispatch_distributed) instead of one process's RAM — issue #1. Requires jax.device_count() >= num_chunks; raises RuntimeError otherwise (see dispatch_distributed's docstring for how to test this with simulated multi-device CPU).