| 127 | } |
| 128 | |
| 129 | int getMaxNumQubitsBeforeGlobalMemSizeofOverflow(bool isDensMatr, int numNodes, bool hasBuffer, bool isSuperOp) { |
| 130 | |
| 131 | // this function assumes we must be able to store the total |
| 132 | // CPU memory (in bytes) used by a single data structure, |
| 133 | // aggregate across all nodes, in a single size_t primitive. |
| 134 | // This is a defensively-designed constraint; we do not ever |
| 135 | // actually need to know the full memory, but assuring that |
| 136 | // we could principally store it in a size_t will futureproof |
| 137 | // reporter functions against future overflows etc. Note it |
| 138 | // does not meaningfully restrict the maximum simulatable size |
| 139 | // except on ~8 EiB supercomputers. Looking at you, Jupiter! |
| 140 | |
| 141 | size_t maxSizeof = std::numeric_limits<size_t>::max(); |
| 142 | size_t maxGlobalNumAmps = maxSizeof / sizeof(qcomp); // floors |
| 143 | size_t maxGlobalNumQubits = std::floor(std::log2(maxGlobalNumAmps)); // floors |
| 144 | |
| 145 | // distributing Quregs requires communication buffers, doubling memory, decreasing qubits by 1 |
| 146 | if (hasBuffer && numNodes > 1) |
| 147 | maxGlobalNumQubits -= 1; |
| 148 | |
| 149 | // density matrices have square-more amps, halving the number of qubtis (AFTER buffer subtraction) |
| 150 | if (isDensMatr) |
| 151 | maxGlobalNumQubits /= 2; // floors |
| 152 | |
| 153 | // superoperators are square-bigger than their constituent dense matrices |
| 154 | if (isSuperOp) |
| 155 | maxGlobalNumQubits /= 2; // floors |
| 156 | |
| 157 | /// @todo |
| 158 | /// above sometimes overestimates by one; suggesting N can fit |
| 159 | /// in fact only N-1 can fit without causing overflows. It's |
| 160 | /// a chore to correct this precision-agnostically, and we cannot |
| 161 | /// just try get the total-memory and provoke the overflow because |
| 162 | /// a call to mem_getLocalQuregMemoryRequired() would recurse! As |
| 163 | /// this function is only needed for ridiculously overzealous |
| 164 | /// validation, and does not risk any logical error, we simply |
| 165 | /// subtract one to avoid the overflowing edge-case. The returned |
| 166 | /// max-size remains completely unreachable by users of course! |
| 167 | maxGlobalNumQubits -= 1; |
| 168 | |
| 169 | return maxGlobalNumQubits; |
| 170 | } |
| 171 | |
| 172 | int mem_getMaxNumQuregQubitsBeforeGlobalMemSizeofOverflow(bool isDensityMatrix, int numNodes) { |
| 173 |
no outgoing calls
no test coverage detected