tensor-roll / docs /BOUNDARIES.md
SNAPKITTYWEST's picture
October 2026 main drop: mirror from GitHub
9e551a1 verified
|
Raw History Blame Contribute Delete
11.9 kB

Tensor Roll β€” process / IR boundaries

Copyright (C) 2026 SnapKitty Collective β€” AGPLv3.

This document states exactly where one execution domain ends and another begins. There are three boundaries that matter; none of them is a wrapper around an existing framework, and none of them is invented.

1. Classical dispatch boundary: TensorRoll β†’ GEMM vs quantum candidate

Location: tensor_roll/core.py β€” dispatch_matmul() and evaluate_options() / qsim_encode_for_roll.

The recursive operator TensorRoll(T, axis, depth, rank, quantum_policy) partitions a tensor and evaluates candidate representations per leaf. Ordinary candidates (PRESERVE / QUANTIZE / FACTORIZE / MERGED / ROUTED / RECONSTRUCTED / PRUNED) execute as NumPy on CPU and every report labels them backend: cpu-numpy.

A leaf is eligible for the quantum path only when all of these hold:

  • quantum_policy != "off" (CLI: roll --quantum-policy, default for demo is explore),
  • the leaf block has at most QUANTUM_ELIGIBLE_MAX = 256 elements (8 qubits β€” an honest near-term register size),
  • a qsim encoder is supplied.

Eligible leaves gain QUANTUM-ENCODED / RECONSTRUCTED / ROUTED candidates whose numbers come from the real statevector simulator in tensor_roll/qsim.py. Their reports are labeled backend: qsim-classical, device: cpu (statevector simulator). That label is the boundary: it is classical linear algebra (complex128 statevectors, explicit unitary application, Born-rule sampling), never a QPU, and it never claims to be one.

On a machine with the NVIDIA CUDA-Q toolchain, the same kernel family in cudaq/tensor_roll_kernels.py can execute for real (run_smoke() targets qpp-cpu); on this machine the import fails and the module prints unavailable instead of pretending.

2. CUDA-Q ↔ Q# boundary: serialized trace artifact (real, not an API)

There is no direct CUDA-Q ↔ Q# linkage β€” the two toolchains do not share an in-process API, and inventing one would be fabrication. The real boundary is a serialized artifact produced by tensor_roll/boundary.py:

  • trace_for_kernel(kernel, n_qubits, angles, depth) builds the gate-level IR: the exact gate sequence (ry / cnot / measure / reset) that both cudaq/tensor_roll_kernels.py and qsharp/TensorRoll.qs implement. Each gate carries its QIR op name (__quantum__qis__ry__body, …) so the trace maps 1:1 onto QIR when both vendor toolchains are present.
  • write_trace(path, ...) writes {sha256, trace} JSON: schema version, kernel name, qubit count, shots, the gate list, the measurement counts, producer label, and timestamp.
  • read_trace(path) refuses the file if the SHA-256 does not match or the schema is wrong.
  • counts_to_amplitudes(trace) is the shared classical reconstruction estimator (amplitude = sqrt(count/shots)) β€” classical by construction on every side of the boundary.

Data flow:

CUDA-Q process (cudaq/tensor_roll_kernels.py)
        β”‚  executes kernels (needs CUDA-Q toolchain + target)
        β–Ό
boundary.json  {gates, counts, sha256}     <-- the boundary: a file
        β–²
Q# toolchain (qsharp/TensorRoll.qs)
        β”‚  implements the same gate sequence; reads/writes the artifact

tensor-roll qkernel writes qkernel/boundary.json on every run and immediately re-reads it to prove the round trip. Corrupt the file and the reader rejects it β€” verified by the test suite.

What is NOT claimed: at no point does tensor-roll convert CUDA-Q objects to Q# objects in memory. The handoff is serialization, honestly labeled.

3. Sandbox boundary: supervisor ↔ untrusted child

