... remaining fixes: hybrid dynamic multi-threaded operations work

This commit is contained in:
Christian Zimmermann 2020-08-29 23:36:01 +02:00
parent 4e7e57fcb9
commit 566da70618
8 changed files with 171 additions and 14 deletions

View file

@ -41,10 +41,89 @@ namespace MultiArrayTools
return std::make_shared<DynamicOperation<T,Operation>>(*this); return std::make_shared<DynamicOperation<T,Operation>>(*this);
} }
template <typename T, class Operation, class... Ranges>
DynamicOuterOp<T,Operation,Ranges...>::DynamicOuterOp(const DynamicOuterOp& in) :
mThreadId(omp_get_thread_num()), mOp(in.mOp),
mIndices(in.mIndices),
mMa((mThreadId != in.mThreadId) ? std::make_shared<MultiArray<T,Ranges...>>(*in.mMa) : in.mMa),
mProto((mThreadId != in.mThreadId) ? OperationRoot<T,Ranges...>(*mMa,mIndices) : in.mProto),
mL((mThreadId != in.mThreadId) ?
mkILoop(std::make_tuple(*mProto.mOp,mOp), mIndices,
std::make_tuple(mMa),
std::make_tuple(mProto.mOp->assign( mOp, mkMIndex(mIndices) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0})) :
in.mL)
{*mMa = 0;}
template <typename T, class Operation, class... Ranges>
DynamicOuterOp<T,Operation,Ranges...>::DynamicOuterOp(DynamicOuterOp&& in) :
mThreadId(omp_get_thread_num()), mOp(in.mOp),
mIndices(in.mIndices),
mMa((mThreadId != in.mThreadId) ? std::make_shared<MultiArray<T,Ranges...>>(*in.mMa) : in.mMa),
mProto((mThreadId != in.mThreadId) ? OperationRoot<T,Ranges...>(*mMa,mIndices) : in.mProto),
mL((mThreadId != in.mThreadId) ?
mkILoop(std::make_tuple(*mProto.mOp,mOp), mIndices,
std::make_tuple(mMa),
std::make_tuple(mProto.mOp->assign( mOp, mkMIndex(mIndices) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0})) :
in.mL)
{*mMa = 0;}
template <typename T, class Operation, class... Ranges>
DynamicOuterOp<T,Operation,Ranges...>&
DynamicOuterOp<T,Operation,Ranges...>::operator=(const DynamicOuterOp& in)
{
mThreadId = omp_get_thread_num();
mOp = in.mOp;
mIndices = in.mIndices;
if(mThreadId != in.mThreadId){
mMa = std::make_shared<MultiArray<T,Ranges...>>(in.mMa);
mProto = OperationRoot<T,Ranges...>(*mMa,mIndices);
mL = mkILoop(std::make_tuple(*mProto.mOp,mOp), mIndices,
std::make_tuple(mMa),
std::make_tuple(mProto.mOp->assign( mOp, mkMIndex(mIndices) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0}));
}
else {
mMa = in.mMa;
mProto = in.mProto;
mL = in.mL;
}
*mMa = 0;
return *this;
}
template <typename T, class Operation, class... Ranges>
DynamicOuterOp<T,Operation,Ranges...>&
DynamicOuterOp<T,Operation,Ranges...>::operator=(DynamicOuterOp&& in)
{
mThreadId = omp_get_thread_num();
mOp = in.mOp;
mIndices = in.mIndices;
if(mThreadId != in.mThreadId){
mMa = std::make_shared<MultiArray<T,Ranges...>>(in.mMa);
mProto = OperationRoot<T,Ranges...>(*mMa,mIndices);
mL = mkILoop(std::make_tuple(*mProto.mOp,mOp), mIndices,
std::make_tuple(mMa),
std::make_tuple(mProto.mOp->assign( mOp, mkMIndex(mIndices) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0}));
}
else {
mMa = in.mMa;
mProto = in.mProto;
mL = in.mL;
}
*mMa = 0;
return *this;
}
template <typename T, class Operation, class... Ranges> template <typename T, class Operation, class... Ranges>
DynamicOuterOp<T,Operation,Ranges...>::DynamicOuterOp(const Operation& op, DynamicOuterOp<T,Operation,Ranges...>::DynamicOuterOp(const Operation& op,
const std::shared_ptr<typename Ranges::IndexType>&... inds) const std::shared_ptr<typename Ranges::IndexType>&... inds)
: mOp(op), : mThreadId(omp_get_thread_num()), mOp(op),
mIndices(inds...),
mMa(std::make_shared<MultiArray<T,Ranges...>>(mkArray<T>(inds->range()...))), mMa(std::make_shared<MultiArray<T,Ranges...>>(mkArray<T>(inds->range()...))),
mProto(OperationRoot<T,Ranges...>(*mMa,inds...)), mProto(OperationRoot<T,Ranges...>(*mMa,inds...)),
mL(std::make_tuple(*mProto.mOp,mOp), std::make_tuple(inds...), mL(std::make_tuple(*mProto.mOp,mOp), std::make_tuple(inds...),

View file

@ -70,8 +70,10 @@ namespace MultiArrayTools
class DynamicOuterOp : public DynamicOperationBase<OpH<OperationRoot<T,Ranges...>>> class DynamicOuterOp : public DynamicOperationBase<OpH<OperationRoot<T,Ranges...>>>
{ {
private: private:
size_t mThreadId;
Operation mOp; Operation mOp;
//OperationRoot<T,Ranges...> mProto; //OperationRoot<T,Ranges...> mProto;
std::tuple<std::shared_ptr<typename Ranges::IndexType>...> mIndices;
std::shared_ptr<MultiArray<T,Ranges...>> mMa; std::shared_ptr<MultiArray<T,Ranges...>> mMa;
OpH<OperationRoot<T,Ranges...>> mProto; OpH<OperationRoot<T,Ranges...>> mProto;
@ -90,11 +92,11 @@ namespace MultiArrayTools
typedef decltype(mL.rootSteps()) ET; typedef decltype(mL.rootSteps()) ET;
//typedef decltype(std::declval<Operation>().rootSteps()) ET; //typedef decltype(std::declval<Operation>().rootSteps()) ET;
DynamicOuterOp() = default; DynamicOuterOp() : mThreadId(omp_get_thread_num()) {}
DynamicOuterOp(const DynamicOuterOp& in) = default; DynamicOuterOp(const DynamicOuterOp& in);
DynamicOuterOp(DynamicOuterOp&& in) = default; DynamicOuterOp(DynamicOuterOp&& in);
DynamicOuterOp& operator=(const DynamicOuterOp& in) = default; DynamicOuterOp& operator=(const DynamicOuterOp& in);
DynamicOuterOp& operator=(DynamicOuterOp&& in) = default; DynamicOuterOp& operator=(DynamicOuterOp&& in);
DynamicOuterOp(const Operation& op, const std::shared_ptr<typename Ranges::IndexType>&... inds); DynamicOuterOp(const Operation& op, const std::shared_ptr<typename Ranges::IndexType>&... inds);

View file

@ -36,6 +36,41 @@ namespace MultiArrayTools
return std::dynamic_pointer_cast<MultiRange<RangeTypes...> >( mrf.create() ); return std::dynamic_pointer_cast<MultiRange<RangeTypes...> >( mrf.create() );
} }
namespace
{
template <size_t N>
struct IndexToRangeTuple
{
template <class... IndexTypes>
static inline void set(std::tuple<std::shared_ptr<typename IndexTypes::RangeType>...>& out,
const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
{
std::get<N>(out) = std::get<N>(indices)->range();
IndexToRangeTuple<N-1>::set(out,indices);
}
};
template <>
struct IndexToRangeTuple<0>
{
template <class... IndexTypes>
static inline void set(std::tuple<std::shared_ptr<typename IndexTypes::RangeType>...>& out,
const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
{
std::get<0>(out) = std::get<0>(indices)->range();
}
};
}
template <class... IndexTypes>
auto indexToRangeTuple(const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
-> std::tuple<std::shared_ptr<typename IndexTypes::RangeType>...>
{
std::tuple<std::shared_ptr<typename IndexTypes::RangeType>...> out;
IndexToRangeTuple<sizeof...(IndexTypes)-1>::set(out, indices);
return out;
}
template <class... IndexTypes> template <class... IndexTypes>
auto mkMIndex(std::shared_ptr<IndexTypes>... indices) auto mkMIndex(std::shared_ptr<IndexTypes>... indices)
-> decltype( getIndex( mkMulti( indices->range()... ) ) ) -> decltype( getIndex( mkMulti( indices->range()... ) ) )
@ -45,6 +80,16 @@ namespace MultiArrayTools
return mi; return mi;
} }
template <class... IndexTypes>
auto mkMIndex(const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
-> decltype( getIndex( mkMulti( indexToRangeTuple(indices) ) ) )
{
auto mi = getIndex( mkMulti( indexToRangeTuple(indices) ) );
(*mi)( indices );
return mi;
}
template <class Index> template <class Index>
auto mkIndexW(const std::shared_ptr<Index>& ind) auto mkIndexW(const std::shared_ptr<Index>& ind)
-> std::shared_ptr<IndexW> -> std::shared_ptr<IndexW>
@ -102,7 +147,7 @@ namespace MultiArrayTools
template <class... RangeTypes> template <class... RangeTypes>
auto mkMulti(std::tuple<std::shared_ptr<RangeTypes>...> rangesTuple) auto mkMulti(std::tuple<std::shared_ptr<RangeTypes>...> rangesTuple)
-> MultiRange<RangeTypes...> -> std::shared_ptr<MultiRange<RangeTypes...>>
{ {
MultiRangeFactory<RangeTypes...> mrf( rangesTuple ); MultiRangeFactory<RangeTypes...> mrf( rangesTuple );
return std::dynamic_pointer_cast<MultiRange<RangeTypes...> >( mrf.create() ); return std::dynamic_pointer_cast<MultiRange<RangeTypes...> >( mrf.create() );

View file

@ -57,17 +57,26 @@ namespace MultiArrayTools
auto mkMapI(const std::tuple<Op,MA>& f, std::shared_ptr<IndexTypes>... indices) auto mkMapI(const std::tuple<Op,MA>& f, std::shared_ptr<IndexTypes>... indices)
-> decltype( mkGenMapI<SpaceType::ANY>(f, indices... ) ); -> decltype( mkGenMapI<SpaceType::ANY>(f, indices... ) );
template <class... IndexTypes>
auto indexToRangeTuple(const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
-> std::tuple<std::shared_ptr<typename IndexTypes::RangeType>...>;
template <class... RangeTypes>
auto mkMulti(std::tuple<std::shared_ptr<RangeTypes>...> rangesTuple)
-> std::shared_ptr<MultiRange<RangeTypes...>>;
template <class... IndexTypes> template <class... IndexTypes>
auto mkMIndex(std::shared_ptr<IndexTypes>... indices) auto mkMIndex(std::shared_ptr<IndexTypes>... indices)
-> decltype( getIndex( mkMulti( indices.range()... ) ) ); -> decltype( getIndex( mkMulti( indices.range()... ) ) );
template <class... IndexTypes>
auto mkMIndex(const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
-> decltype( getIndex( mkMulti( indexToRangeTuple(indices) ) ) );
template <class Index> template <class Index>
auto mkIndexW(const std::shared_ptr<Index>& ind) auto mkIndexW(const std::shared_ptr<Index>& ind)
-> std::shared_ptr<IndexW>; -> std::shared_ptr<IndexW>;
template <class... RangeTypes>
auto mkMulti(std::tuple<std::shared_ptr<RangeTypes>...> rangesTuple)
-> MultiRange<RangeTypes...>;
template <class RangeFactory> template <class RangeFactory>
auto createExplicit(RangeFactory& rf) auto createExplicit(RangeFactory& rf)

View file

@ -481,6 +481,18 @@ namespace MultiArrayTools
mDataPtr = mOrigDataPtr + mIndex.pos(); mDataPtr = mOrigDataPtr + mIndex.pos();
} }
template <typename T, class... Ranges>
OperationRoot<T,Ranges...>::
OperationRoot(MutableMultiArrayBase<T,Ranges...>& ma,
const std::tuple<std::shared_ptr<typename Ranges::IndexType>...>& indices) :
mDataPtr(ma.data()),
mOrigDataPtr(ma.data()),
mIndex( ma.begin() )
{
mIndex(indices);
mDataPtr = mOrigDataPtr + mIndex.pos();
}
template <typename T, class... Ranges> template <typename T, class... Ranges>
OperationRoot<T,Ranges...>:: OperationRoot<T,Ranges...>::
OperationRoot(T* data, const IndexType& ind) : OperationRoot(T* data, const IndexType& ind) :

View file

@ -368,6 +368,9 @@ namespace MultiArrayTools
OperationRoot(MutableMultiArrayBase<T,Ranges...>& ma, OperationRoot(MutableMultiArrayBase<T,Ranges...>& ma,
const std::shared_ptr<typename Ranges::IndexType>&... indices); const std::shared_ptr<typename Ranges::IndexType>&... indices);
OperationRoot(MutableMultiArrayBase<T,Ranges...>& ma,
const std::tuple<std::shared_ptr<typename Ranges::IndexType>...>& indices);
OperationRoot(T* data, const IndexType& ind); OperationRoot(T* data, const IndexType& ind);
template <class OpClass> template <class OpClass>

View file

@ -85,6 +85,7 @@ namespace MultiArrayTools
// NO foreign/external controll) // NO foreign/external controll)
// Do NOT share index instances between two or more MultiIndex instances // Do NOT share index instances between two or more MultiIndex instances
MultiIndex& operator()(std::shared_ptr<Indices>&... indices); MultiIndex& operator()(std::shared_ptr<Indices>&... indices);
MultiIndex& operator()(const std::tuple<std::shared_ptr<Indices>...>& indices);
// ==== >>>>> STATIC POLYMORPHISM <<<<< ==== // ==== >>>>> STATIC POLYMORPHISM <<<<< ====
@ -324,6 +325,14 @@ namespace MultiArrayTools
return *this; return *this;
} }
template <class... Indices>
MultiIndex<Indices...>& MultiIndex<Indices...>::operator()(const std::tuple<std::shared_ptr<Indices>...>& indices)
{
RPackNum<sizeof...(Indices)-1>::swapIndices(mIPack, indices);
RPackNum<sizeof...(Indices)-1>::setIndexPack(mIPack, IB::mPos);
return *this;
}
template <class... Indices> template <class... Indices>
IndexType MultiIndex<Indices...>::type() const IndexType MultiIndex<Indices...>::type() const
{ {

View file

@ -137,14 +137,12 @@ namespace
resx2(i1,di4) = mkDynOp(ma1(i1,di1) * ma2(i1,di2)); resx2(i1,di4) = mkDynOp(ma1(i1,di1) * ma2(i1,di2));
resx3(i1,di4) = mkDynOp(mkDynOp(ma1(i1,di1)) * mkDynOp(ma2(i1,di2))); resx3(i1,di4) = mkDynOp(mkDynOp(ma1(i1,di1)) * mkDynOp(ma2(i1,di2)));
//auto op1 = mkDynOutOp((ma1(i1,di1) * ma2(i1,di2)), ci4_1, ci4_2); auto op1x = mkDynOutOp((ma1(i1,di1) * ma2(i1,di2)), ci4_1, ci4_2);
//auto opr = resx4(i1,di4);
auto op1x = (ma1(i1,di1) * ma2(i1,di2));
auto opr = resx4(i1,di4); auto opr = resx4(i1,di4);
auto loop = mkPILoop auto loop = mkPILoop
( [&op1x,&opr,&xx,this](){ ( [&op1x,&opr,&xx,this](){
auto op1 = mkDynOutOp(op1x, ci4_1, ci4_2); auto op1 = op1x;
return mkGetExpr(op1,mkILoop(std::make_tuple(opr,op1,*op1.data()->mOp), std::make_tuple(ci4_1, ci4_2), return mkGetExpr(op1,mkILoop(std::make_tuple(opr,op1,*op1.data()->mOp), std::make_tuple(ci4_1, ci4_2),
std::make_tuple(xx), std::make_tuple(xx),
std::make_tuple(opr.assign( *op1.data()->mOp, mkMIndex(ci4_1, ci4_2) )), std::make_tuple(opr.assign( *op1.data()->mOp, mkMIndex(ci4_1, ci4_2) )),