Qrack  1.7
General classical-emulating-quantum development framework
qengine_opencl.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017, 2018. All rights reserved.
4 //
5 // This is a multithreaded, universal quantum register simulation, allowing
6 // (nonphysical) register cloning and direct measurement of probability and
7 // phase, to leverage what advantages classical emulation of qubits can have.
8 //
9 // Licensed under the GNU General Public License V3.
10 // See LICENSE.md in the project root or https://www.gnu.org/licenses/gpl-3.0.en.html
11 // for details.
12 
13 #pragma once
14 
15 #if !ENABLE_OPENCL
16 #error OpenCL has not been enabled
17 #endif
18 
19 #include "qengine_cpu.hpp"
20 
21 namespace Qrack {
22 
23 typedef std::shared_ptr<cl::Buffer> BufferPtr;
24 
25 class OCLEngine;
26 
27 class QEngineOCL;
28 
29 typedef std::shared_ptr<QEngineOCL> QEngineOCLPtr;
30 
32 class QEngineOCL : public QEngineCPU {
33 protected:
34  int deviceID;
36  cl::CommandQueue queue;
37  cl::Context context;
38  // stateBuffer is allocated as a shared_ptr, because it's the only buffer that will be acted on outside of
39  // QEngineOCL itself, specifically by QEngineOCLMulti.
40  BufferPtr stateBuffer;
41  cl::Buffer cmplxBuffer;
42  cl::Buffer ulongBuffer;
43  cl::Buffer nrmBuffer;
44  cl::Buffer maxBuffer;
45 
46 public:
58  QEngineOCL(bitLenInt qBitCount, bitCapInt initState, std::shared_ptr<std::default_random_engine> rgp = nullptr,
59  int devID = -1, bool partialInit = false)
60  : QEngineCPU(qBitCount, initState, rgp, complex(-999.0, -999.0), partialInit)
61  {
62  InitOCL(devID);
63  }
64 
65  QEngineOCL(QEngineOCLPtr toCopy)
66  : QEngineCPU(toCopy)
67  {
68  InitOCL(toCopy->deviceID);
69  }
70 
71  virtual void SetQubitCount(bitLenInt qb)
72  {
73  qubitCount = qb;
74  maxQPower = 1 << qubitCount;
75  }
76 
77  virtual complex* GetStateVector() { return stateVec; }
78 
79  /* Operations that have an improved implementation. */
80  virtual void Swap(bitLenInt qubit1, bitLenInt qubit2); // Inherited overload
81  virtual void Swap(bitLenInt start1, bitLenInt start2, bitLenInt length);
82  using QEngineCPU::Cohere;
83  virtual bitLenInt Cohere(QEngineOCLPtr toCopy);
84  virtual bitLenInt Cohere(QInterfacePtr toCopy) { return Cohere(std::dynamic_pointer_cast<QEngineOCL>(toCopy)); }
86  virtual void Decohere(bitLenInt start, bitLenInt length, QInterfacePtr dest);
87  virtual void Dispose(bitLenInt start, bitLenInt length);
88  using QEngineCPU::X;
89  virtual void X(bitLenInt start, bitLenInt length);
90  virtual void ROL(bitLenInt shift, bitLenInt start, bitLenInt length);
91  virtual void ROR(bitLenInt shift, bitLenInt start, bitLenInt length);
92  virtual void INC(bitCapInt toAdd, bitLenInt start, bitLenInt length);
93  virtual void DEC(bitCapInt toSub, bitLenInt start, bitLenInt length);
94  virtual void INCC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
95  virtual void DECC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
96  virtual bitCapInt IndexedLDA(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart,
97  bitLenInt valueLength, unsigned char* values);
98  virtual bitCapInt IndexedADC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart,
99  bitLenInt valueLength, bitLenInt carryIndex, unsigned char* values);
100  virtual bitCapInt IndexedSBC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart,
101  bitLenInt valueLength, bitLenInt carryIndex, unsigned char* values);
102 
103  virtual real1 Prob(bitLenInt qubit);
104 
105  virtual int GetDeviceID() { return deviceID; }
106  virtual void SetDevice(const int& dID);
107 
108  virtual void NormalizeState(real1 nrm = -999.0);
109  virtual void UpdateRunningNorm();
110 
111 protected:
112  static const int BCI_ARG_LEN = 10;
113 
114  void InitOCL(int devID);
115  void ReInitOCL();
116  void ResetStateVec(complex* nStateVec);
117 
118  void DecohereDispose(bitLenInt start, bitLenInt length, QEngineOCLPtr dest);
119  void DispatchCall(OCLAPI api_call, bitCapInt (&bciArgs)[BCI_ARG_LEN], complex* nVec = NULL,
120  unsigned char* values = NULL, bitCapInt valuesLength = 0);
121 
122  void Apply2x2(bitCapInt offset1, bitCapInt offset2, const complex* mtrx, const bitLenInt bitCount,
123  const bitCapInt* qPowersSorted, bool doCalcNorm);
124 
125  /* Utility functions used by the operations above. */
126  void ROx(OCLAPI api_call, bitLenInt shift, bitLenInt start, bitLenInt length);
127  void INT(OCLAPI api_call, bitCapInt toAdd, const bitLenInt inOutStart, const bitLenInt length);
128  void INTC(OCLAPI api_call, bitCapInt toAdd, const bitLenInt inOutStart, const bitLenInt length,
129  const bitLenInt carryIndex);
130 
131  bitCapInt OpIndexed(OCLAPI api_call, bitCapInt carryIn, bitLenInt indexStart, bitLenInt indexLength,
132  bitLenInt valueStart, bitLenInt valueLength, bitLenInt carryIndex, unsigned char* values);
133 };
134 
135 } // namespace Qrack
cl::Buffer ulongBuffer
Definition: qengine_opencl.hpp:42
cl::Buffer nrmBuffer
Definition: qengine_opencl.hpp:43
virtual void UpdateRunningNorm()
Definition: opencl.cpp:639
virtual bitCapInt IndexedLDA(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, unsigned char *values)
Set 8 bit register bits based on read from classical memory.
Definition: opencl.cpp:497
virtual void Swap(bitLenInt qubit1, bitLenInt qubit2)
Swap values of two bits in register.
Definition: opencl.cpp:399
OCLAPI
Definition: oclengine.hpp:38
virtual void X(bitLenInt start, bitLenInt length)
Bitwise Pauli X (or logical "NOT") operator.
Definition: opencl.cpp:385
virtual bitCapInt IndexedADC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, bitLenInt carryIndex, unsigned char *values)
Add based on an indexed load from classical memory.
Definition: opencl.cpp:586
virtual void ROL(bitLenInt shift, bitLenInt start, bitLenInt length)
"Circular shift left" - shift bits left, and carry last bits.
Definition: opencl.cpp:428
virtual void Decohere(bitLenInt start, bitLenInt length, QInterfacePtr dest)
Minimally decohere a set of contiguous bits from the full coherent unit, into "destination.".
Definition: state.cpp:387
void Apply2x2(bitCapInt offset1, bitCapInt offset2, const complex *mtrx, const bitLenInt bitCount, const bitCapInt *qPowersSorted, bool doCalcNorm)
Apply a 2x2 matrix to the state vector.
Definition: opencl.cpp:96
static const int BCI_ARG_LEN
Definition: qengine_opencl.hpp:112
std::shared_ptr< OCLDeviceContext > DeviceContextPtr
Definition: oclengine.hpp:34
virtual real1 Prob(bitLenInt qubit)
PSEUDO-QUANTUM Direct measure of bit probability to be in |1> state.
Definition: opencl.cpp:335
virtual void SetDevice(const int &dID)
Definition: opencl.cpp:22
bitCapInt maxQPower
Definition: qinterface.hpp:97
#define real1
Definition: qinterface.hpp:35
BufferPtr stateBuffer
Definition: qengine_opencl.hpp:40
virtual void Decohere(bitLenInt start, bitLenInt length, QInterfacePtr dest)
Minimally decohere a set of contiguous bits from the full coherent unit, into "destination.".
Definition: opencl.cpp:327
void ReInitOCL()
Definition: opencl.cpp:44
void InitOCL(int devID)
Definition: opencl.cpp:42
cl::CommandQueue queue
Definition: qengine_opencl.hpp:36
void ResetStateVec(complex *nStateVec)
Definition: opencl.cpp:53
virtual bitLenInt Cohere(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qengine_cpu.hpp:54
void ROx(OCLAPI api_call, bitLenInt shift, bitLenInt start, bitLenInt length)
Definition: opencl.cpp:417
#define complex
Definition: qinterface.hpp:34
bitCapInt OpIndexed(OCLAPI api_call, bitCapInt carryIn, bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, bitLenInt carryIndex, unsigned char *values)
Add or Subtract based on an indexed load from classical memory.
Definition: opencl.cpp:534
virtual void DEC(bitCapInt toSub, bitLenInt start, bitLenInt length)
Subtract integer (without sign, with carry)
Definition: opencl.cpp:452
OpenCL enhanced QEngineCPU implementation.
Definition: qengine_opencl.hpp:32
virtual void DECC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract integer (without sign, with carry)
Definition: opencl.cpp:484
#define bitCapInt
Definition: qinterface.hpp:22
void DecohereDispose(bitLenInt start, bitLenInt length, QEngineOCLPtr dest)
Definition: opencl.cpp:199
DeviceContextPtr device_context
Definition: qengine_opencl.hpp:35
void INTC(OCLAPI api_call, bitCapInt toAdd, const bitLenInt inOutStart, const bitLenInt length, const bitLenInt carryIndex)
Add or Subtract integer (without sign, with carry)
Definition: opencl.cpp:458
#define bitLenInt
Definition: qinterface.hpp:21
virtual void SetQubitCount(bitLenInt qb)
Definition: qengine_opencl.hpp:71
void DispatchCall(OCLAPI api_call, bitCapInt(&bciArgs)[BCI_ARG_LEN], complex *nVec=NULL, unsigned char *values=NULL, bitCapInt valuesLength=0)
Definition: opencl.cpp:60
"Qrack::OCLEngine" manages the single OpenCL context.
Definition: oclengine.hpp:110
virtual complex * GetStateVector()
Definition: qengine_opencl.hpp:77
int deviceID
Definition: qengine_opencl.hpp:34
General purpose QEngineCPU implementation.
Definition: qengine_cpu.hpp:37
virtual void Dispose(bitLenInt start, bitLenInt length)
Minimally decohere a set of contigious bits from the full coherent unit, throwing these qubits away...
Definition: opencl.cpp:332
QEngineOCL(QEngineOCLPtr toCopy)
Definition: qengine_opencl.hpp:65
virtual void INCC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Increment integer (without sign, with carry)
Definition: opencl.cpp:472
virtual void X(bitLenInt qubitIndex)
NOT gate, which is also Pauli x matrix.
Definition: gates.cpp:114
bitLenInt qubitCount
Definition: qinterface.hpp:96
QEngineOCL(bitLenInt qBitCount, bitCapInt initState, std::shared_ptr< std::default_random_engine > rgp=nullptr, int devID=-1, bool partialInit=false)
Initialize a Qrack::QEngineOCL object.
Definition: qengine_opencl.hpp:58
std::shared_ptr< QEngineOCL > QEngineOCLPtr
Definition: qengine_opencl.hpp:27
void INT(OCLAPI api_call, bitCapInt toAdd, const bitLenInt inOutStart, const bitLenInt length)
Add or Subtract integer (without sign or carry)
Definition: opencl.cpp:434
virtual bitLenInt Cohere(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qengine_opencl.hpp:84
cl::Context context
Definition: qengine_opencl.hpp:37
std::shared_ptr< QInterface > QInterfacePtr
Definition: qinterface.hpp:41
std::shared_ptr< cl::Buffer > BufferPtr
Definition: qengine_opencl.hpp:23
virtual int GetDeviceID()
Definition: qengine_opencl.hpp:105
Definition: complex16simd.hpp:21
virtual void ROR(bitLenInt shift, bitLenInt start, bitLenInt length)
"Circular shift right" - shift bits right, and carry first bits.
Definition: opencl.cpp:431
cl::Buffer maxBuffer
Definition: qengine_opencl.hpp:44
virtual void NormalizeState(real1 nrm=-999.0)
Definition: opencl.cpp:599
complex * stateVec
Definition: qengine_cpu.hpp:41
cl::Buffer cmplxBuffer
Definition: qengine_opencl.hpp:41
virtual bitLenInt Cohere(QEngineOCLPtr toCopy)
Definition: opencl.cpp:152
virtual void INC(bitCapInt toAdd, bitLenInt start, bitLenInt length)
Increment integer (without sign, with carry)
Definition: opencl.cpp:446
virtual bitCapInt IndexedSBC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, bitLenInt carryIndex, unsigned char *values)
Subtract based on an indexed load from classical memory.
Definition: opencl.cpp:593