Skip to content

Commit

Permalink
Move code all over the place.
Browse files Browse the repository at this point in the history
  • Loading branch information
Benn Bollay committed Feb 28, 2018
1 parent 76bcf0a commit c7ddaa0
Show file tree
Hide file tree
Showing 14 changed files with 488 additions and 3,165 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/doc/*
*.o
qrackcl.hpp
qregistercl.hpp
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ Direct measurement of qubit probability and phase are implemented for debugging,

Qrack compiles like a library. To include in your project:

1)In your source code:
#include "qrack.hpp"
2)On the command line, in the project directory
make all
1. In your source code:
```
#include "qregister.hpp"
```

Make will link against math, pthreads, and OpenCL. Modify the makefile as necessary for inclusion in your project. Set the makefile QRACKVER variable to "qrack_ocl.cpp" for the OpenCL version, "qrack.cpp" for CPU parallelism only (without OpenCL), or "qrack_serial.cpp" for a totally non-parallel version. If you aren't using the OpenCL version, you should remove OpenCL linkage from the makefile.
2. On the command line, in the project directory
```
make all
```

Instantiate a Qrack::CoherentUnit, specifying the desired number of qubits. (Optionally, also specify the initial bit state in the constructor.) Coherent units can be "cohered" and "decohered" with each other, to simulate coherence and loss of coherence between distinct quantum bit registers. Both single quantum gate commands and register-like multi-bit commands are available.

Expand Down
9 changes: 8 additions & 1 deletion example.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
#include "qrack.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

#include "qregister.hpp"

using namespace Qrack;

#if ENABLE_OPENCL
#include "qregister_opencl.hpp"

#define CoherentUnit CoherentUnitOCL
#endif

int main()
{

Expand Down
16 changes: 8 additions & 8 deletions makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# 1 to use OpenCL-based optimizations
ENABLE_OPENCL ?= 0
ENABLE_OPENCL ?= 1

CPP = g++
XXD = xxd
OBJ = complex16simd.o example.o qrack_base.o par_for.o
OBJ = complex16simd.o example.o qregister.o par_for.o
BIN = example
LIBS = -lm -lpthread
INCS =
Expand All @@ -14,25 +14,25 @@ RM = rm -f
ifeq (${ENABLE_OPENCL},1)
LIBS += -lOpenCL
CXXFLAGS += -DENABLE_OPENCL=1
OBJ += qrack_ocl.o qrack.o
OBJ += qregister_opencl.o oclengine.o
else
CXXFLAGS += -DENABLE_OPENCL=0
OBJ += qrack.o
OBJ += qregister_software.o
endif

.PHONY: all all-before all-after clean clean-custom

all: all-before $(BIN) all-after

clean: clean-custom
$(RM) $(OBJ) qrackcl.hpp
$(RM) $(OBJ) qregistercl.hpp

$(BIN): $(OBJ)
$(CPP) $(OBJ) -o $(BIN) $(LIBS)

ifeq (${ENABLE_OPENCL},1)
qrackcl.hpp: qrack.cl
${XXD} -i qrack.cl > qrackcl.hpp
qregistercl.hpp: qregister.cl
${XXD} -i qregister.cl > qregistercl.hpp

qrack_ocl.o: qrackcl.hpp
qregister_opencl.o: qregistercl.hpp
endif
107 changes: 107 additions & 0 deletions oclengine.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//////////////////////////////////////////////////////////////////////////////////////
//
// (C) Daniel Strano 2017. All rights reserved.
//
// This is a header-only, quick-and-dirty, multithreaded, universal quantum register
// simulation, allowing (nonphysical) register cloning and direct measurement of
// probability and phase, to leverage what advantages classical emulation of qubits
// can have.
//
// Licensed under the GNU General Public License V3.
// See LICENSE.md in the project root or https://www.gnu.org/licenses/gpl-3.0.en.html
// for details.

#include <iostream>

#include "oclengine.hpp"

#include "qregistercl.hpp"

namespace Qrack {

/// "Qrack::OCLEngine" manages the single OpenCL context

// Public singleton methods to get pointers to various methods
cl::Context* OCLEngine::GetContextPtr() { return &context; }
cl::CommandQueue* OCLEngine::GetQueuePtr() { return &queue; }
cl::Kernel* OCLEngine::GetApply2x2Ptr() { return &apply2x2; }
cl::Kernel* OCLEngine::GetROLPtr() { return &rol; }
cl::Kernel* OCLEngine::GetRORPtr() { return &ror; }
cl::Kernel* OCLEngine::GetADDPtr() { return &add; }
cl::Kernel* OCLEngine::GetSUBPtr() { return &sub; }
cl::Kernel* OCLEngine::GetADDCPtr() { return &addc; }
cl::Kernel* OCLEngine::GetSUBCPtr() { return &subc; }

OCLEngine::OCLEngine() { InitOCL(0, 0); }
OCLEngine::OCLEngine(int plat, int dev) { InitOCL(plat, dev); }
OCLEngine::OCLEngine(OCLEngine const&) {}
OCLEngine& OCLEngine::operator=(OCLEngine const& rhs) { return *this; }

void OCLEngine::InitOCL(int plat, int dev)
{
// get all platforms (drivers), e.g. NVIDIA

cl::Platform::get(&all_platforms);

if (all_platforms.size() == 0) {
std::cout << " No platforms found. Check OpenCL installation!\n";
exit(1);
}
default_platform = all_platforms[plat];
std::cout << "Using platform: " << default_platform.getInfo<CL_PLATFORM_NAME>() << "\n";

// get default device (CPUs, GPUs) of the default platform
default_platform.getDevices(CL_DEVICE_TYPE_ALL, &all_devices);
if (all_devices.size() == 0) {
std::cout << " No devices found. Check OpenCL installation!\n";
exit(1);
}

// use device[1] because that's a GPU; device[0] is the CPU
default_device = all_devices[dev];
std::cout << "Using device: " << default_device.getInfo<CL_DEVICE_NAME>() << "\n";

// a context is like a "runtime link" to the device and platform;
// i.e. communication is possible
context = cl::Context({ default_device });

// create the program that we want to execute on the device
cl::Program::Sources sources;

sources.push_back({ (const char*)qregister_cl, (long unsigned int)qregister_cl_len });

program = cl::Program(context, sources);
if (program.build({ default_device }) != CL_SUCCESS) {
std::cout << "Error building: " << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device) << std::endl;
exit(1);
}

queue = cl::CommandQueue(context, default_device);
apply2x2 = cl::Kernel(program, "apply2x2");
rol = cl::Kernel(program, "rol");
ror = cl::Kernel(program, "ror");
add = cl::Kernel(program, "add");
sub = cl::Kernel(program, "sub");
addc = cl::Kernel(program, "addc");
subc = cl::Kernel(program, "subc");
}

OCLEngine* OCLEngine::m_pInstance = NULL;
OCLEngine* OCLEngine::Instance()
{
if (!m_pInstance)
m_pInstance = new OCLEngine();
return m_pInstance;
}

OCLEngine* OCLEngine::Instance(int plat, int dev)
{
if (!m_pInstance) {
m_pInstance = new OCLEngine(plat, dev);
} else {
std::cout << "Warning: Tried to reinitialize OpenCL environment with platform and device." << std::endl;
}
return m_pInstance;
}

} // namespace Qrack
47 changes: 11 additions & 36 deletions qrack_ocl.hpp → oclengine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,13 @@

namespace Qrack {

class OCLSingleton;

class CoherentUnitOCL : public CoherentUnit {
public:
virtual void ROL(bitLenInt shift, bitLenInt start, bitLenInt length);
virtual void ROR(bitLenInt shift, bitLenInt start, bitLenInt length);
virtual void ADD(const bitLenInt inOutStart, const bitLenInt inStart, const bitLenInt length);
virtual void SUB(const bitLenInt inOutStart, const bitLenInt toSub, const bitLenInt length);

protected:
OCLSingleton* clObj;
cl::CommandQueue queue;
cl::Buffer stateBuffer;
cl::Buffer cmplxBuffer;
cl::Buffer ulongBuffer;
cl::Buffer nrmBuffer;
cl::Buffer maxBuffer;

virtual void InitOCL();
virtual void ReInitOCL();
virtual void ResetStateVec(std::unique_ptr<Complex16[]>& nStateVec);

virtual void Apply2x2(bitCapInt offset1, bitCapInt offset2, const Complex16* mtrx, const bitLenInt bitCount,
const bitCapInt* qPowersSorted, bool doApplyNorm, bool doCalcNorm);
};

/** "Qrack::OCLSingleton" manages the single OpenCL context. */
class OCLSingleton {
/** "Qrack::OCLEngine" manages the single OpenCL context. */
class OCLEngine {
public:
/// Get a pointer to the Instance of the singleton. (The instance will be instantiated, if it does not exist yet.)
static OCLSingleton* Instance();
static OCLEngine* Instance();
/// If this is the first time instantiating the OpenCL context, you may specify platform number and device number.
static OCLSingleton* Instance(int plat, int dev);
static OCLEngine* Instance(int plat, int dev);
/// Get a pointer to the OpenCL context
cl::Context* GetContextPtr();
/// Get a pointer to the OpenCL queue
Expand Down Expand Up @@ -105,12 +79,13 @@ class OCLSingleton {
cl::Kernel addbcdc;
cl::Kernel subbcdc;

OCLSingleton(); // Private so that it can not be called
OCLSingleton(int plat, int dev); // Private so that it can not be called
OCLSingleton(OCLSingleton const&); // copy constructor is private
OCLSingleton& operator=(OCLSingleton const& rhs); // assignment operator is private
static OCLSingleton* m_pInstance;
OCLEngine(); // Private so that it can not be called
OCLEngine(int plat, int dev); // Private so that it can not be called
OCLEngine(OCLEngine const&); // copy constructor is private
OCLEngine& operator=(OCLEngine const& rhs); // assignment operator is private
static OCLEngine* m_pInstance;

void InitOCL(int plat, int dev);
};
}

} // namespace Qrack
2 changes: 1 addition & 1 deletion par_for.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "qrack.hpp"
#include "qregister.hpp"
#include <atomic>
#include <future>
#include <thread>
Expand Down
Loading

0 comments on commit c7ddaa0

Please sign in to comment.