Location: tensor_roll/sandbox.py, exercised by tensor-roll sandbox.

  • The child runs in its own session/process group (start_new_session), with rlimits (address space, CPU, file size, process count), a filtered environment (only PATH/LANG/TZ/HOME survive), and cwd pinned to a jail directory.
  • Policy: absolute paths must resolve inside the jail; the binary must be on an allowlist or not on the denylist (deny wins). Network namespaces are entered via unshare(CLONE_NEWNET) when the kernel permits it β€” probed at startup and reported (netns_available=True/False); on this machine the probe passes, so qkernel-adjacent untrusted code genuinely loses network access.
  • Every spawn, policy verdict, timeout, and signal is appended as JSONL to sandbox/audit.log.

Signals: on timeout the supervisor kills the whole process group (killpg(SIGKILL)), then reaps strays the same way. The audit log records which.

4. What runs where (summary table)

Component Executes on Label in reports
Tensor math, training, search NumPy / CPU cpu-numpy
Quantum kernel candidates classical statevector sim qsim-classical
CUDA-Q kernels NVIDIA toolchain (absent here) unavailable here
Q# operations Q# toolchain (absent here) unavailable here
CUDA-Q ↔ Q# handoff serialized boundary.json sha256-verified
Untrusted subprocesses sandboxed child audit-logged

If a row says unavailable, no number was invented for it β€” the CLI prints unavailable and the docs say what hardware would change that (see docs/ARCHITECTURE.md).

Integration state (failure-resolution audit, 2026-09-29)

Finding: file-mediated. The CUDA-Q ↔ Q# handoff in this repository is a checksummed serialized JSON trace artifact on disk β€” not a direct in-process API, not live QIR/MLIR bitcode exchange, and not process-to-process RPC. Vendor-toolchain execution on this machine is additionally source-only: CUDA, CUDA-Q, and Q# all probe UNAVAILABLE here, so no vendor kernel has ever executed on this box. The file artifact itself round-trips for real (tensor-roll qkernel writes qkernel/boundary.json and re-reads it; test_trace_roundtrip corrupts it and watches the reader refuse).

Candidates considered and rejected:

  • direct β€” rejected. tensor_roll/boundary.py states the two toolchains "do not share an in-process API", and no code path converts CUDA-Q objects to Q# objects in memory.
  • IR-mediated (true QIR/MLIR bitcode) β€” rejected for this machine. boundary.py notes "True QIR/MLIR bitcode exchange requires both vendor toolchains installed"; neither is installed, so the QIR op names carried on each gate (__quantum__qis__ry__body, …) are a mapping specification, not an executed exchange.
  • process-mediated β€” rejected. No live RPC exists between a CUDA-Q process and a Q# process; the handoff is a file both sides can write/read.
  • file-mediated β€” ACCEPTED. Evidence below.
  • source-only β€” true of execution on this machine (see probes), but the integration mechanism itself is richer than source-only: the trace artifact is really written, checksummed, read, and verified on every qkernel run via the qsim-classical path.

File/line evidence (from tensor_roll/doctor.py::integration_state()):

  • tensor_roll/boundary.py:7 β€” "an in-process API. The real boundary used by tensor-roll is a serialized," [no direct linkage; artifact, not API]
  • tensor_roll/boundary.py:8 β€” "checksummed, versioned artifact containing:" [integrity-checked artifact]
  • tensor_roll/boundary.py:20 β€” "True QIR/MLIR bitcode exchange requires both vendor toolchains installed;" [true QIR/MLIR exchange needs toolchains]
  • tensor_roll/boundary.py:57 β€” def trace_for_kernel(...) [gate IR constructor: the single source of truth both kernel families implement]
  • tensor_roll/boundary.py:102 β€” def write_trace(...) [trace is WRITTEN to disk as {sha256, trace} JSON]
  • tensor_roll/boundary.py:130 β€” def read_trace(...) [trace is READ from disk; checksum/schema mismatch raises]
  • tensor_roll/cli.py:291 β€” bpath = os.path.join(wdir, "qkernel", "boundary.json") [CLI writes the file artifact]
  • tensor_roll/cli.py:296 β€” back = BD.read_trace(bpath) [CLI verifies the round trip immediately]
  • cudaq/tensor_roll_kernels.py:9 β€” "These kernels are NOT executed by the tensor-roll CLI on machines without" [the CUDA-Q toolchain]
  • cudaq/tensor_roll_kernels.py:28 β€” _HAS_CUDAQ = False [toolchain-absent fallback path]
  • qsharp/TensorRoll.qs:13 β€” "NOTE: not compiled or executed in this repository's test environment" [source-only on this machine]

