CUDA-Q Backend
The CUDA-Q backend leverages NVIDIA GPUs via the cuda-quantum framework. When no compatible GPU is detected it transparently falls back to a CPU target, so the same code prototyped on a laptop will also run on an accelerated machine.
Installation
CUDA-Q is not shipped with QiliSDK, install the build that matches your CUDA toolkit yourself and the backend becomes available:
pip install "cuda-quantum-cu12>=0.14.0" # or cuda-quantum-cu13
Note
CudaqBackend requires CUDA-Q 0.14.0 or newer. CUDA-Q publishes no wheels for Python 3.14, so
the backend is unavailable there until it does.
Quick start
import numpy as np
from qilisdk.digital import Circuit, H, RX, CNOT
from qilisdk.backends import CudaqBackend, CudaqSamplingMethod
from qilisdk.functionals import DigitalPropagation
from qilisdk.readout import Readout
circuit = Circuit(2)
circuit.add(RX(0, theta=np.pi / 4))
circuit.add(H(0))
circuit.add(CNOT(0, 1))
backend = CudaqBackend(sampling_method=CudaqSamplingMethod.STATE_VECTOR)
result = backend.execute(DigitalPropagation(circuit), Readout().with_sampling(nshots=500))
print(result.get_samples())
Functional support
Functional |
Support |
Notes |
|---|---|---|
✅ |
Native CUDA-Q kernel. Sampling method selected via |
|
✅ |
Driven by |
|
🟡 |
The CudaqBackend does not natively implement |
|
✅ |
Reuses the digital/analog handlers above for each optimization step. |
Configuration
The CUDA backend exposes a single configuration parameter —
CudaqSamplingMethod — that selects the underlying CUDA-Q
target used for digital circuits. If no method is specified, STATE_VECTOR is used.
Analog evolution always runs on the dynamics target and ignores this setting.
Method |
CUDA-Q target |
Supports Sampling |
Supports Expectation Values |
Supports State Tomography |
|---|---|---|---|---|
|
✅ |
✅ |
✅ |
|
|
✅ |
✅ |
✅ |
|
|
✅ |
❌ |
❌ |
|
|
✅ |
❌ |
❌ |
|
|
✅ |
✅ |
✅ |
Set the method at construction time:
from qilisdk.backends import CudaqBackend, CudaqSamplingMethod
backend = CudaqBackend(sampling_method=CudaqSamplingMethod.MATRIX_PRODUCT_STATE)
Some CUDA simulation methods support parameters being set via environment variables, notably the MATRIX_PRODUCT_STATE and TENSOR_NETWORK methods. See the CUDA-Q documentation for details.
To set the precision of the simulation, use the Settings object:
from qilisdk.settings import get_settings, Precision
settings = get_settings()
settings.complex_precision = Precision.COMPLEX_64 # or COMPLEX_32
Noise model support
A NoiseModel can be passed to CudaqBackend(noise_model=…):
For
DigitalPropagation, qilisdk noise channels are translated into acudaq.NoiseModel(Kraus channels for static / time-derived noise, parameter perturbations applied to the circuit). With noise enabled, only a singleSamplingReadoutis supported.For
AnalogEvolution, Lindblad-compatible noise channels become CUDA-Q jump operators and Hamiltonian deltas fed tocudaq.evolve.For
QuantumReservoir, the fallback implementation drops the noise model (a warning is logged).
Example: a depolarising channel applied to every gate of a digital circuit:
from qilisdk.backends import CudaqBackend, CudaqSamplingMethod
from qilisdk.noise import NoiseModel, Depolarizing
nm = NoiseModel()
nm.add(Depolarizing(probability=1e-3))
backend = CudaqBackend(
sampling_method=CudaqSamplingMethod.STATE_VECTOR,
noise_model=nm,
)