From 7bdbf5a2cc4f1bcd2fa1b17e43c49eed991719d5 Mon Sep 17 00:00:00 2001 From: Daniel Strano Date: Sun, 6 Sep 2020 11:01:35 -0400 Subject: [PATCH] Make QHybrid default engine type (#462) * Make QHybrid default engine type * Debug default threshold * Debug default threshold * Debug default threshold * Debug default threshold * Debug default threshold * Debug default threshold --- README.md | 2 +- include/qfactory.hpp | 6 ++++-- include/qhybrid.hpp | 7 ++++++- include/qinterface.hpp | 2 +- include/qunitmulti.hpp | 10 +--------- src/qhybrid.cpp | 6 ++++-- src/qunitmulti.cpp | 10 +++++----- 7 files changed, 22 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index f775f49c2..6b0e8fd2f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Qrack -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3785646.svg)](https://zenodo.org/badge/latestdoi/114947047) [![Qrack Build Status](https://api.travis-ci.org/vm6502q/qrack.svg?branch=master)](https://travis-ci.org/vm6502q/qrack/builds) [![Mentioned in Awesome awesome-quantum-computing](https://awesome.re/mentioned-badge.svg)](https://github.com/desireevl/awesome-quantum-computing) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3842287.svg)](https://doi.org/10.5281/zenodo.3842287) [![Qrack Build Status](https://api.travis-ci.org/vm6502q/qrack.svg?branch=master)](https://travis-ci.org/vm6502q/qrack/builds) [![Mentioned in Awesome awesome-quantum-computing](https://awesome.re/mentioned-badge.svg)](https://github.com/desireevl/awesome-quantum-computing) [![Unitary Fund](https://img.shields.io/badge/Supported%20By-UNITARY%20FUND-brightgreen.svg?style=for-the-badge)](http://unitary.fund) diff --git a/include/qfactory.hpp b/include/qfactory.hpp index 6b9ff9f28..4262448bb 100644 --- a/include/qfactory.hpp +++ b/include/qfactory.hpp @@ -45,7 +45,7 @@ QInterfacePtr CreateQuantumInterface( case QINTERFACE_HYBRID: return std::make_shared(args...); case QINTERFACE_QUNIT_MULTI: - return std::make_shared(subengine1, args...); + return std::make_shared(args...); #endif default: return NULL; @@ -70,7 +70,7 @@ QInterfacePtr CreateQuantumInterface(QInterfaceEngine engine, QInterfaceEngine s case QINTERFACE_HYBRID: return std::make_shared(args...); case QINTERFACE_QUNIT_MULTI: - return std::make_shared(subengine, args...); + return std::make_shared(args...); #endif default: return NULL; @@ -87,6 +87,8 @@ template QInterfacePtr CreateQuantumInterface(QInterfaceEngine return std::make_shared(args...); case QINTERFACE_HYBRID: return std::make_shared(args...); + case QINTERFACE_QUNIT_MULTI: + return std::make_shared(args...); #endif default: return NULL; diff --git a/include/qhybrid.hpp b/include/qhybrid.hpp index ef1068209..13f83663b 100644 --- a/include/qhybrid.hpp +++ b/include/qhybrid.hpp @@ -39,7 +39,7 @@ class QHybrid : public QInterface { QHybrid(bitLenInt qBitCount, bitCapInt initState = 0, qrack_rand_gen_ptr rgp = nullptr, complex phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = true, bool randomGlobalPhase = true, bool useHostMem = false, int deviceId = -1, bool useHardwareRNG = true, bool useSparseStateVec = false, - real1 norm_thresh = REAL1_DEFAULT_ARG, std::vector ignored = {}, bitLenInt qubitThreshold = 13); + real1 norm_thresh = REAL1_DEFAULT_ARG, std::vector ignored = {}, bitLenInt qubitThreshold = 0); QEnginePtr MakeEngine(bool isOpenCL, bitCapInt initState = 0); @@ -51,6 +51,11 @@ class QHybrid : public QInterface { engine->SetConcurrency(concurrency); } + /** + * Switches between CPU and GPU used modes. (This will not incur a performance penalty, if the chosen mode matches + * the current mode.) Mode switching happens automatically when qubit counts change, but Compose() and Decompose() + * might leave their destination QInterface parameters in the opposite mode. + */ virtual void SwitchModes(bool useGpu) { if (!isGpu && useGpu) { diff --git a/include/qinterface.hpp b/include/qinterface.hpp index 0bfd85a5d..0efa4f46f 100644 --- a/include/qinterface.hpp +++ b/include/qinterface.hpp @@ -118,7 +118,7 @@ enum QInterfaceEngine { QINTERFACE_FIRST = QINTERFACE_CPU, #if ENABLE_OPENCL - QINTERFACE_OPTIMAL = QINTERFACE_OPENCL, + QINTERFACE_OPTIMAL = QINTERFACE_HYBRID, #else QINTERFACE_OPTIMAL = QINTERFACE_CPU, #endif diff --git a/include/qunitmulti.hpp b/include/qunitmulti.hpp index 2ac83ba90..0083a1094 100644 --- a/include/qunitmulti.hpp +++ b/include/qunitmulti.hpp @@ -68,15 +68,7 @@ class QUnitMulti : public QUnit, public ParallelFor { std::vector deviceList; public: - QUnitMulti(bitLenInt qBitCount, bitCapInt initState, qrack_rand_gen_ptr rgp, complex phaseFac, bool doNorm, - bool randomGlobalPhase, bool useHostMem, int deviceID, bool useHardwareRNG, bool useSparseStateVec, - real1 norm_thresh, std::vector devList, bitLenInt qubitThreshold) - : QUnitMulti(QINTERFACE_OPENCL, qBitCount, initState, rgp, phaseFac, doNorm, randomGlobalPhase, useHostMem, -1, - useHardwareRNG, qubitThreshold) - { - } - - QUnitMulti(QInterfaceEngine eng, bitLenInt qBitCount, bitCapInt initState = 0, qrack_rand_gen_ptr rgp = nullptr, + QUnitMulti(bitLenInt qBitCount, bitCapInt initState = 0, qrack_rand_gen_ptr rgp = nullptr, complex phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = true, bool randomGlobalPhase = true, bool useHostMem = false, int deviceID = -1, bool useHardwareRNG = true, bool useSparseStateVec = false, real1 norm_thresh = REAL1_DEFAULT_ARG, std::vector devList = {}, bitLenInt qubitThreshold = 0); diff --git a/src/qhybrid.cpp b/src/qhybrid.cpp index f09faa45b..03a03d0fb 100644 --- a/src/qhybrid.cpp +++ b/src/qhybrid.cpp @@ -25,10 +25,12 @@ QHybrid::QHybrid(bitLenInt qBitCount, bitCapInt initState, qrack_rand_gen_ptr rg , useHostRam(useHostMem) , useRDRAND(useHardwareRNG) , isSparse(useSparseStateVec) - , isGpu(qubitCount >= qubitThreshold) { concurrency = std::thread::hardware_concurrency(); - thresholdQubits = qubitThreshold ? qubitThreshold : log2(concurrency) + QBCAPPOW; + thresholdQubits = (qubitThreshold != 0) + ? qubitThreshold + : (concurrency == 1 ? PSTRIDEPOW : (log2(concurrency - 1) + PSTRIDEPOW + 1)); + isGpu = (qubitCount >= thresholdQubits); engine = MakeEngine(qubitCount >= thresholdQubits, initState); } diff --git a/src/qunitmulti.cpp b/src/qunitmulti.cpp index 582fd7d93..855a6221f 100644 --- a/src/qunitmulti.cpp +++ b/src/qunitmulti.cpp @@ -17,10 +17,10 @@ namespace Qrack { -QUnitMulti::QUnitMulti(QInterfaceEngine eng, bitLenInt qBitCount, bitCapInt initState, qrack_rand_gen_ptr rgp, - complex phaseFac, bool doNorm, bool randomGlobalPhase, bool useHostMem, int deviceID, bool useHardwareRNG, - bool useSparseStateVec, real1 norm_thresh, std::vector devList, bitLenInt qubitThreshold) - : QUnit(eng, QINTERFACE_OPENCL, qBitCount, initState, rgp, phaseFac, doNorm, randomGlobalPhase, useHostMem, -1, +QUnitMulti::QUnitMulti(bitLenInt qBitCount, bitCapInt initState, qrack_rand_gen_ptr rgp, complex phaseFac, bool doNorm, + bool randomGlobalPhase, bool useHostMem, int deviceID, bool useHardwareRNG, bool useSparseStateVec, + real1 norm_thresh, std::vector devList, bitLenInt qubitThreshold) + : QUnit(QINTERFACE_OPENCL, qBitCount, initState, rgp, phaseFac, doNorm, randomGlobalPhase, useHostMem, -1, useHardwareRNG, useSparseStateVec, norm_thresh, devList, qubitThreshold) { // Notice that this constructor always passes QINTERFACE_OPENCL to the QUnit constructor. For QUnitMulti, the @@ -199,7 +199,7 @@ QInterfacePtr QUnitMulti::Clone() EndAllEmulation(); QUnitMultiPtr copyPtr = std::make_shared( - engine, qubitCount, 0, rand_generator, complex(ONE_R1, ZERO_R1), doNormalize, randGlobalPhase, useHostRam); + qubitCount, 0, rand_generator, complex(ONE_R1, ZERO_R1), doNormalize, randGlobalPhase, useHostRam); return CloneBody(copyPtr); }