Live probes on this machine (tensor-roll doctor, 2026-09-29):

  • CUDA: UNAVAILABLE β€” no nvidia-smi on PATH, no /dev/nvidia* devices.
  • CUDA-Q: UNAVAILABLE β€” no toolchain (ModuleNotFoundError from a neutral directory; the repo-local cudaq/ directory is a namespace package of kernel source, not the NVIDIA toolchain).
  • Q#: UNAVAILABLE β€” no toolchain and no dotnet; the repo-local qsharp/ directory is operation source, not an installed toolchain.
  • GPU: NONE. CPU (NumPy) executes for real and passes.

What would change this determination: installing the NVIDIA CUDA-Q toolchain and a Q# toolchain would move the execution rows from source-only to executed, but the integration state would remain file-mediated until a real QIR/MLIR bitcode handoff (not just a JSON trace carrying QIR op names) is demonstrated between the two toolchains.

Failure-resolution modules (2026-09-29)

Out-of-core boundary (tensor_roll/ooc.py)

The streaming path never confuses "addressable" with "in RAM":

  • A VirtualManifest carries shapes, dtypes, and byte offsets only. reader() raises RuntimeError β€” there is no silent path from a virtual manifest to weight data.
  • MappedTensor.view is an np.memmap view; TensorWindow.data materializes only the window. RollWorkspace accounts the logical working set against an explicit ceiling and raises MemoryBudgetExceeded past it. Measured: virtual 30B planning peaks at 35MB RSS β€” the bound is demonstrated, not asserted.
  • StudentWriter checksums every emitted tensor (SHA-256); verify() re-hashes on resume and refuses mismatches. Checkpoints are JSON + SHA-256 with atomic replace; corruption is refused, never loaded.
  • The .npz repack path reads one array at a time into the shard format; .safetensors is windowed in place via mmap with zero copy.

Planner boundary (tensor_roll/planner.py)

  • plan() lands the allocation on the requested target (≀ 8.0B by default) and never above the 8.5B hard cap. Sensitivity is measured from sampled windows (calibrate_sensitivity) or documented as uniform 0.5 when no data exists β€” the planner degrades to a uniform ratio rather than inventing sensitivity.
  • The 30B STRUCTURAL SCALE TEST label is load-bearing: it certifies storage addressing and planning under bounded RAM, and explicitly does not certify model quality. Actual 30B weights: NOT TESTED.

Fidelity boundary (tensor_roll/fidelity.py)

  • divergence_trace() measures on teacher-forced contexts so model divergence is isolated from context drift; free-run agreement (the 3/24 number) is reported separately and never mixed with it.
  • fidelity_aware_select() applies the divergence penalty uniformly to every decision class from measured (sensitivity, reconstruction error). Quantum-gated options are scored from their own qsim-measured errors β€” the penalty cannot prefer or punish a backend beyond what the measurements say.
  • Ablations replace student components with shape-aligned teacher weights and report Ξ”agreement/Ξ”KL; components that cannot be aligned are skipped and reported as skipped, not zeroed.

INT4 boundary (tensor_roll/quant.py)

  • Scheme choice (per-tensor / per-channel / group-wise) is the argmin of measured MSE per tensor, never a hard-coded default.
  • recovery_train() reports PPL before training, after training, and after requantization; "improved" is a measured boolean, not a claim.