| 173 | |
| 174 | |
| 175 | unsigned rand_getThreadSharedRandomSeed(bool distinctPerNode) { |
| 176 | |
| 177 | // (callable by multiple nodes, but NOT by multiple threads!) |
| 178 | |
| 179 | // this function produces a seed which can be subsequently |
| 180 | // used by many threads (each perturbing their seed via their |
| 181 | // thread rank) to generate random amplitudes in parallel. |
| 182 | // The dispatched seed is informed by the mainGenerator, |
| 183 | // such that the user's API seeding determines both all |
| 184 | // measurement outcomes and state amps, whilst retaining |
| 185 | // independence amps for each subsequent random state |
| 186 | |
| 187 | // a single uniform seed suffices to seed local random amp generation |
| 188 | unsigned maxSeed = std::numeric_limits<unsigned>::max(); |
| 189 | std::uniform_int_distribution<unsigned> distrib(0, maxSeed); // ~[0 .. max] |
| 190 | |
| 191 | // if we want the same seed on every node, advance all generators |
| 192 | if (!distinctPerNode) |
| 193 | return distrib(mainGenerator); |
| 194 | |
| 195 | // otherwise, if we wish for distinct per-node seeds (e.g. a |
| 196 | // Qureg is distributed in a distributed environment)... |
| 197 | unsigned mySeed = 0; |
| 198 | int myRank = comm_getRank(); |
| 199 | int numNodes = comm_getNumNodes(); |
| 200 | |
| 201 | // then we must advance all generators #ranks times... |
| 202 | for (int rank=0; rank<numNodes; rank++) { |
| 203 | |
| 204 | unsigned globalSeed = distrib(mainGenerator); |
| 205 | |
| 206 | // but keep a distinct seed per-node |
| 207 | if (rank == myRank) |
| 208 | mySeed = globalSeed; |
| 209 | } |
| 210 | |
| 211 | return mySeed; |
| 212 | } |
| 213 | |
| 214 | |
| 215 | std::mt19937_64 rand_getThreadPrivateGenerator(unsigned sharedSeed, int threadId) { |
no test coverage detected