qsengine 1.1.1

CPU and GPU backends

Every method that runs a circuit takes a backend argument. You rarely need it: the default, "auto", picks the faster backend for the circuit’s size and falls back to the CPU when there is no GPU.

qc.run(shots=1000)                 # auto
qc.run(shots=1000, backend="cpu")  # always the CPU
qc.run(shots=1000, backend="gpu")  # the GPU, or RuntimeError

The three choices compared

PropertyCPUGPUauto
How you ask for itbackend="cpu"backend="gpu"backend="auto" (the default)
Precision64-bit floats32-bit floats, within about 1e-5 of the CPU for a few hundred gates64-bit below 14 qubits, 32-bit from 14
Runs onEvery CPU core, through RayonAny NVIDIA, AMD, Intel or Apple GPU, through wgpuWhichever is faster for the size
Fastest forFewer than 14 qubits14 qubits and moreBoth, by switching at 14
Largest register30 qubits (16 GiB)What the GPU memory holdsThat of the backend it picks
With no GPUWorks as usualRaises RuntimeErrorFalls back to the CPU

Why auto switches at 14 qubits

Launching work on a GPU and reading the result back costs about a millisecond, whatever the circuit. Below 14 qubits the CPU finishes before that. From 14 qubits up the GPU is faster, and the gap grows with every qubit: at 22 qubits it is about 15 times faster than the CPU backend. The crossover was measured on one desktop (Ryzen 5 5500 and Radeon RX 6600) and may sit a qubit higher or lower on yours.

Circuits that measure part-way switch later, at 20 qubits. Each mid-circuit measurement waits for one number to come back from the GPU, about a millisecond, and every shot is simulated on its own, so those waits add up. Below 20 qubits the CPU finishes a whole shot first.

Precision

The CPU computes in 64-bit floats. GPUs generally lack fast 64-bit arithmetic, so the GPU backend uses 32-bit floats. On the circuits in the test suite (up to 18 qubits and a few hundred gates) it agrees with the CPU to about 1e-5. Rounding error grows with the number of gates, so deep circuits drift further. Counts from run() are unaffected in practice; pass backend="cpu" when you compare amplitudes to many decimal places.

Because "auto" switches at 14 qubits, statevector(), probabilities() and expectation() give 64-bit results below 14 qubits and 32-bit results from 14 on a machine with a GPU. If you compare results across register sizes, pass backend="cpu" so every size has the same precision.

On the GPU, each mid-circuit measurement renormalises the state using a 32-bit sum. The error is small but adds up over many measurements in one shot, such as repeated syndrome rounds. Use backend="cpu" for those circuits when precision matters.

Supported GPUs

qsengine reaches the GPU through wgpu, which speaks Vulkan, DirectX 12 and Metal. Recent NVIDIA, AMD, Intel and Apple GPUs all work with their normal drivers, and there is no CUDA or vendor toolkit to install.