Loading runtime/qrt/impls/nisq/nisq_qrt.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,71 @@ using namespace cppmicroservices; using namespace xacc; namespace { class NisqQubitAllocator : public AllocEventListener, public QubitAllocator { public: static inline const std::string ANC_BUFFER_NAME = "nisq_temp_buffer"; virtual void onAllocate(qubit *in_qubit) override {} // On deallocate: don't try to deref the qubit since it may have been gone. virtual void onDealloc(qubit *in_qubit) override { // If this qubit was allocated from this pool: if (xacc::container::contains(m_allocatedQubits, in_qubit)) { const auto qIndex = std::find(m_allocatedQubits.begin(), m_allocatedQubits.end(), in_qubit) - m_allocatedQubits.begin(); // Strategy: create a storage copy of the returned qubit: // i.e. with the same index w.r.t. this global anc. buffer // but store it in the pool vector -> will stay alive // until giving out at the next allocate() qubit archive_qubit(ANC_BUFFER_NAME, qIndex, m_buffer.get()); m_allocatedQubits[qIndex] = &archive_qubit; m_qubitPool.emplace_back(archive_qubit); } } virtual qubit allocate() override { if (!m_qubitPool.empty()) { auto recycled_qubit = m_qubitPool.back(); m_qubitPool.pop_back(); return recycled_qubit; } if (!m_buffer) { // This must be the first call. assert(m_allocatedQubits.empty()); m_buffer = xacc::qalloc(1); } // Need to allocate new qubit: // Each new qubit will have an incrementing index. const auto newIdx = m_allocatedQubits.size(); qubit new_qubit(ANC_BUFFER_NAME, newIdx, m_buffer.get()); // Just track that we allocated this qubit m_allocatedQubits.emplace_back(&new_qubit); m_buffer->setSize(m_allocatedQubits.size()); return new_qubit; } static NisqQubitAllocator *getInstance() { if (!g_instance) { g_instance = new NisqQubitAllocator(); } return g_instance; } static NisqQubitAllocator *g_instance; private: std::vector<qubit> m_qubitPool; // Track the list of qubit pointers for those // that was allocated by this Allocator. std::vector<qubit *> m_allocatedQubits; std::shared_ptr<xacc::AcceleratorBuffer> m_buffer; }; NisqQubitAllocator *NisqQubitAllocator::g_instance = nullptr; } // namespace namespace qcor { template <typename T> bool ptr_is_a(std::shared_ptr<Observable> ptr) { Loading runtime/qrt/internal_compiler/qalloc.cpp +22 −6 Original line number Diff line number Diff line Loading @@ -173,20 +173,36 @@ void setGlobalQubitManager(AllocEventListener *in_listener) { // Dummy one: struct DummyListener : AllocEventListener { static std::string address_to_string(qubit *qubit) { std::ostringstream address; address << (void const *)qubit; return address.str(); } virtual void onAllocate(qubit *qubit) override { xacc::debug("Allocate: " + qubit->first + "[" + std::to_string(qubit->second) + "]"); xacc::debug("Allocate qubit: " + qubit->first + "[" + std::to_string(qubit->second) + "] at: " + address_to_string(qubit)); } // On deallocate: don't try to deref the qubit since it may have been gone. virtual void onDealloc(qubit *qubit) override { xacc::debug("Deallocate: " + qubit->first + "[" + std::to_string(qubit->second) + "]"); xacc::debug("Deallocate qubit at address: " + address_to_string(qubit)); } // Note: AllocEventListener global instances must // be heap-allocated to be alive until all qubits have been deallocated. static AllocEventListener *getInstance() { static DummyListener dummy; return &dummy; if (!g_instance) { g_instance = new DummyListener(); } return g_instance; } static DummyListener *g_instance; }; DummyListener *DummyListener::g_instance = nullptr; AllocEventListener *getGlobalQubitManager() { return global_alloc_tracker ? global_alloc_tracker : DummyListener::getInstance(); Loading runtime/qrt/internal_compiler/qalloc.hpp +2 −2 Original line number Diff line number Diff line Loading @@ -64,13 +64,13 @@ struct qubit { qubit(const std::string ®_name, size_t idx, xacc::AcceleratorBuffer *in_buffer = nullptr) : first(reg_name), second(idx), buffer(in_buffer) { // tracker = std::make_shared<AllocTracker>(this); tracker = std::make_shared<AllocTracker>(this); } qubit() = default; // Having this tracker as a shared_ptr so that we can follow the qubit // even if it is copied, e.g. via slicing. // Default copy and copy assign should just copy this tracker across. // std::shared_ptr<AllocTracker> tracker; std::shared_ptr<AllocTracker> tracker; }; class qreg; Loading Loading
runtime/qrt/impls/nisq/nisq_qrt.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,71 @@ using namespace cppmicroservices; using namespace xacc; namespace { class NisqQubitAllocator : public AllocEventListener, public QubitAllocator { public: static inline const std::string ANC_BUFFER_NAME = "nisq_temp_buffer"; virtual void onAllocate(qubit *in_qubit) override {} // On deallocate: don't try to deref the qubit since it may have been gone. virtual void onDealloc(qubit *in_qubit) override { // If this qubit was allocated from this pool: if (xacc::container::contains(m_allocatedQubits, in_qubit)) { const auto qIndex = std::find(m_allocatedQubits.begin(), m_allocatedQubits.end(), in_qubit) - m_allocatedQubits.begin(); // Strategy: create a storage copy of the returned qubit: // i.e. with the same index w.r.t. this global anc. buffer // but store it in the pool vector -> will stay alive // until giving out at the next allocate() qubit archive_qubit(ANC_BUFFER_NAME, qIndex, m_buffer.get()); m_allocatedQubits[qIndex] = &archive_qubit; m_qubitPool.emplace_back(archive_qubit); } } virtual qubit allocate() override { if (!m_qubitPool.empty()) { auto recycled_qubit = m_qubitPool.back(); m_qubitPool.pop_back(); return recycled_qubit; } if (!m_buffer) { // This must be the first call. assert(m_allocatedQubits.empty()); m_buffer = xacc::qalloc(1); } // Need to allocate new qubit: // Each new qubit will have an incrementing index. const auto newIdx = m_allocatedQubits.size(); qubit new_qubit(ANC_BUFFER_NAME, newIdx, m_buffer.get()); // Just track that we allocated this qubit m_allocatedQubits.emplace_back(&new_qubit); m_buffer->setSize(m_allocatedQubits.size()); return new_qubit; } static NisqQubitAllocator *getInstance() { if (!g_instance) { g_instance = new NisqQubitAllocator(); } return g_instance; } static NisqQubitAllocator *g_instance; private: std::vector<qubit> m_qubitPool; // Track the list of qubit pointers for those // that was allocated by this Allocator. std::vector<qubit *> m_allocatedQubits; std::shared_ptr<xacc::AcceleratorBuffer> m_buffer; }; NisqQubitAllocator *NisqQubitAllocator::g_instance = nullptr; } // namespace namespace qcor { template <typename T> bool ptr_is_a(std::shared_ptr<Observable> ptr) { Loading
runtime/qrt/internal_compiler/qalloc.cpp +22 −6 Original line number Diff line number Diff line Loading @@ -173,20 +173,36 @@ void setGlobalQubitManager(AllocEventListener *in_listener) { // Dummy one: struct DummyListener : AllocEventListener { static std::string address_to_string(qubit *qubit) { std::ostringstream address; address << (void const *)qubit; return address.str(); } virtual void onAllocate(qubit *qubit) override { xacc::debug("Allocate: " + qubit->first + "[" + std::to_string(qubit->second) + "]"); xacc::debug("Allocate qubit: " + qubit->first + "[" + std::to_string(qubit->second) + "] at: " + address_to_string(qubit)); } // On deallocate: don't try to deref the qubit since it may have been gone. virtual void onDealloc(qubit *qubit) override { xacc::debug("Deallocate: " + qubit->first + "[" + std::to_string(qubit->second) + "]"); xacc::debug("Deallocate qubit at address: " + address_to_string(qubit)); } // Note: AllocEventListener global instances must // be heap-allocated to be alive until all qubits have been deallocated. static AllocEventListener *getInstance() { static DummyListener dummy; return &dummy; if (!g_instance) { g_instance = new DummyListener(); } return g_instance; } static DummyListener *g_instance; }; DummyListener *DummyListener::g_instance = nullptr; AllocEventListener *getGlobalQubitManager() { return global_alloc_tracker ? global_alloc_tracker : DummyListener::getInstance(); Loading
runtime/qrt/internal_compiler/qalloc.hpp +2 −2 Original line number Diff line number Diff line Loading @@ -64,13 +64,13 @@ struct qubit { qubit(const std::string ®_name, size_t idx, xacc::AcceleratorBuffer *in_buffer = nullptr) : first(reg_name), second(idx), buffer(in_buffer) { // tracker = std::make_shared<AllocTracker>(this); tracker = std::make_shared<AllocTracker>(this); } qubit() = default; // Having this tracker as a shared_ptr so that we can follow the qubit // even if it is copied, e.g. via slicing. // Default copy and copy assign should just copy this tracker across. // std::shared_ptr<AllocTracker> tracker; std::shared_ptr<AllocTracker> tracker; }; class qreg; Loading