pub unsafe extern "C" fn createDensityQureg(
numQubits: c_int,
env: QuESTEnv,
) -> QuregExpand description
Creates a density matrix Qureg object representing a set of qubits which can enter noisy and mixed states.
Allocates space for a matrix of complex amplitudes, which assuming a single ::qreal floating-point number requires qrealBytes, requires memory \f[ \text{qrealBytes} \times 2 \times 2^{2 \times\text{numQubits}};;\text{(bytes)}, \f] though there are additional memory costs in GPU and distributed modes. Notice this is the memory cost of a state-vector created with createQureg() of twice as many qubits.
The returned ::Qureg begins in the zero state, as produced by initZeroState().
Once created, the following ::Qureg fields are relevant in all backends:
- Qureg.numQubitsRepresented
- Qureg.isDensityMatrix
Behind the scenes, density matrice are stored as state-vectors, flattened column-wise. As such, individual amplitudes should be fetched with getDensityAmp(), in lieu of direct access. \n
::QuESTEnv \p env must be prior created with createQuESTEnv().
§Serial
In serial and local (non-distributed) multithreaded modes, a density matrix \p Qureg costs only the memory above. For example, at double precision (#QuEST_PREC = 2, qrealBytes = 8), the memory costs are: \p numQubits | memory ———–– | ———–– 10 | 16 MiB 12 | 256 MiB 14 | 4 GiB 16 | 64 GiB 18 | 1 TiB 20 | 16 TiB
§GPU
In GPU-accelerated mode, an additional density matrix is created in GPU memory. Therefore both RAM and VRAM must be of sufficient memory to store the state-vector, each of the size indicated in the Serial table above.
Note that many GPUs do not support quad precision ::qreal.
§Distributed
In distributed mode, the density matrix is uniformly partitioned between the N distributed nodes (column-wise).
Only a power-of-2 number of nodes N may be used (e.g. N = 1, 2, 4, 8, …). There must additionally be at least 1 amplitude of a density matrix stored on each node. This means one cannot create a density matrix ::Qureg with fewer than \f$\log_2(\text{N})/2\f$ qubits.
Additional memory is allocated on each node for communication buffers, of size equal to the density matrix partition. Hence the total memory per-node required is: \f[ 2 \times \text{qrealBytes} \times 2 \times 2^{2\times\text{numQubits}}/N ;;\text{(bytes)}, \f]
For example, at double precision (#QuEST_PREC = 2, qrealBytes = 8), the memory costs are:
| \p numQubits | memory per node | ||||
|---|---|---|---|---|---|
| N = 2 | N = 4 | N = 8 | N = 16 | N = 32 | |
| 10 | 16 MiB | 8 MiB | 4 MiB | 2 MiB | 1 MiB |
| 15 | 16 GiB | 8 GiB | 4 GiB | 2 GiB | 1 GiB |
| 20 | 16 TiB | 8 TiB | 4 TiB | 2 TiB | 1 TiB |
@see
- createQureg() to create a state-vector of the equivalent number of qubits, with a square-root memory cost
- createCloneQureg() to create a new qureg of the size and state of an existing qureg.
- destroyQureg() to free the allocated \p Qureg memory.
- reportQuregParams() to print information about a ::Qureg.
@ingroup type @returns an object representing the set of qubits @param[in] numQubits number of qubits in the system @param[in] env object representing the execution environment (local, multinode etc) @throws invalidQuESTInputError()
- if \p numQubits <= 0
- if \p numQubits is so large that the number of amplitudes cannot fit in a long long int type,
- if in distributed mode, there are more nodes than elements in the would-be state-vector @throws exit
- if in GPU mode, but GPU memory cannot be allocated. @author Tyson Jones