From 5638b61de1cb667631d78601c5238757222b8009 Mon Sep 17 00:00:00 2001 From: Akihiro Hayashi Date: Thu, 13 May 2021 03:25:22 +0000 Subject: [PATCH 1/3] Initial Thread-Safe Implementation Add thread-safety to XACC/QCOR (Experimental). We introduce `_XACC_MUTEX` macro in `xacc.hpp` to turn on/off the feature (default is OFF). When the macro is ON, only a single thread can execute the following routines by using either `std::mutex` or `std::recursive_mutex`: - User-facing API routines - `xacc::qalloc()` - Backend modules - `QppAccelerator` - `execute()` (the existing shot-level parallel execution still works) - `apply()` - `NLOptimizer` - `optimize()` Also, regardless of the macro, the `NLOptimizer` class is now `xacc::Cloneable`. Signed-off-by: Akihiro Hayashi --- quantum/plugins/qpp/accelerator/QppAccelerator.cpp | 11 +++++++++++ quantum/plugins/qpp/accelerator/QppAccelerator.hpp | 10 +++++++++- xacc/optimizer/nlopt-optimizers/nlopt_optimizer.cpp | 3 +++ xacc/optimizer/nlopt-optimizers/nlopt_optimizer.hpp | 13 ++++++++++++- xacc/xacc.cpp | 10 ++++++++++ xacc/xacc.hpp | 5 +++++ 6 files changed, 50 insertions(+), 2 deletions(-) diff --git a/quantum/plugins/qpp/accelerator/QppAccelerator.cpp b/quantum/plugins/qpp/accelerator/QppAccelerator.cpp index 318bc8665..7d7a39833 100644 --- a/quantum/plugins/qpp/accelerator/QppAccelerator.cpp +++ b/quantum/plugins/qpp/accelerator/QppAccelerator.cpp @@ -244,6 +244,9 @@ namespace quantum { void QppAccelerator::execute(std::shared_ptr buffer, const std::shared_ptr compositeInstruction) { +#ifdef _XACC_MUTEX + std::lock_guard lock(getMutex()); +#endif const auto runCircuit = [&](bool shotsMode){ m_visitor->initialize(buffer, shotsMode); @@ -325,6 +328,10 @@ namespace quantum { void QppAccelerator::execute(std::shared_ptr buffer, const std::vector> compositeInstructions) { +#ifdef _XACC_MUTEX + std::lock_guard lock(getMutex()); +#endif + if (!m_vqeMode || compositeInstructions.size() <= 1) { for (auto& f : compositeInstructions) @@ -370,6 +377,10 @@ namespace quantum { void QppAccelerator::apply(std::shared_ptr buffer, std::shared_ptr inst) { +#ifdef _XACC_MUTEX + std::lock_guard lock(getMutex()); +#endif + if (!m_visitor->isInitialized()) { m_visitor->initialize(buffer); m_currentBuffer = std::make_pair(buffer.get(), buffer->size()); diff --git a/quantum/plugins/qpp/accelerator/QppAccelerator.hpp b/quantum/plugins/qpp/accelerator/QppAccelerator.hpp index f7ce05a7f..01b11560e 100644 --- a/quantum/plugins/qpp/accelerator/QppAccelerator.hpp +++ b/quantum/plugins/qpp/accelerator/QppAccelerator.hpp @@ -14,7 +14,9 @@ #include "xacc.hpp" #include "QppVisitor.hpp" #include "NoiseModel.hpp" - +#ifdef _XACC_MUTEX +#include +#endif namespace xacc { namespace quantum { @@ -50,6 +52,12 @@ class QppAccelerator : public Accelerator { std::vector> m_connectivity; xacc::HeterogeneousMap m_executionInfo; std::pair m_currentBuffer; +#ifdef _XACC_MUTEX + static std::recursive_mutex& getMutex() { + static std::recursive_mutex m;; + return m; + } +#endif }; class DefaultNoiseModelUtils : public NoiseModelUtils diff --git a/xacc/optimizer/nlopt-optimizers/nlopt_optimizer.cpp b/xacc/optimizer/nlopt-optimizers/nlopt_optimizer.cpp index c91aec2ba..375e590e1 100644 --- a/xacc/optimizer/nlopt-optimizers/nlopt_optimizer.cpp +++ b/xacc/optimizer/nlopt-optimizers/nlopt_optimizer.cpp @@ -56,6 +56,9 @@ const bool NLOptimizer::isGradientBased() const { } OptResult NLOptimizer::optimize(OptFunction &function) { +#ifdef _XACC_MUTEX + std::lock_guard lock(getMutex()); +#endif auto dim = function.dimensions(); nlopt::algorithm algo = nlopt::algorithm::LN_COBYLA; diff --git a/xacc/optimizer/nlopt-optimizers/nlopt_optimizer.hpp b/xacc/optimizer/nlopt-optimizers/nlopt_optimizer.hpp index c2b770099..5ba981753 100644 --- a/xacc/optimizer/nlopt-optimizers/nlopt_optimizer.hpp +++ b/xacc/optimizer/nlopt-optimizers/nlopt_optimizer.hpp @@ -17,6 +17,7 @@ #include #include "Optimizer.hpp" +#include "xacc.hpp" namespace xacc { @@ -24,7 +25,13 @@ struct ExtraNLOptData { std::function&, std::vector&)> f; }; -class NLOptimizer : public Optimizer { +class NLOptimizer : public Optimizer, public xacc::Cloneable { +#ifdef _XACC_MUTEX + static std::mutex& getMutex() { + static std::mutex lock; + return lock; + } +#endif public: OptResult optimize(OptFunction &function) override; const bool isGradientBased() const override; @@ -32,6 +39,10 @@ class NLOptimizer : public Optimizer { const std::string name() const override { return "nlopt"; } const std::string description() const override { return ""; } + + std::shared_ptr clone() override { + return std::make_shared(); + } }; } // namespace xacc #endif diff --git a/xacc/xacc.cpp b/xacc/xacc.cpp index 4716e9423..92b55ecdf 100644 --- a/xacc/xacc.cpp +++ b/xacc/xacc.cpp @@ -156,7 +156,14 @@ void error(const std::string &msg, MessagePredicate predicate) { } } +#ifdef _XACC_MUTEX +std::mutex qalloc_lock; +#endif + qbit qalloc(const int n) { +#ifdef _XACC_MUTEX + std::lock_guard lock(qalloc_lock); +#endif qbit q(n); std::stringstream ss; ss << "qreg_" << q; @@ -165,6 +172,9 @@ qbit qalloc(const int n) { return q; } qbit qalloc() { +#ifdef _XACC_MUTEX + std::lock_guard lock(qalloc_lock); +#endif qbit q; std::stringstream ss; ss << "qreg_" << q; diff --git a/xacc/xacc.hpp b/xacc/xacc.hpp index 7c71740bd..6f7aa57ce 100644 --- a/xacc/xacc.hpp +++ b/xacc/xacc.hpp @@ -28,6 +28,11 @@ #include #include +#undef _XACC_MUTEX +#ifdef _XACC_MUTEX +#include +#endif + namespace xacc { namespace constants { From ca4286de2952ec96321e08fe366eb0aaf3a79340 Mon Sep 17 00:00:00 2001 From: Akihiro Hayashi Date: Wed, 23 Jun 2021 19:04:07 +0000 Subject: [PATCH 2/3] Add a CMake option that turns on/off _XACC_MUTEX Signed-off-by: Akihiro Hayashi --- CMakeLists.txt | 8 ++++++++ xacc/xacc.hpp | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 46f9a83de..289e72952 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ message(STATUS "C++ version ${CXX_STANDARD} configured.") option(XACC_BUILD_TESTS "Build test programs" OFF) option(XACC_BUILD_EXAMPLES "Build example programs" OFF) +option(XACC_MULTI_THREADED "Enable multi-thread support" OFF) option(XACC_ENSMALLEN_INCLUDE_DIR "Path to ensmallen.hpp for mlpack optimizer" "") option(XACC_ARMADILLO_INCLUDE_DIR "Path to armadillo header for mlpack optimizer" "") @@ -101,6 +102,13 @@ endif() message(STATUS "${BoldGreen}Installing XACC to ${CMAKE_INSTALL_PREFIX}. Override with -DCMAKE_INSTALL_PREFIX=...${ColorReset}") +if (XACC_MULTI_THREADED) + message(STATUS "${BoldGreen}Multi-thread support is enabled ${ColorReset}") + add_compile_definitions(_XACC_MUTEX) +else() + message(STATUS "${BoldGreen}Multi-thread support is disabled (default)${ColorReset}") +endif() + if (XACC_BUILD_TESTS) enable_testing() macro(add_xacc_test _TEST_NAME) diff --git a/xacc/xacc.hpp b/xacc/xacc.hpp index 6f7aa57ce..d4c63e61b 100644 --- a/xacc/xacc.hpp +++ b/xacc/xacc.hpp @@ -28,7 +28,6 @@ #include #include -#undef _XACC_MUTEX #ifdef _XACC_MUTEX #include #endif From d51b6dc121ea1c5d6b8ca317c751201e97b8de0e Mon Sep 17 00:00:00 2001 From: Akihiro Hayashi Date: Tue, 20 Jul 2021 16:59:28 +0000 Subject: [PATCH 3/3] Export _XACC_MUTEX and XACC_MULTI_THREADED Signed-off-by: Akihiro Hayashi --- CMakeLists.txt | 4 +++- cmake/xacc-config.cmake.in | 3 +++ cmake/xacc_config.hpp.in | 1 + xacc/xacc.hpp | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 289e72952..ec876c74e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,9 +104,11 @@ message(STATUS "${BoldGreen}Installing XACC to ${CMAKE_INSTALL_PREFIX}. Override if (XACC_MULTI_THREADED) message(STATUS "${BoldGreen}Multi-thread support is enabled ${ColorReset}") - add_compile_definitions(_XACC_MUTEX) + add_compile_definitions(_XACC_MUTEX) + set(_XACC_MUTEX True) else() message(STATUS "${BoldGreen}Multi-thread support is disabled (default)${ColorReset}") + set(_XACC_MUTEX False) endif() if (XACC_BUILD_TESTS) diff --git a/cmake/xacc-config.cmake.in b/cmake/xacc-config.cmake.in index b9b0c8ec2..84e576293 100644 --- a/cmake/xacc-config.cmake.in +++ b/cmake/xacc-config.cmake.in @@ -179,3 +179,6 @@ set_target_properties(xacc::fermion PROPERTIES if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set (CMAKE_INSTALL_PREFIX "${XACC_ROOT}" CACHE PATH "default install path" FORCE ) endif() + +# If xacc is built with -DXACC_MULTI_THREADED +set(XACC_MULTI_THREADED @XACC_MULTI_THREADED@) diff --git a/cmake/xacc_config.hpp.in b/cmake/xacc_config.hpp.in index 9aef5305e..19c73b2b7 100644 --- a/cmake/xacc_config.hpp.in +++ b/cmake/xacc_config.hpp.in @@ -7,5 +7,6 @@ #define ROERROR_TEST_FILE_DIR "${CMAKE_SOURCE_DIR}/quantum/plugins/decorators/tests/files" #define GATEIR_TEST_FILE_DIR "${CMAKE_SOURCE_DIR}/quantum/gate/ir/tests/files" #define XACC_IS_APPLE ${XACC_IS_APPLE} +#cmakedefine _XACC_MUTEX #endif diff --git a/xacc/xacc.hpp b/xacc/xacc.hpp index d4c63e61b..85d06eca7 100644 --- a/xacc/xacc.hpp +++ b/xacc/xacc.hpp @@ -29,6 +29,7 @@ #include #ifdef _XACC_MUTEX +#pragma message("_XACC_MUTEX is defined") #include #endif