Status: current planning baseline, updated 2026-09.
This document describes what remains after the dense Tensor, kernel-dispatch, Krylov, and first async Tensor vertical slices came together. For a description of implemented user-visible capabilities, start with About Uni20. For exact operation contracts, use the linked canonical subsystem guides.
Uni20 remains an active-design C++23 library. The roadmap therefore names engineering outcomes and invariants rather than promising a stable API or fixed release dates.
Current Baseline
The following foundations are implemented and tested.
Tensor and view semantics
Tensor<Element, Rank, ...> is the concrete owner with runtime extents by default and explicit column-major, row-major, or strided layout policy.
- Tensor-level concepts separate readable, mutable, owning, strided, and rank-constrained objects from resolved mdspan operands.
- Generated
full, zeros, ones, and generalized eye tensors avoid dense storage until an operation requires materialization.
conj, reshape_view, explicit ordered reshape views, materializing reshape, copy, make_tensor, and in-place conjugation have documented ownership and accessor semantics.
- Variadic elementwise overwrite and update operations lower through callable-carrying dispatch values to an accessor-respecting CPU reference backend.
ScalarTensor provides a rank-zero owner, while inner product and stable Euclidean norm expose separate storage-preserving and host-scalar result contracts. Full and axis-selective sums use the same distinction.
- All-async elementwise overwrite and update wrappers retain callable state, construct overwrite outputs when possible, and preserve one-writer update semantics.
- All-async sums, inner products, and norms support storage-preserving, host-scalar, and explicit-output forms with deferred output construction.
- Async conjugating and reshape aliases retain the source owner and share its exact epoch queue.
- Async owning reshape supports preserving, consuming, and in-place mapping changes. Copy,
make_tensor, to_host, and to_device cover explicit host and CUDA materialization while preserving accessor semantics.
- Canonical contiguous Tensors transfer between pageable host storage and CUDA storage through explicit blocking
to_host/to_device boundaries. Device and peer copies retain CUDA completion in the buffer ledger, with a dedicated non-blocking Async CUDA-to-CUDA overload.
See Tensor Operations, Generated Tensors and Reshape, and Async Storage.
Dense operation dispatch
- Operation values identify backend-independent work such as elementwise transforms, copy, GEMM, GEMV, matrix exponential, eigensystems, and Schur operations. Values may carry immutable options or callable state.
kernel_accepts_types performs compile-time tri-state capability probing.
try_kernel performs runtime layout/accessor checks and returns a structured clean-decline reason.
dispatch_kernel walks an ordered backend list and produces structured errors when no backend succeeds.
- Host vector storage selects LAPACK, BLAS when configured, and the CPU reference backend in a fixed order.
- Runtime diagnostics can report every candidate, decline reason, and selected backend without changing the operation interface.
- Tensor front ends own output shape and allocation policy, then pass resolved mdspans to leaf kernels.
Current vertical slices include accessor-respecting variadic elementwise transforms, copy/materialization, inner product, stable Euclidean norm, GEMM, GEMV, matrix initialization and exponential, self-adjoint and nonsymmetric eigensystems, exact and truncating SVD, Schur operations, and tridiagonal eigensystems. Backend and scalar coverage is operation-specific rather than uniform.
See Kernel Dispatch, Mdspan Linear Algebra Dispatch, and Mdspan BLAS/LAPACK Wrappers.
Async execution
Async<T>, epoch queues, read buffers, and exclusive mutable write buffers define causal dataflow and storage lifetime.
DebugScheduler, TbbScheduler, and TbbNumaScheduler execute the host task model. DebugCudaScheduler deterministically executes host and multi-device CUDA tasks from one queue. TbbCudaScheduler combines one host arena with one worker-only arena per enrolled CUDA device; device-arena observers establish and restore device state for every activation.
- TBB waits can make scheduler progress from application or worker threads, and
run_all() waits for scheduler quiescence.
- Exceptions and cancellation propagate to output epochs; multi-output tasks can publish independent results or the same failure.
- Task-registry snapshots, presentation reports, optional stacktraces, signal triggers and Graphviz output support diagnosis.
- Async fixed-output contraction, GEMM, GEMV, matrix initialization and exponential, dense solve, matrix-product overwrite/update, preserving or consuming QR/LQ/self-adjoint
eigh/exact and truncating SVD, and general reductions schedule the existing synchronous Tensor operations.
See the Async Documentation Index and Async Tensor Kernel Authoring.
CUDA runtime and first Tensor provider path
cuda::initialize(...) installs a scoped process-wide runtime with one canonical DeviceResources instance for every enrolled device.
- Device discovery, scoped device selection, actually-idle stream pools, completion tokens, typed buffers, and per-buffer completion ledgers are implemented and tested on multi-device systems.
- CUDA tasks can await streams and generic provider resources without blocking a scheduler participant. cuBLAS adds pooled handle-plus-stream execution leases over those primitives.
CudaTensor owns opaque device storage and selects CublasBackend. Async GEMM and matrix-product overwrite/update await a device-bound CudaTask, which acquires a handle-plus-stream lease and lowers through staged CUDA mdspans, synchronized buffer access, and checked S/D/C/ZGEMM provider calls.
- Ordinary
CublasBackend uses blocking resource admission. Async lowering uses generic co_dispatch_kernel; its optional cuBLAS try_make_kernel_task implementation suspends while the same execution resources are unavailable. Both paths share operand preparation and provider execution.
CudaReferenceBackend has a compiled elementwise copy kernel for same-device semantic copies. Raw contiguous storage retains the cudaMemcpyAsync path; conjugated complex storage is evaluated through device-callable accessors and CUDA execution-value proxies.
- The same arity-generic CUDA elementwise executor implements positive-strided in-place conjugation for complex storage. This zero-input update path acquires one exclusive buffer access; trivial real and integer conjugation does not launch.
- Registered same-element-type arithmetic callables exercise one- and two-input overwrite transforms across independently positive-strided CUDA mappings: unary negate, square, and reciprocal; stateful scale; and binary addition, subtraction, multiplication, and division. Other callable types continue to require an explicit compiled lowering.
See CUDA Runtime Foundation, CUDA Buffers, and CUDA Kernel Dispatch.
Krylov and numerical validation
- Native matrix-free Lanczos and Arnoldi solvers cover symmetric/Hermitian, generalized, and nonsymmetric problems.
- Krylov and Taylor exponential-action algorithms provide independent paths for validation.
- Dense projected subspace work uses
DenseMatrix and the normal linalg dispatch layer rather than a private dense algebra stack.
- Matrix Market fixtures, convergence/residual tests, provider comparisons, and the optional MPLAPACK binary128 backend exercise precision-sensitive paths.
See Krylov Algorithms and Krylov Precision Validation.
Presentation and development infrastructure
- Semantic presentation documents render to terminal, plain text, strict ASCII, width-aware tables, and mdspan/tensor previews.
- Kernel-dispatch and async diagnostics use the presentation layer.
- CI covers Debug, Release, and Clang builds, while a separate pull-request workflow validates generated Doxygen documentation.
- Source-module READMEs and contributor/review guidance now provide a navigable development surface.
Immediate Priorities
These are the next implementation tracks. They can proceed in parallel when their contracts do not conflict.
1. Broaden dense linalg vertical slices
Use the existing GEMM/GEMV/eigh shape as the template, not a second wrapper hierarchy.
- Audit the remaining BLAS/LAPACK wrappers for consistent operand descriptors, checked provider failure behavior, scalar promotion, and workspace policy.
- Give ordinary callers allocating, overwrite, update, consuming, or in-place Tensor APIs as appropriate to each operation.
- Keep mdspan leaf functions fixed-output and explicit about layout/accessor requirements.
- Add provider and CPU-reference kernels through operation-tag dispatch where a useful independent reference exists.
- Continue routing Krylov projected operations through these public paths so the solver layer exercises the same kernels as applications.
- Add async wrappers one operation at a time after output construction, consumption, aliasing, and exception behavior are explicit.
- Maintain real/complex, row/column layout, zero/singleton extent, and optional binary128 coverage in proportion to each operation's supported domain.
2. Complete common Tensor operations and structural views
- Build synthetic-diagonal views and trace lowering on the implemented one-or-more-axis CPU sum reduction.
- Extend scalar-result allocation beyond the current static storage-policy model when device/context-bearing storage requires it.
- Add slicing/indexing descriptors with const-correct mdspan access and explicit layout/striding semantics.
- Extend the owner-retaining async alias model to slices and future structural views without allowing descriptors to retarget accidentally.
- Extend the implemented async copy/materialization and reshape operations to future structural views as their overwrite, alias, and consumption semantics become explicit.
- Keep semantic accessor views such as conjugation read-only; treat writable component views such as future
real/imag as true structural slices.
- Introduce subrange dependency tracking only if whole-owner epoch ordering becomes a demonstrated bottleneck. Correct conservative ordering is the baseline.
Dynamic-rank tensors remain a separate future descriptor design. They should not add a second meaning to the current fixed-rank mdspan-based Tensor.
3. Harden async operation composition
- Exercise multi-output success, failure, cancellation, and unobserved-branch behavior as more linalg operations become async.
- Preserve the distinction between independent async values and aliases bound to an owner's lifetime and epoch queue.
- Add coroutine kernel implementations incrementally through
try_make_kernel_task. Backends without one continue through ordinary try_kernel inside co_dispatch_kernel; allocation, mutation, and consumption remain operation-specific Tensor concerns.
- Improve deadlock and task-provenance diagnostics without adding meaningful cost when instrumentation is disabled.
- Integrate future CUDA/MPI external completions with targeted readiness notifications, including when no CPU tasks are runnable.
4. Extend the symmetry-aware block tensor
The bosonic Abelian U(1) BlockTensor path now includes sparse and complete block patterns, separate and packed host storage, packed CUDA storage, mapped views, linear operations, generalized adjacent contraction, staged block SVD, and matrix-free Krylov vector algebra. Remaining work must extend that path without weakening its symmetry metadata contract.
- Broaden operation coverage and introduce specialized packed/coalesced storage only where it improves a measured block workload.
- Extend the implemented host and single-device CUDA worklists and placement records to multi-device and MPI storage.
- Preserve quantum numbers, local spaces, orientations, and logical block keys through every new backend lowering.
- Keep any dense projection explicitly diagnostic and prevent it from feeding back into the symmetry-aware calculation.
- Use coalescing and grouped GEMM only as optimizations over a tested blockwise reference path.
- Extend the staged block SVD while preserving its one-matrix-per-charge factorization, stable metadata-bearing singular-state selections, exact selected bond spaces, and independent kept, discarded, and null-space materializations.
- The implemented block SVD schedules independent host charge sectors by descending estimated cost and keeps supported real CUDA sector matrices, factors, and selected outputs resident around cuSOLVER. Next, broaden CUDA scalar/shape coverage and make provider completion asynchronous without changing the selection contract.
See BlockTensor Design, Raw Primitives and Symmetric Lowering, and Block Coalescing.
5. Extend the pure-Uni20 DMRG vertical slice
Pure Uni20 now implements finite bosonic U(1) two-site DMRG, matrix-free fixed-work Lanczos, block-sparse environments and centers, truncating block SVD, and host or single-device resident-CUDA sweeps. The historical tensorcontraction-integration branch remains a functional MPI and performance reference. The goal is to extend capability and scale through Uni20's current architecture without retaining the external TensorContraction implementation.
- Extend the implemented dispatched sparse R/A/B/C plan and host/CUDA right-first
(B,C) reuse with backend-aware left-first/hybrid selection and multi-device placement.
- Extend the implemented finite-chain owners, revision-aware directional environment caches, selected-SVD factor absorption, and directional sweep traversal with post-truncation measurement and general initial-state canonicalization.
- Extend the implemented U(1) spin-half local-space, Néel product-MPS, and reduced-boundary Heisenberg-MPO builders and converged alternating sweep driver into later model families.
- Rebuild MPS, MPO, environment, model, and sweep operations over explicit Uni20 ownership, tensor-view, and async contracts.
- Replace branch-specific block containers with the symmetry-aware
BlockTensor and preserve every quantum-number and leg-orientation invariant.
- Reproduce the integration branch's U(1) Heisenberg and U(1)xU(1) Fermi-Hubbard numerical checks and sweep diagnostics.
- Extend the kernel-dispatched effective-Hamiltonian R/A/B/C operation through placement, device-completion, and communication abstractions.
- Extend the resident CUDA center, environment, local eigensolver, block-SVD, and MPS-installation path to multi-device placement; recover MPI execution incrementally using captured R/A/B/C fixtures and branch benchmark results as regression evidence.
- Treat successful parity as migration of capability, not a source-level port: reuse algorithms and validated conventions while replacing the bridge's scheduler, ownership, storage, and backend boundaries.
See Tensor-Network Documentation, TensorContraction Integration Findings, and R/A/B/C Contraction Scheduling.
Heterogeneous Execution Track
Uni20 follows a device-aware design rule: host-only assumptions must not become part of core Tensor, storage, dispatch, or async contracts. This does not mean that incomplete CUDA code takes priority over every host operation. It means that host vertical slices must leave the correct extension points.
The Deployment Environment records the scheduled multi-node, x86-64/AArch64, and multi-generation GPU systems that motivate these constraints.
Extend device-aware foundations
- Preserve the implemented split between compile-time storage memory kind and runtime location such as CUDA device ordinal or MPI rank.
- Keep CUDA events and buffer completion ledgers as backend completion evidence;
EpochQueue remains the causal ordering model for Async<T>.
- Extend the explicit host/device transfer operations to peer-device and distributed movement without hiding synchronization inside ordinary backend fallback.
- Add storage-driven initial scheduler admission after its ownership and process-wide scheduler-lifetime contract is defined.
- Keep backend selector state immutable unless a concrete stream, communicator, precision, or algorithm use case demonstrates a need for stateful values.
Incremental CUDA and cuSOLVER
- Bring up one operation at a time through the same capability and runtime attempt mechanism used by host kernels.
- Extend the implemented blocking real tall-matrix cuSOLVER exact SVD with wide and complex lowering, then add an asynchronous completion boundary.
- Use the current
Async<CudaTensor> matrix-product path as the non-blocking correctness baseline. Keep resource admission in the CUDA coroutine and provider submission in the non-suspending backend leaf.
- Extend provider coverage through cuBLAS, cuSOLVER, and reference CUDA kernels only after each Tensor operation's output, aliasing, and failure contracts are explicit.
- Do not allow ordinary backend fallback to copy device operands to host. Emergency transfer-based implementations must be explicit composite operations whose cost and synchronization are visible.
Distributed execution
- Represent placement and communication policy above the ordering layer.
- Lower cross-rank edges to nonblocking MPI/NCCL operations with deterministic identity and active progress.
- Preserve block and symmetry metadata across placement and transfer.
- Optimize throughput without making correctness depend on one placement strategy.
See Storage Kind and Location, Ordering Ownership, and CUDA Buffer Completion Lowering. Future distributed planning and commitment constraints are recorded in Distributed Kernel Dispatch.
Later Integration Work
Tensor-level reverse-mode AD
Extend the existing async value-level AD machinery only after the Tensor operation set has explicit mutation, consumption, and alias contracts. Linalg rules must cover real and complex conventions, multi-output decompositions, absent gradients, graph pruning, and failure propagation.
Python and notebook interface
Bind stable C++ Tensor operations through checked dynamic dispatch boundaries. Python should validate user errors before entering invariant-enforced C++ code, translate recoverable diagnostic exceptions, and use the presentation model for plain and rich notebook output. Packaging and dtype promotion policy belong to this track.
Expression and fusion layer
Do not build a generic expression system merely to provide operator syntax. Introduce expression nodes only when a measured operation sequence benefits from fusion, reduced temporaries, or a backend-specific compound kernel. The existing explicit Tensor operations and async DAG remain the semantic baseline.
Definition of a Complete Operation Slice
A substantial new Tensor/linalg operation is complete when the relevant items below are addressed:
- The mathematical, shape, alias, ownership, and failure contracts are documented.
- The Tensor front end chooses allocating, overwrite, update, consuming, or in-place semantics deliberately.
- Tensor-view operands use operation-tag dispatch and structured clean decline; the selected backend lowers them to resolved mdspan leaf kernels.
- At least one deterministic implementation exists, with an independent test oracle where practical.
- Provider-specific paths have scalar, layout, workspace, and provider-error coverage.
- Async lowering, when exposed, owns buffers and ordinary parameters for the coroutine lifetime and routes failures to every output.
- A focused example or test demonstrates the complete path rather than only a leaf helper.
Guardrails
- Maintain C++23 and the captureless
static coroutine-lambda rule.
- Treat accessor semantics, storage domain, and symmetry metadata as correctness constraints.
- Keep backend decline free of execution effects. Operation-authorized preparation of a replaceable output may survive a decline; execution failure is not fallback.
- Make allocation, materialization, transfer, synchronization, and dense projection explicit.
- Prefer incremental vertical slices with independent numerical evidence over broad interface scaffolding.
- Update current guides and examples in the same change when behavior moves. Update AI guidance only when a durable repository-wide convention or invariant changes.