From a8efbd083a4787cc31b4d77055e7ae992bb16b99 Mon Sep 17 00:00:00 2001 From: Christian Zimmermann Date: Wed, 22 May 2019 16:36:44 +0200 Subject: [PATCH] piloop: handles iloop instances wrt to thread safety --- src/include/helper_tools.h | 9 ++- src/include/xfor/iloop.h | 119 ++++++++++++++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/src/include/helper_tools.h b/src/include/helper_tools.h index 0b567d7..8e5b1ef 100644 --- a/src/include/helper_tools.h +++ b/src/include/helper_tools.h @@ -129,7 +129,14 @@ namespace MultiArrayTools { return MultiArrayHelper::ILoop(opTp, indTp, varTp, lTp, umpos, setzero); } - + + template + auto mkPILoop(const CF& cf) + -> MultiArrayHelper::PILoop + { + return MultiArrayHelper::PILoop(cf); + } + template inline void For(const std::shared_ptr& ind, const std::function& ll) { diff --git a/src/include/xfor/iloop.h b/src/include/xfor/iloop.h index f172bf4..65a492c 100644 --- a/src/include/xfor/iloop.h +++ b/src/include/xfor/iloop.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace MultiArrayHelper { @@ -87,7 +88,7 @@ namespace MultiArrayHelper private: static constexpr size_t LTpSize = std::tuple_size::value; static constexpr size_t VarTpSize = std::tuple_size::value; - + OpTp mOpTp; IndTp mIndTp; @@ -102,6 +103,8 @@ namespace MultiArrayHelper static constexpr bool CONT = false; typedef decltype(NN::rootSteps(mLTp)) ExtType; + ILoop() { assert(omp_get_thread_num() == 0); } + ILoop(const OpTp& opTp, const IndTp& indTp, const VarTp& varTp, const LTp& lTp, const std::array& umpos, const std::array& setzero) : mOpTp(opTp), mIndTp(indTp), mVarTp(varTp), mLTp(lTp), mUmpos(umpos), mSetzero(setzero) {} @@ -122,6 +125,120 @@ namespace MultiArrayHelper }; + template + struct CreateLoops + { + template + static inline auto apply(CLTp& cltp, VarTp& varTp) + { + return std::tuple_cat( CreateLoops::apply(cltp,varTp) , std::make_tuple( std::get(cltp)(varTp) ) ); + } + }; + + template <> + struct CreateLoops <0> + { + template + static inline auto apply(CLTp& cltp, VarTp& varTp) + { + return std::make_tuple( std::get<0>(cltp)(varTp) ); + } + }; + + template + struct ThrCpy + { + template + static inline auto apply(size_t thread1, size_t thread2, const VarTp& varTp) + { + auto& var = std::get(varTp); + typedef typename std::remove_reference::type Type; + return std::tuple_cat( ThrCpy::apply(thread1, thread2, varTp), + std::make_tuple( (thread1 == thread2) ? var : std::make_shared(*var) ) ); + } + }; + + template <> + struct ThrCpy <0> + { + template + static inline auto apply(size_t thread1, size_t thread2, const VarTp& varTp) + { + auto& var = std::get<0>(varTp); + typedef typename std::remove_reference::type Type; + return std::make_tuple( (thread1 == thread2) ? var : std::make_shared(*var) ); + } + }; + + template + auto thrCpy(size_t thread1, size_t thread2, const std::tuple...>& vars) + { + return ThrCpy::apply(thread1, thread2, vars); + } + + template + auto createLoops(std::tuple& cls) + { + return CreateLoops::apply(cls); + } + + // CF = creation function + // if instance copied to different thread, the "copy" will be newly created from this function + // -> ensures that there is NO SHARED WORKSPACE + template + class PILoop + { + private: + size_t mThreadId = 0; + CF mCF; + + typedef decltype(mCF()) LType; + + LType mL; + + static constexpr size_t LTpSize = LType::LTpSize; + static constexpr size_t VarTpSize = LType::VarTpSize; + + public: + static constexpr size_t SIZE = LType::SIZE; + static constexpr bool CONT = LType::CONT; + typedef typename LType::ExtType ExtType; + + PILoop() : mThreadId(omp_get_thread_num()) {} + + PILoop(const PILoop& in) : mThreadId(omp_get_thread_num()), mCF(in.mCF), mL((mThreadId == in.mThreadId) ? in.mL : mCF()) {} + PILoop& operator=(const PILoop& in) + { + mThreadId = omp_get_thread_num(); + mCF = in.mCF; + mL = (mThreadId == in.mThreadId) ? in.mL : mCF(); + return *this; + } + + PILoop(PILoop&& in) : mThreadId(omp_get_thread_num()), mCF(std::move(in.mCF)), mL((mThreadId == in.mThreadId) ? std::move(in.mL) : std::move(mCF())) {} + PILoop& operator=(PILoop&& in) + { + mThreadId = omp_get_thread_num(); + mCF = std::move(in.mCF); + mL = (mThreadId == in.mThreadId) ? std::move(in.mL) : std::move(mCF()); + return *this; + } + + PILoop(const CF& cf) : mThreadId(omp_get_thread_num()), mCF(cf), mL(mCF()) {} + + inline size_t operator()(size_t mpos, ExtType pos) + { + return mL(mpos, pos); + } + + auto rootSteps(std::intptr_t i = 0) const + -> ExtType + { + return mL.rootSteps(i); + } + + }; + } #endif