|
Uni20
Asynchronous tensor and runtime library.
|
A C++23 research library for asynchronous, symmetry-aware tensor networks on CPUs and NVIDIA GPUs.
Uni20's target is tensor-network calculations over tensor categories with non-trivial braiding, at the scale of large GPU clusters. That means grappling with tensor data that is block sparse, numerical work that spans multiple libraries and devices, and dependencies between operations too complex to manage by hand. The current prototype validating that architecture end to end is a U(1)-symmetric two-site DMRG calculation for the spin-half Heisenberg chain that exercises the async runtime, ordered CPU/GPU backend dispatch, and block-sparse tensor model together, running on multiple CPUs or a single NVIDIA GPU.
[!IMPORTANT] Uni20 is an early-stage research project, not a stable released library. APIs and algorithms are evolving, backend coverage is operation-specific, and the code currently serves as an executable design and validation platform rather than a general-purpose tensor-network package.
Uni20 already contains several connected, tested vertical slices:
BlockTensor model with typed domain/codomain spaces, sparse and complete block patterns, packed host and CUDA storage, structure-preserving contraction and linear operations, and staged per-charge-sector SVD and truncation;Tensor values with compile-time rank and runtime extents, generated tensors, structural views, reductions, contractions, decompositions, and matrix-free Krylov algorithms;float/double paths across the supported host and CUDA operations, plus binary128 via MPLAPACK;A supported C++23 compiler, CMake 3.28 or newer, and BLAS/LAPACK are required. Compatible versions of oneTBB, fmt, GoogleTest, and Google Benchmark can be fetched by CMake when they are not installed locally.
The current CPU build supports real or complex fp32, fp64, and — when built with -DUNI20_ENABLE_FLOAT128=ON -DUNI20_BACKEND_MPLAPACK=ON — real or complex fp128, selectable at runtime via --scalar=real|complex and --precision=fp32|fp64|fp128.
For a CUDA build with cuBLAS and cuSOLVER:
The current CUDA DMRG executable supports real double precision. See the model example guide for larger fixtures, execution and storage controls, reference energies, and benchmarking rules.
The following three sections explain the design ideas that make this possible: ordinary algorithms lift to async execution unchanged, and each backend runs or declines independently.
Async<T> represents a value of type T together with its lifetime and read/write history. Uni20 tensor operations accept either ordinary tensors or their asynchronous counterparts with the same names and mathematical meaning. The intended change to an algorithm is deliberately small:
Call the same function with either ordinary or asynchronous matrices:
In the async version, each call schedules its operation to run asynchronously and returns immediately. Because they write the same output, Uni20 automatically orders the update after the initial product. The caller does not connect task handles or insert a barrier.
Internally, each Async<T> has an EpochQueue that records which operations read and write the value. Those accesses form an implicit dependency graph: an operation may have to wait until an earlier read or write on the same value has finished before it can run. Blocking a worker thread on that wait would defeat the point of scheduling in the first place, so Uni20 represents each operation as a C++ coroutine — a resumable function that can suspend mid-execution and be resumed later without tying up a scheduler participant while it waits. When an operation's data, CUDA stream, or provider handle isn't ready, it suspends there; when the dependency becomes ready, execution resumes with the operation's state and storage still alive in the coroutine frame.
The scheduler is therefore responsible only for running ready work; the epoch queues are responsible for causal ordering. The same algorithm can run through a deterministic debug scheduler, concurrently through oneTBB, or with CUDA completion integrated into the tensor's storage timeline. This enables the same algorithm to run in a serial configuration or on multiple CPUs or GPUs with no changes to the algorithm.
An operation can have several implementations, ordered from the most specific or optimized to the most general, and Uni20 tries them in order until one succeeds. Some declines are settled at compile time — a kernel simply has no instantiation for a given combination of types — while others are run-time decisions: an optimized contraction can decline a layout it doesn't handle, or a provider can decline a scalar type it doesn't support, and the next compatible backend gets its turn. A build without an optional library simply leaves that backend out of the chain entirely. The algorithm itself contains no backend-specific fallback tree, and individual backends never redispatch to one another.
Declining is safe only before real computation starts — a backend may prepare output storage first, but once a provider call or GPU kernel actually launches, a failure is reported rather than retried on another backend.
Uni20's BlockTensor type carries a typed domain and codomain of quantum-number spaces on each leg, not just raw extents. Those spaces enumerate which sectors exist and which combinations of incoming legs can fuse to which outgoing sector; contraction, decomposition, SVD, and truncation all walk that structure directly, producing sparse and complete block patterns rather than a dense array that happens to contain zeros.
Current host and single-GPU paths are stepping stones toward multi-GPU and MPI-distributed block placement, not assumptions embedded in the tensor interface. The finite U(1) DMRG path is the first application where async causality, ordered backend dispatch, symmetry metadata, and device-resident execution meet end to end.
The immediate and async paths converge before numerical backend execution; the async layer does not duplicate BLAS, LAPACK, CUDA, cuBLAS, or cuSOLVER kernels. Before backend selection, tensor views retain storage and execution policy. After selection, fixed operands become lightweight mdspec descriptors. The backend that accepts the operation acquires the appropriate host or CUDA access and lowers to an mdspan, provider call, or lower-level Uni20 kernel.
The immediate research program is to make symmetry-aware DMRG efficient at much larger bond dimensions and on heterogeneous systems. The main tracks are:
Async<T>, epochs, coroutine ownership, and scheduler responsibilities.Uni20 is being developed as an open research platform. Collaboration is especially welcome around GPU numerical kernels and scheduling, block-sparse algorithms, multi-GPU and distributed execution, symmetry models, and potential applications. Use GitHub issues for technical proposals, reproducible problems, and research discussions.