Skip to content

Commit 44909e2

Browse files
committed
added calcAmpSum backend
1 parent a6ac16b commit 44909e2

File tree

10 files changed

+142
-3
lines changed

10 files changed

+142
-3
lines changed

quest/src/api/calculations.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,10 @@ qreal calcRealAmpSum(Qureg qureg) {
134134
validate_quregFields(qureg, __func__);
135135
validate_quregHasEvenNumQubits(qureg, __func__);
136136

137-
/// @todo
138-
/// implement and call new backend function
139-
return -1;
137+
// logic is identical for both statevectors and density matrices
138+
qcomp value = localiser_statevec_calcAmpSum(qureg);
139+
140+
return std::real(value);
140141
}
141142

142143

quest/src/core/accelerator.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,20 @@ using std::min;
182182

183183

184184

185+
/*
186+
* PR DEMOS
187+
*/
188+
189+
190+
qcomp accel_statevec_calcAmpSum(Qureg qureg) {
191+
192+
return (qureg.isGpuAccelerated)?
193+
gpu_statevec_calcAmpSum(qureg):
194+
cpu_statevec_calcAmpSum(qureg);
195+
}
196+
197+
198+
185199
/*
186200
* GETTERS
187201
*/

quest/src/core/accelerator.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,13 @@ using std::vector;
147147
name = compileval;
148148

149149

150+
/*
151+
* PR DEMOS
152+
*/
153+
154+
qcomp accel_statevec_calcAmpSum(Qureg qureg);
155+
156+
150157
/*
151158
* GETTERS
152159
*/

quest/src/core/localiser.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,27 @@ void exchangeAmpsToBuffersWhereQubitsAreInStates(Qureg qureg, int pairRank, vect
461461

462462

463463

464+
/*
465+
* PR DEMOS
466+
*/
467+
468+
469+
qcomp localiser_statevec_calcAmpSum(Qureg qureg) {
470+
471+
// each node computes the sum of its local amps
472+
// in an embarrassingly parallel fashion
473+
qcomp out = accel_statevec_calcAmpSum(qureg);
474+
475+
// node partial sums are combined, and every
476+
// node receives a copy of the full sum (consensus)
477+
if (qureg.isDistributed)
478+
comm_reduceAmp(&out);
479+
480+
return out;
481+
}
482+
483+
484+
464485
/*
465486
* GETTERS
466487
*/

quest/src/core/localiser.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
using std::vector;
2424

2525

26+
/*
27+
* PR DEMOS
28+
*/
29+
30+
qcomp localiser_statevec_calcAmpSum(Qureg qureg);
31+
32+
2633
/*
2734
* GETTERS
2835
*/

quest/src/cpu/cpu_subroutines.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,34 @@ using std::vector;
4040

4141

4242

43+
/*
44+
* PR DEMOS
45+
*/
46+
47+
48+
qcomp cpu_statevec_calcAmpSum(Qureg qureg) {
49+
50+
// we brazenly perform this all-state reduction without
51+
// a single thought to finite precision effects - arrest me!
52+
53+
// separately reduce real and imag components to make MSVC happy
54+
qreal outRe = 0;
55+
qreal outIm = 0;
56+
57+
// every local amplitude contributes to the sum
58+
qindex numIts = qureg.numAmpsPerNode;
59+
60+
#pragma omp parallel for reduction(+:outRe,outIm) if(qureg.isMultithreaded)
61+
for (qindex n=0; n<numIts; n++) {
62+
outRe += std::real(qureg.cpuAmps[n]);
63+
outIm += std::imag(qureg.cpuAmps[n]);
64+
}
65+
66+
return qcomp(outRe, outIm);
67+
}
68+
69+
70+
4371
/*
4472
* GETTERS
4573
*/

quest/src/cpu/cpu_subroutines.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
using std::vector;
2121

2222

23+
/*
24+
* PR DEMOS
25+
*/
26+
27+
qcomp cpu_statevec_calcAmpSum(Qureg qureg);
28+
29+
2330
/*
2431
* GETTERS
2532
*/

quest/src/gpu/gpu_subroutines.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,32 @@ using std::vector;
6565

6666

6767

68+
/*
69+
* PR DEMOS
70+
*/
71+
72+
73+
qcomp gpu_statevec_calcAmpSum(Qureg qureg) {
74+
75+
#if COMPILE_CUDA || COMPILE_CUQUANTUM
76+
77+
// there is no cuQuantum function for this facility,
78+
// nor is there a need to implement a custom kernel;
79+
// we will leverage an exting Thrust facility
80+
cu_qcomp out = thrust_statevec_calcAmpSum(qureg);
81+
82+
// the GPU backend uses a CUDA-equivalent of 'qcomp'
83+
// which we must cast back and forth between (ew!)
84+
return toQcomp(out);
85+
86+
#else
87+
error_gpuSimButGpuNotCompiled();
88+
return -1;
89+
#endif
90+
}
91+
92+
93+
6894
/*
6995
* GETTERS
7096
*/

quest/src/gpu/gpu_subroutines.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
using std::vector;
1818

1919

20+
/*
21+
* PR DEMOS
22+
*/
23+
24+
qcomp gpu_statevec_calcAmpSum(Qureg qureg);
25+
26+
2027
/*
2128
* GETTERS
2229
*/

quest/src/gpu/gpu_thrust.cuh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,27 @@ struct functor_setRandomStateVecAmp : public thrust::unary_function<qindex,cu_qc
635635

636636

637637

638+
/*
639+
* PR DEMOS
640+
*/
641+
642+
643+
cu_qcomp thrust_statevec_calcAmpSum(Qureg qureg) {
644+
645+
// beware that we must explicitly instantiate a
646+
// qcomp type here, rather than pass reduce() a
647+
// literal, which would cause a silent bug (grr)
648+
cu_qcomp init = getCuQcomp(0, 0);
649+
650+
cu_qcomp out = thrust::reduce(
651+
getStartPtr(qureg), getEndPtr(qureg),
652+
init, thrust::plus<cu_qcomp>());
653+
654+
return out;
655+
}
656+
657+
658+
638659
/*
639660
* MATRIX INITIALISATION
640661
*/

0 commit comments

Comments
 (0)