From 3090282ba8b9d930d0bc64e2b1e6f5abefe7cd15 Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Thu, 29 Oct 2020 21:53:32 +0100 Subject: [PATCH 01/18] #1051: vrt-collection: add invoke function to virtual collection proxy which instantly invokes the handler without going through scheduler --- src/CMakeLists.txt | 1 + src/vt/vrt/collection/balance/lb_comm.h | 3 +- src/vt/vrt/collection/balance/node_stats.cc | 3 +- src/vt/vrt/collection/invoke/invokable.h | 75 +++++++++++ src/vt/vrt/collection/invoke/invokable.impl.h | 91 ++++++++++++++ src/vt/vrt/collection/manager.h | 48 +++++++ src/vt/vrt/collection/manager.impl.h | 119 ++++++++++++++++++ .../proxy_traits/proxy_elm_traits.h | 6 +- 8 files changed, 343 insertions(+), 3 deletions(-) create mode 100644 src/vt/vrt/collection/invoke/invokable.h create mode 100644 src/vt/vrt/collection/invoke/invokable.impl.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5d7f4beb04..50d16619ab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -76,6 +76,7 @@ set( vrt/collection/dispatch vrt/collection/gettable vrt/collection/rdmaable vrt/collection/staged_token vrt/collection/listener + vrt/collection/invoke vrt/collection/balance vrt/collection/balance/baselb vrt/collection/balance/hierarchicallb diff --git a/src/vt/vrt/collection/balance/lb_comm.h b/src/vt/vrt/collection/balance/lb_comm.h index c71a43ebec..1049acdb0e 100644 --- a/src/vt/vrt/collection/balance/lb_comm.h +++ b/src/vt/vrt/collection/balance/lb_comm.h @@ -59,7 +59,8 @@ enum struct CommCategory : int8_t { Broadcast = 4, CollectionToNodeBcast = 5, NodeToCollectionBcast = 6, - CollectiveToCollectionBcast = 7 + CollectiveToCollectionBcast = 7, + LocalInvoke = 8 }; inline NodeType objGetNode(ElementIDType const id) { diff --git a/src/vt/vrt/collection/balance/node_stats.cc b/src/vt/vrt/collection/balance/node_stats.cc index 3e34e05061..3a518f9b4c 100644 --- a/src/vt/vrt/collection/balance/node_stats.cc +++ b/src/vt/vrt/collection/balance/node_stats.cc @@ -237,9 +237,10 @@ getRecvSendDirection(CommKeyType const& comm) { case CommCategory::CollectionToNodeBcast: return std::make_pair(comm.toNode(), comm.fromObj()); - // Comm stats are not recorded for collective bcast + // Comm stats are not recorded for local operations // this case is just to avoid warning of not handled enum case CommCategory::CollectiveToCollectionBcast: + case CommCategory::LocalInvoke: return std::make_pair(ElementIDType{}, ElementIDType{}); } diff --git a/src/vt/vrt/collection/invoke/invokable.h b/src/vt/vrt/collection/invoke/invokable.h new file mode 100644 index 0000000000..8573c7d4dd --- /dev/null +++ b/src/vt/vrt/collection/invoke/invokable.h @@ -0,0 +1,75 @@ +/* +//@HEADER +// ***************************************************************************** +// +// invokable.h +// DARMA Toolkit v. 1.0.0 +// DARMA/vt => Virtual Transport +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_VRT_COLLECTION_INVOKE_INVOKABLE_H +#define INCLUDED_VRT_COLLECTION_INVOKE_INVOKABLE_H + +#include "vt/config.h" +#include "vt/vrt/collection/active/active_funcs.h" + +namespace vt { namespace vrt { namespace collection { + +template +struct Invokable : BaseProxyT { + Invokable() = default; + Invokable( + typename BaseProxyT::ProxyType const& in_proxy, + typename BaseProxyT::ElementProxyType const& in_elm + ); + + template < + typename MsgT, ActiveColMemberTypedFnType f, typename... Args + > + void invoke(Args&&... args) const; + + template < + typename MsgT, ActiveColTypedFnType* f, + typename... Args + > + void invoke(Args&&... args) const; +}; + +}}} /* end namespace vt::vrt::collection */ + +#endif /*INCLUDED_VRT_COLLECTION_INVOKE_INVOKABLE_H*/ diff --git a/src/vt/vrt/collection/invoke/invokable.impl.h b/src/vt/vrt/collection/invoke/invokable.impl.h new file mode 100644 index 0000000000..9058dfe941 --- /dev/null +++ b/src/vt/vrt/collection/invoke/invokable.impl.h @@ -0,0 +1,91 @@ +/* +//@HEADER +// ***************************************************************************** +// +// invokable.impl.h +// DARMA Toolkit v. 1.0.0 +// DARMA/vt => Virtual Transport +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_VRT_COLLECTION_INVOKE_INVOKABLE_IMPL_H +#define INCLUDED_VRT_COLLECTION_INVOKE_INVOKABLE_IMPL_H + +#include "vt/vrt/collection/invoke/invokable.h" +#include "vt/vrt/collection/manager.h" + +namespace vt { namespace vrt { namespace collection { + +template +Invokable::Invokable( + typename BaseProxyT::ProxyType const& in_proxy, + typename BaseProxyT::ElementProxyType const& in_elm +) : BaseProxyT(in_proxy, in_elm) +{ } + +template +template < + typename MsgT, ActiveColMemberTypedFnType f, typename... Args +> +void Invokable::invoke(Args&&... args) const +{ + auto const& proxy = VrtElmProxy( + this->getCollectionProxy(), this->getElementProxy() + ); + + auto msg = makeMessage(std::forward(args)...); + theCollection()->invokeMsg(proxy, msg); +} + +template +template < + typename MsgT, ActiveColTypedFnType* f, + typename... Args +> +void Invokable::invoke(Args&&... args) const +{ + auto const& proxy = VrtElmProxy( + this->getCollectionProxy(), this->getElementProxy() + ); + + auto msg = makeMessage(std::forward(args)...); + theCollection()->invokeMsg(proxy, msg); +} + +}}} /* end namespace vt::vrt::collection */ + +#endif /*INCLUDED_VRT_COLLECTION_INVOKE_INVOKABLE_IMPL_H*/ diff --git a/src/vt/vrt/collection/manager.h b/src/vt/vrt/collection/manager.h index 61241cb6df..df18d72549 100644 --- a/src/vt/vrt/collection/manager.h +++ b/src/vt/vrt/collection/manager.h @@ -791,6 +791,53 @@ struct CollectionManager template static void recordStats(ColT* col_ptr, MsgT* msg); + /** + * \brief Invoke message action function handler without going through scheduler + * + * \param[in] proxy the collection proxy + * \param[in] msg the message + * \param[in] instrument whether to instrument the broadcast for load + * balancing (some system calls use this to disable instrumentation) + */ + template < + typename MsgT, ActiveColTypedFnType* f + > + void invokeMsg( + VirtualElmProxyType const& proxy, + messaging::MsgPtrThief msg, bool instrument = true + ); + + /** + * \brief Invoke message action member handler without going through scheduler + * + * \param[in] proxy the collection proxy + * \param[in] msg the message + * \param[in] instrument whether to instrument the broadcast for load + * balancing (some system calls use this to disable instrumentation) + */ + template < + typename MsgT, + ActiveColMemberTypedFnType f + > + void invokeMsg( + VirtualElmProxyType const& proxy, + messaging::MsgPtrThief msg, bool instrument = true + ); + + /** + * \internal \brief Invoke message handler without going through scheduler + * + * \param[in] proxy the collection proxy + * \param[in] msg the message with the virtual handler + * \param[in] instrument whether to instrument the broadcast for load + * balancing (some system calls use this to disable instrumentation) + */ + template + void invokeMsgImpl( + VirtualElmProxyType const& proxy, messaging::MsgPtrThief msg, + bool instrument + ); + /** * \brief Reduce over a collection * @@ -1994,6 +2041,7 @@ namespace details #include "vt/vrt/collection/send/sendable.impl.h" #include "vt/vrt/collection/gettable/gettable.impl.h" #include "vt/vrt/collection/reducable/reducable.impl.h" +#include "vt/vrt/collection/invoke/invokable.impl.h" #include "vt/vrt/collection/insert/insertable.impl.h" #include "vt/vrt/collection/insert/insert_finished.impl.h" #include "vt/vrt/collection/destroy/destroyable.impl.h" diff --git a/src/vt/vrt/collection/manager.impl.h b/src/vt/vrt/collection/manager.impl.h index fc366d1c9d..9a9de07c7c 100644 --- a/src/vt/vrt/collection/manager.impl.h +++ b/src/vt/vrt/collection/manager.impl.h @@ -776,6 +776,125 @@ template } } +template < + typename MsgT, ActiveColTypedFnType* f +> +void CollectionManager::invokeMsg( + VirtualElmProxyType const& proxy, + messaging::MsgPtrThief msg, bool instrument +) +{ + using ColT = typename MsgT::CollectionType; + + auto& msgPtr = msg.msg_; + msgPtr->setMember(false); + msgPtr->setVrtHandler( + auto_registry::makeAutoHandlerCollection() + ); + + invokeMsgImpl(proxy, msg, instrument); +} + +template < + typename MsgT, + ActiveColMemberTypedFnType f +> +void CollectionManager::invokeMsg( + VirtualElmProxyType const& proxy, + messaging::MsgPtrThief msg, bool instrument +) +{ + using ColT = typename MsgT::CollectionType; + + auto& msgPtr = msg.msg_; + msgPtr->setMember(true); + msgPtr->setVrtHandler( + auto_registry::makeAutoHandlerCollectionMem() + ); + + invokeMsgImpl(proxy, msg, instrument); +} + +template +void CollectionManager::invokeMsgImpl( + VirtualElmProxyType const& proxy, messaging::MsgPtrThief msg, + bool instrument +) +{ + using IndexT = typename ColT::IndexType; + auto& msgPtr = msg.msg_; + + auto idx = proxy.getElementProxy().getIndex(); + auto elm_holder = + theCollection()->findElmHolder(proxy.getCollectionProxy() + ); + + vtAssert(elm_holder != nullptr, "Must have elm holder"); + vtAssert( + elm_holder->exists(idx), + fmt::format( + "Element with idx:{} doesn't exist on node:{}\n", idx, + theContext()->getNode() + ) + ); + +#if vt_check_enabled(lblite) + auto const temp_elm_id = getCurrentContextTemp(); + auto const perm_elm_id = getCurrentContextPerm(); + + vt_debug_print( + vrt_coll, node, "invokeMsg: LB current elm context perm={}, temp={}\n", + perm_elm_id, temp_elm_id + ); + + if (perm_elm_id != balance::no_element_id) { + msgPtr->setElm(perm_elm_id, temp_elm_id); + } + msgPtr->setCat(balance::CommCategory::LocalInvoke); + +#endif + + auto const cur_epoch = theMsg()->setupEpochMsg(msgPtr); + auto& inner_holder = elm_holder->lookup(idx); + auto const col_ptr = inner_holder.getCollection(); + auto const from = theContext()->getNode(); + + msgPtr->setFromNode(from); + msgPtr->setProxy(proxy); + +#if vt_check_enabled(lblite) + if (instrument) { + col_ptr->getStats().startTime(); + } +#endif + + theMsg()->pushEpoch(cur_epoch); + + trace::TraceEventIDType trace_event = trace::no_trace_event; +#if vt_check_enabled(trace_enabled) + auto reg_type = msgPtr->getMember() ? + auto_registry::RegistryTypeEnum::RegVrtCollectionMember : + auto_registry::RegistryTypeEnum::RegVrtCollection; + auto msg_size = vt::serialization::MsgSizer::get(msgPtr.get()); + + trace_event = theMsg()->makeTraceCreationSend( + msgPtr, msgPtr->getVrtHandler(), reg_type, msg_size, true + ); +#endif + + collectionAutoMsgDeliver( + msgPtr.get(), col_ptr, msgPtr->getVrtHandler(), msgPtr->getMember(), from, + trace_event + ); + + theMsg()->popEpoch(cur_epoch); + +#if vt_check_enabled(lblite) + if (instrument) { + col_ptr->getStats().stopTime(); + } +#endif +} template /*static*/ void CollectionManager::collectionMsgHandler(BaseMessage* msg) { diff --git a/src/vt/vrt/collection/proxy_traits/proxy_elm_traits.h b/src/vt/vrt/collection/proxy_traits/proxy_elm_traits.h index adb2ae466a..728aec3d3b 100644 --- a/src/vt/vrt/collection/proxy_traits/proxy_elm_traits.h +++ b/src/vt/vrt/collection/proxy_traits/proxy_elm_traits.h @@ -49,6 +49,7 @@ #include "vt/vrt/proxy/base_collection_elm_proxy.h" #include "vt/vrt/proxy/base_elm_proxy.h" #include "vt/vrt/collection/send/sendable.h" +#include "vt/vrt/collection/invoke/invokable.h" #include "vt/vrt/collection/gettable/gettable.h" #include "vt/vrt/collection/insert/insertable.h" @@ -57,7 +58,10 @@ namespace vt { namespace vrt { namespace collection { namespace elm_proxy { template -using Chain3 = Gettable>; +using Chain4 = Invokable>; + +template +using Chain3 = Gettable>; template using Chain2 = ElmInsertable>; From 97999ad755b1401391b62717acebaa1d5af84867 Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Tue, 3 Nov 2020 16:31:48 +0100 Subject: [PATCH 02/18] #1051: objgroup: add invoke function for objgrp proxy which invokes given handler inline without going through scheduler --- src/vt/objgroup/manager.fwd.h | 2 ++ src/vt/objgroup/manager.h | 21 +++++++++++++++++++ src/vt/objgroup/manager.impl.h | 21 +++++++++++++++++++ src/vt/objgroup/manager.static.h | 15 +++++++++++++ src/vt/objgroup/proxy/proxy_objgroup_elm.h | 9 ++++++++ .../objgroup/proxy/proxy_objgroup_elm.impl.h | 9 ++++++++ src/vt/vrt/collection/manager.impl.h | 2 +- 7 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/vt/objgroup/manager.fwd.h b/src/vt/objgroup/manager.fwd.h index 82b419dd38..d4e947e075 100644 --- a/src/vt/objgroup/manager.fwd.h +++ b/src/vt/objgroup/manager.fwd.h @@ -57,6 +57,8 @@ void dispatchObjGroup(MsgSharedPtr msg, HandlerType han); template void send(MsgSharedPtr msg, HandlerType han, NodeType node); template +void invoke(messaging::MsgPtrThief msg, HandlerType han, NodeType node); +template void broadcast(MsgSharedPtr msg, HandlerType han); void scheduleMsg( MsgSharedPtr msg, HandlerType han, EpochType epoch diff --git a/src/vt/objgroup/manager.h b/src/vt/objgroup/manager.h index 914ef4428c..1ac6b4dbd7 100644 --- a/src/vt/objgroup/manager.h +++ b/src/vt/objgroup/manager.h @@ -215,6 +215,16 @@ struct ObjGroupManager : runtime::component::Component { template fn> void send(ProxyElmType proxy, MsgSharedPtr msg); + /** + * \internal \brief Invoke message handler on an element of the object group + * The message handler will be invoked inline without going through scheduler + * + * \param[in] proxy proxy to the object group + * \param[in] msg message + */ + template fn> + void invoke(ProxyElmType proxy, messaging::MsgPtrThief msg); + /** * \internal \brief Broadcast a message to all nodes in object group * @@ -316,6 +326,17 @@ struct ObjGroupManager : runtime::component::Component { template void send(MsgSharedPtr msg, HandlerType han, NodeType node); + /** + * \internal \brief Invoke a message handler on an objgroup + * The message handler will be invoked inline without going through scheduler + * + * \param[in] msg message + * \param[in] han handler to invoke + * \param[in] node node to invoke the handler on + */ + template + void invoke(messaging::MsgPtrThief msg, HandlerType han, NodeType node); + /** * \internal \brief Broadcast message to an objgroup * diff --git a/src/vt/objgroup/manager.impl.h b/src/vt/objgroup/manager.impl.h index 5f2f29504f..55787e8258 100644 --- a/src/vt/objgroup/manager.impl.h +++ b/src/vt/objgroup/manager.impl.h @@ -262,6 +262,20 @@ void ObjGroupManager::send(ProxyElmType proxy, MsgSharedPtr msg) { send(msg,han,dest_node); } +template fn> +void ObjGroupManager::invoke(ProxyElmType proxy, messaging::MsgPtrThief msg) { + auto const proxy_bits = proxy.getProxy(); + auto const dest_node = proxy.getNode(); + auto const ctrl = proxy::ObjGroupProxy::getID(proxy_bits); + auto const han = auto_registry::makeAutoHandlerObjGroup(ctrl); + vt_debug_print( + objgroup, node, + "ObjGroupManager::invoke: proxy={:x}, node={}, ctrl={:x}, han={:x}\n", + proxy_bits, dest_node, ctrl, han + ); + invoke(msg, han, dest_node); +} + template fn> void ObjGroupManager::broadcast(ProxyType proxy, MsgSharedPtr msg) { auto const proxy_bits = proxy.getProxy(); @@ -282,6 +296,13 @@ void ObjGroupManager::send( return objgroup::send(msg,han,dest_node); } +template +void ObjGroupManager::invoke( + messaging::MsgPtrThief msg, HandlerType han, NodeType dest_node +) { + objgroup::invoke(msg, han, dest_node); +} + template void ObjGroupManager::broadcast(MsgSharedPtr msg, HandlerType han) { return objgroup::broadcast(msg,han); diff --git a/src/vt/objgroup/manager.static.h b/src/vt/objgroup/manager.static.h index 95f0a9bc17..db5e2151ed 100644 --- a/src/vt/objgroup/manager.static.h +++ b/src/vt/objgroup/manager.static.h @@ -66,6 +66,21 @@ void send(MsgSharedPtr msg, HandlerType han, NodeType dest_node) { } } +template +void invoke(messaging::MsgPtrThief msg, HandlerType han, NodeType dest_node) { + auto const this_node = theContext()->getNode(); + + vtAssert( + dest_node == this_node, + fmt::format( + "Attempting to invoke handler on node:{} instead of node:{}!", this_node, + dest_node + ) + ); + + runnable::Runnable::run(han, nullptr, msg.msg_.get(), this_node); +} + template void broadcast(MsgSharedPtr msg, HandlerType han) { // Get the current epoch for the message diff --git a/src/vt/objgroup/proxy/proxy_objgroup_elm.h b/src/vt/objgroup/proxy/proxy_objgroup_elm.h index 4fefcc82e5..fb2a9e8c6b 100644 --- a/src/vt/objgroup/proxy/proxy_objgroup_elm.h +++ b/src/vt/objgroup/proxy/proxy_objgroup_elm.h @@ -127,6 +127,15 @@ struct ProxyElm { template fn, typename... Args> void send(Args&&... args) const; + /** + * \brief Invoke locally a message handler on the node/element indexed by this proxy. + * The message handler will be invoked inline without going through scheduler + * + * \param[in] args args to pass to the message constructor + */ + template fn, typename... Args> + void invoke(Args&&... args) const; + /** * \brief Update the local object instance pointer on this node. Must be run * on local node. diff --git a/src/vt/objgroup/proxy/proxy_objgroup_elm.impl.h b/src/vt/objgroup/proxy/proxy_objgroup_elm.impl.h index 1ca1641b29..f429cf7508 100644 --- a/src/vt/objgroup/proxy/proxy_objgroup_elm.impl.h +++ b/src/vt/objgroup/proxy/proxy_objgroup_elm.impl.h @@ -78,6 +78,15 @@ void ProxyElm::send(Args&&... args) const { return sendMsg(makeMessage(std::forward(args)...)); } +template +template fn, typename... Args> +void ProxyElm::invoke(Args&&... args) const { + auto proxy = ProxyElm(*this); + theObjGroup()->invoke( + proxy, makeMessage(std::forward(args)...) + ); +} + template template void ProxyElm::serialize(SerializerT& s) { diff --git a/src/vt/vrt/collection/manager.impl.h b/src/vt/vrt/collection/manager.impl.h index 9a9de07c7c..80d0d0b3f6 100644 --- a/src/vt/vrt/collection/manager.impl.h +++ b/src/vt/vrt/collection/manager.impl.h @@ -878,7 +878,7 @@ void CollectionManager::invokeMsgImpl( auto msg_size = vt::serialization::MsgSizer::get(msgPtr.get()); trace_event = theMsg()->makeTraceCreationSend( - msgPtr, msgPtr->getVrtHandler(), reg_type, msg_size, true + msgPtr, msgPtr->getVrtHandler(), reg_type, msg_size, false ); #endif From b836975cb6a66bcd0fa9c1654a05d93d5d74c894 Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Wed, 4 Nov 2020 19:06:46 +0100 Subject: [PATCH 03/18] #1051: vrt-collection: Add unittest for Vrt-Collection invoke --- tests/unit/collection/test_invoke.cc | 89 ++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 tests/unit/collection/test_invoke.cc diff --git a/tests/unit/collection/test_invoke.cc b/tests/unit/collection/test_invoke.cc new file mode 100644 index 0000000000..820c94a456 --- /dev/null +++ b/tests/unit/collection/test_invoke.cc @@ -0,0 +1,89 @@ +/* +//@HEADER +// ***************************************************************************** +// +// test_invoke.cc +// DARMA Toolkit v. 1.0.0 +// DARMA/vt => Virtual Transport +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#include + +#include "test_parallel_harness.h" +#include "test_collection_common.h" + +#include "vt/transport.h" + +namespace vt { namespace tests { namespace unit { namespace invoke { + +static bool handlerInvoked = false; + +template +struct TestMsg : CollectionMessage { + using IdxType = typename TestCol::IndexType; + + explicit TestMsg(IdxType indexVal) { + indexValue_ = indexVal; + } + + IdxType indexValue_ = IdxType{-1}; +}; + +struct TestCol : public Collection { + void MemberHandler(TestMsg* msg) { + handlerInvoked = true; + EXPECT_EQ(getIndex(), msg->indexValue_); + } +}; + +struct TestCollectionInvoke : TestParallelHarness {}; + +TEST_F(TestCollectionInvoke, test_collection_invoke_1) { + auto const& this_node = theContext()->getNode(); + auto const& num_nodes = theContext()->getNumNodes(); + auto const num_elems = Index1D{4}; + + auto proxy = theCollection()->constructCollective(num_elems); + + auto const destElem = Index1D{this_node + num_elems.x() / num_nodes - 1}; + proxy[destElem].invoke, &TestCol::MemberHandler>(destElem); + + EXPECT_EQ(handlerInvoked, true); +} + +}}}} // end namespace vt::tests::unit::invoke From baf591a1f880f784defaf94e86eb44ccc412b3cc Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Wed, 4 Nov 2020 20:41:20 +0100 Subject: [PATCH 04/18] #1051: objgroup: Add unittest for Objgroup proxy invoke --- tests/unit/objgroup/test_objgroup.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/unit/objgroup/test_objgroup.cc b/tests/unit/objgroup/test_objgroup.cc index 330203ce04..75aeaaaab6 100644 --- a/tests/unit/objgroup/test_objgroup.cc +++ b/tests/unit/objgroup/test_objgroup.cc @@ -271,4 +271,13 @@ TEST_F(TestObjGroup, test_proxy_reduce) { } } +TEST_F(TestObjGroup, test_proxy_invoke) { + auto const& this_node = theContext()->getNode(); + + auto proxy = vt::theObjGroup()->makeCollective(); + proxy[this_node].invoke(); + + EXPECT_EQ(proxy.get()->recv_, 1); +} + }}} // end namespace vt::tests::unit From d790d8058e50e99ad321db7cec2b2bda3d483132 Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Mon, 16 Nov 2020 18:39:08 +0100 Subject: [PATCH 05/18] #1051: runnable: Add invoke function which invokes and creates trace data for given Callable object. Works for C style functions, functors and member functions --- src/vt/runnable/invoke.h | 223 +++++++++++++++++++++++++++++++++ src/vt/trace/trace.cc | 14 +++ src/vt/trace/trace.h | 11 ++ src/vt/trace/trace_constants.h | 3 +- 4 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 src/vt/runnable/invoke.h diff --git a/src/vt/runnable/invoke.h b/src/vt/runnable/invoke.h new file mode 100644 index 0000000000..87ef872e8b --- /dev/null +++ b/src/vt/runnable/invoke.h @@ -0,0 +1,223 @@ +/* +//@HEADER +// ***************************************************************************** +// +// invoke.h +// DARMA Toolkit v. 1.0.0 +// DARMA/vt => Virtual Transport +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_RUNNABLE_INVOKE_H +#define INCLUDED_RUNNABLE_INVOKE_H + +#include "vt/config.h" +#include "vt/utils/demangle/demangle.h" + +#include + +namespace vt { namespace runnable { + +template +struct CallableWrapper; + +template +constexpr decltype(auto) CreatetEventTypeCStyleFunc() { + using TE = vt::util::demangle::TemplateExtract; + using DU = vt::util::demangle::DemanglerUtils; + + auto ns = TE::getNamespace(TE::getValueName()); + if (ns.empty()) + ns = "(none)"; + return DU::removeSpaces(ns); +} + +template +constexpr decltype(auto) CreatetEventTypeMemberFunc() { + using TE = vt::util::demangle::TemplateExtract; + using DU = vt::util::demangle::DemanglerUtils; + + auto typeName = TE::getTypeName(); + if (typeName.empty()) + typeName = "(none)"; + return DU::removeSpaces(typeName); +} + +template +constexpr decltype(auto) CreateEventName() { + using TE = vt::util::demangle::TemplateExtract; + using DU = vt::util::demangle::DemanglerUtils; + + std::vector arg_types = {TE::getTypeName()...}; + auto argsV = DU::join(",", arg_types); + auto valueName = TE::getValueName(); + auto barename = TE::getBarename(valueName); + return DU::removeSpaces(barename + "(" + argsV + ")"); +} + +template +struct CallableWrapper { + using ReturnType = Ret; + using Type = Ret(*)(Args...); + + static decltype(auto) GetTraceID() { + return trace::TraceRegistry::registerEventHashed( + CreatetEventTypeCStyleFunc(), + CreateEventName()); + } +}; + +template < + typename Ret, typename Class, typename... Args, Ret (Class::*f)(Args...) +> +struct CallableWrapper { + using ReturnType = Ret; + using Type = Ret (Class::*)(Args...); + + static decltype(auto) GetTraceID() { + return trace::TraceRegistry::registerEventHashed( + CreatetEventTypeMemberFunc(), CreateEventName() + ); + } +}; + +template +using IsVoidReturn = std::enable_if_t< + std::is_same< + typename CallableWrapper::ReturnType, void>::value, + void +>; + +template < + typename FunctionType, + typename Ret = typename CallableWrapper::ReturnType +> +using Copyable = std::enable_if_t< + !std::is_same::value && std::is_copy_constructible::value, + Ret +>; + +template < + typename FunctionType, + typename Ret = typename CallableWrapper::ReturnType +> +using NotCopyable = std::enable_if_t< + !std::is_same::value && !std::is_copy_constructible::value, + Ret +>; + +template +constexpr decltype(auto) BeginProcessingInvokeEvent() { + const auto trace_id = CallableWrapper::GetTraceID(); + const auto trace_event = theTrace()->localInvoke(trace_id); + const auto from_node = theContext()->getNode(); + + return theTrace()->beginProcessing(trace_id, 0, trace_event, from_node); +} + +template < + typename Fn, typename Type, typename T1, + typename std::enable_if_t>::value, int> = 0, + typename... Args +> +decltype(auto) invokeImpl(Type Fn::*f, T1&& obj, Args&&... args) { + return ((*std::forward(obj)).*f)(std::forward(args)...); +} + +template < + typename Fn, typename Type, typename T1, + typename std::enable_if_t>::value, int> = 0, + typename... Args +> +decltype(auto) invokeImpl(Type Fn::*f, T1&& obj, Args&&... args) { + return (std::forward(obj).*f)(std::forward(args)...); +} + +template +decltype(auto) invokeImpl(RetT (*f)(Args...), Args&&... args) { + return (*f)(std::forward(args)...); +} + +template +constexpr inline Copyable invoke(Args&&... args) { +#if vt_check_enabled(trace_enabled) + const auto processing_tag = + BeginProcessingInvokeEvent(); +#endif + + const auto& returnVal = invokeImpl(f, std::forward(args)...); + +#if vt_check_enabled(trace_enabled) + theTrace()->endProcessing(processing_tag); +#endif + + return returnVal; +} + +template +constexpr inline NotCopyable invoke(Args&&... args) { +#if vt_check_enabled(trace_enabled) + const auto processing_tag = + BeginProcessingInvokeEvent(); +#endif + + auto&& returnVal = invokeImpl(f, std::forward(args)...); + +#if vt_check_enabled(trace_enabled) + theTrace()->endProcessing(processing_tag); +#endif + + return std::move(returnVal); +} + +template +constexpr inline IsVoidReturn invoke(Args&&... args) { +#if vt_check_enabled(trace_enabled) + const auto processing_tag = + BeginProcessingInvokeEvent(); +#endif + + invokeImpl(f, std::forward(args)...); + +#if vt_check_enabled(trace_enabled) + theTrace()->endProcessing(processing_tag); +#endif +} + +}} // namespace vt::runnable + +#endif /*INCLUDED_RUNNABLE_INVOKE_H*/ \ No newline at end of file diff --git a/src/vt/trace/trace.cc b/src/vt/trace/trace.cc index af5f390527..0f0a65cd3e 100644 --- a/src/vt/trace/trace.cc +++ b/src/vt/trace/trace.cc @@ -635,6 +635,19 @@ void Trace::endIdle(double const time) { emitTraceForTopProcessingEvent(time, TraceConstantsType::BeginProcessing); } +TraceEventIDType +Trace::localInvoke(TraceEntryIDType const ep, double const time) { + if (not checkDynamicRuntimeEnabled()) { + return no_trace_event; + } + + auto const type = TraceConstantsType::LocalInvoke; + + NodeType const node = theContext()->getNode(); + + return logEvent(LogType{time, ep, type, node, 0}); +} + TraceEventIDType Trace::messageCreation( TraceEntryIDType const ep, TraceMsgLenType const len, double const time ) { @@ -757,6 +770,7 @@ TraceEventIDType Trace::logEvent(LogType&& log) { case TraceConstantsType::Creation: case TraceConstantsType::CreationBcast: case TraceConstantsType::MessageRecv: + case TraceConstantsType::LocalInvoke: log.event = cur_event_++; break; case TraceConstantsType::BeginIdle: diff --git a/src/vt/trace/trace.h b/src/vt/trace/trace.h index 1c29e2fef4..59084c5852 100644 --- a/src/vt/trace/trace.h +++ b/src/vt/trace/trace.h @@ -384,6 +384,17 @@ struct Trace : runtime::component::Component { double const time = getCurrentTime() ); + /** + * \brief Log a local function invoke + * + * \param[in] ep the registered function's event ID + * \param[in] time the time of the event + * + * \return the trace event ID + */ + TraceEventIDType + localInvoke(TraceEntryIDType const ep, double const time = getCurrentTime()); + /** * \brief Log a message send * diff --git a/src/vt/trace/trace_constants.h b/src/vt/trace/trace_constants.h index e76827df21..e8075aed20 100644 --- a/src/vt/trace/trace_constants.h +++ b/src/vt/trace/trace_constants.h @@ -83,7 +83,8 @@ enum class eTraceConstants : int32_t { UserStat = 32, BeginUserEventPair = 98, EndUserEventPair = 99, - UserEventPair = 100 + UserEventPair = 100, + LocalInvoke = 101 }; From 7e4fa4a61b1e53417bfe525e37bf26b9e6326f20 Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Mon, 16 Nov 2020 22:46:59 +0100 Subject: [PATCH 06/18] #1051: objgroup: Add non-msg invoke function for objgrp proxy. --- src/vt/objgroup/manager.h | 10 ++++++++++ src/vt/objgroup/manager.impl.h | 19 +++++++++++++++++++ src/vt/objgroup/proxy/proxy_objgroup_elm.h | 9 +++++++++ .../objgroup/proxy/proxy_objgroup_elm.impl.h | 11 +++++++++++ 4 files changed, 49 insertions(+) diff --git a/src/vt/objgroup/manager.h b/src/vt/objgroup/manager.h index 1ac6b4dbd7..eca158f173 100644 --- a/src/vt/objgroup/manager.h +++ b/src/vt/objgroup/manager.h @@ -225,6 +225,16 @@ struct ObjGroupManager : runtime::component::Component { template fn> void invoke(ProxyElmType proxy, messaging::MsgPtrThief msg); + /** + * \internal \brief Invoke function 'f' on an element of the object group + * The function will be invoked inline without going through scheduler + * + * \param[in] proxy proxy to the object group + * \param[in] args function arguments + */ + template + decltype(auto) invoke(ProxyElmType proxy, Args&&... args); + /** * \internal \brief Broadcast a message to all nodes in object group * diff --git a/src/vt/objgroup/manager.impl.h b/src/vt/objgroup/manager.impl.h index 55787e8258..c485da017c 100644 --- a/src/vt/objgroup/manager.impl.h +++ b/src/vt/objgroup/manager.impl.h @@ -58,6 +58,7 @@ #include "vt/registry/auto/auto_registry.h" #include "vt/collective/collective_alg.h" #include "vt/messaging/active.h" +#include "vt/runnable/invoke.h" #include @@ -276,6 +277,24 @@ void ObjGroupManager::invoke(ProxyElmType proxy, messaging::MsgPtrThief(msg, han, dest_node); } +template +decltype(auto) +ObjGroupManager::invoke(ProxyElmType proxy, Args&&... args) { + auto const proxy_bits = proxy.getProxy(); + auto const dest_node = proxy.getNode(); + auto const this_node = theContext()->getNode(); + auto const ctrl = proxy::ObjGroupProxy::getID(proxy_bits); + + vtAssert( + dest_node == this_node, + fmt::format( + "Attempting to invoke handler on node:{} instead of node:{}!", this_node, + dest_node)); + + return runnable::invoke(get(proxy), std::forward(args)...); +} + + template fn> void ObjGroupManager::broadcast(ProxyType proxy, MsgSharedPtr msg) { auto const proxy_bits = proxy.getProxy(); diff --git a/src/vt/objgroup/proxy/proxy_objgroup_elm.h b/src/vt/objgroup/proxy/proxy_objgroup_elm.h index fb2a9e8c6b..a8b54ad504 100644 --- a/src/vt/objgroup/proxy/proxy_objgroup_elm.h +++ b/src/vt/objgroup/proxy/proxy_objgroup_elm.h @@ -136,6 +136,15 @@ struct ProxyElm { template fn, typename... Args> void invoke(Args&&... args) const; + /** + * \brief Invoke locally a function 'f' on the node/element indexed by this proxy. + * The function will be invoked inline without going through scheduler + * + * \param[in] args function arguments + */ + template + decltype(auto) invoke(Args&&... args) const; + /** * \brief Update the local object instance pointer on this node. Must be run * on local node. diff --git a/src/vt/objgroup/proxy/proxy_objgroup_elm.impl.h b/src/vt/objgroup/proxy/proxy_objgroup_elm.impl.h index f429cf7508..8267ddf13d 100644 --- a/src/vt/objgroup/proxy/proxy_objgroup_elm.impl.h +++ b/src/vt/objgroup/proxy/proxy_objgroup_elm.impl.h @@ -87,6 +87,17 @@ void ProxyElm::invoke(Args&&... args) const { ); } +template +template +decltype(auto) ProxyElm::invoke( + Args&&... args +) const +{ + auto proxy = ProxyElm(*this); + return theObjGroup()->invoke( + proxy, std::forward(args)...); +} + template template void ProxyElm::serialize(SerializerT& s) { From 798dea18f6c9439033da87714458528704ee55da Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Tue, 17 Nov 2020 00:46:33 +0100 Subject: [PATCH 07/18] #1051: vrt-collection: Add non-msg invoke function for vrt-collection proxy. --- src/vt/vrt/collection/invoke/invokable.h | 3 + src/vt/vrt/collection/invoke/invokable.impl.h | 12 ++ src/vt/vrt/collection/manager.h | 34 +++++ src/vt/vrt/collection/manager.impl.h | 126 +++++++++++++++++- 4 files changed, 169 insertions(+), 6 deletions(-) diff --git a/src/vt/vrt/collection/invoke/invokable.h b/src/vt/vrt/collection/invoke/invokable.h index 8573c7d4dd..b38d76d1f4 100644 --- a/src/vt/vrt/collection/invoke/invokable.h +++ b/src/vt/vrt/collection/invoke/invokable.h @@ -68,6 +68,9 @@ struct Invokable : BaseProxyT { typename... Args > void invoke(Args&&... args) const; + + template + decltype(auto) invoke(Args&&... args) const; }; }}} /* end namespace vt::vrt::collection */ diff --git a/src/vt/vrt/collection/invoke/invokable.impl.h b/src/vt/vrt/collection/invoke/invokable.impl.h index 9058dfe941..774f4a98fb 100644 --- a/src/vt/vrt/collection/invoke/invokable.impl.h +++ b/src/vt/vrt/collection/invoke/invokable.impl.h @@ -86,6 +86,18 @@ void Invokable::invoke(Args&&... args) const theCollection()->invokeMsg(proxy, msg); } +template +template +decltype(auto) +Invokable::invoke(Args&&... args) const { + auto const& proxy = VrtElmProxy( + this->getCollectionProxy(), this->getElementProxy()); + + return theCollection()->invoke( + proxy, std::forward(args)... + ); +} + }}} /* end namespace vt::vrt::collection */ #endif /*INCLUDED_VRT_COLLECTION_INVOKE_INVOKABLE_IMPL_H*/ diff --git a/src/vt/vrt/collection/manager.h b/src/vt/vrt/collection/manager.h index df18d72549..af42091350 100644 --- a/src/vt/vrt/collection/manager.h +++ b/src/vt/vrt/collection/manager.h @@ -76,6 +76,7 @@ #include "vt/vrt/collection/balance/lb_common.h" #include "vt/runtime/component/component_pack.h" #include "vt/vrt/collection/op_buffer.h" +#include "vt/runnable/invoke.h" #include #include @@ -791,6 +792,39 @@ struct CollectionManager template static void recordStats(ColT* col_ptr, MsgT* msg); + /** + * \brief Invoke function 'f' (with copyable return type) inline without going + * through scheduler + * + * \param[in] proxy the collection proxy + * \param[in] args function params + */ + template + runnable::Copyable + invoke(VirtualElmProxyType const& proxy, Args... args); + + /** + * \brief Invoke function 'f' (with non-copyable return type) inline without + * going through scheduler + * + * \param[in] proxy the collection proxy + * \param[in] args function params + */ + template + runnable::NotCopyable + invoke(VirtualElmProxyType const& proxy, Args... args); + + /** + * \brief Invoke function 'f' (with void return type) inline without going + * through scheduler + * + * \param[in] proxy the collection proxy + * \param[in] args function params + */ + template + runnable::IsVoidReturn + invoke(VirtualElmProxyType const& proxy, Args... args); + /** * \brief Invoke message action function handler without going through scheduler * diff --git a/src/vt/vrt/collection/manager.impl.h b/src/vt/vrt/collection/manager.impl.h index 80d0d0b3f6..573fce4965 100644 --- a/src/vt/vrt/collection/manager.impl.h +++ b/src/vt/vrt/collection/manager.impl.h @@ -79,6 +79,7 @@ #include "vt/serialization/sizer.h" #include "vt/collective/reduce/reduce_hash.h" #include "vt/runnable/collection.h" +#include "vt/runnable/invoke.h" #include "vt/group/group_headers.h" #include "vt/pipe/pipe_headers.h" #include "vt/scheduler/scheduler.h" @@ -776,6 +777,119 @@ template } } +template +runnable::Copyable CollectionManager::invoke( + VirtualElmProxyType const& proxy, Args... args +) { + using IndexT = typename ColT::IndexType; + + auto idx = proxy.getElementProxy().getIndex(); + auto elm_holder = + theCollection()->findElmHolder(proxy.getCollectionProxy()); + + vtAssert(elm_holder != nullptr, "Must have elm holder"); + vtAssert( + elm_holder->exists(idx), + fmt::format( + "Element with idx:{} doesn't exist on node:{}\n", idx, + theContext()->getNode())); + + auto& inner_holder = elm_holder->lookup(idx); + auto const col_ptr = inner_holder.getCollection(); + void* raw_ptr = static_cast(col_ptr); + auto ptr = reinterpret_cast(raw_ptr); + + auto const col_proxy = col_ptr->getProxy(); + InsertContextHolder::set(&idx, col_proxy); + +#if vt_check_enabled(lblite) + col_ptr->getStats().startTime(); +#endif + + const auto& result = + runnable::invoke(ptr, std::forward(args)...); + +#if vt_check_enabled(lblite) + col_ptr->getStats().stopTime(); +#endif + + return result; +} + +template +runnable::NotCopyable CollectionManager::invoke( + VirtualElmProxyType const& proxy, Args... args +) { + using IndexT = typename ColT::IndexType; + + auto idx = proxy.getElementProxy().getIndex(); + auto elm_holder = + theCollection()->findElmHolder(proxy.getCollectionProxy()); + + vtAssert(elm_holder != nullptr, "Must have elm holder"); + vtAssert( + elm_holder->exists(idx), + fmt::format( + "Element with idx:{} doesn't exist on node:{}\n", idx, + theContext()->getNode())); + + auto& inner_holder = elm_holder->lookup(idx); + auto const col_ptr = inner_holder.getCollection(); + void* raw_ptr = static_cast(col_ptr); + auto ptr = reinterpret_cast(raw_ptr); + + auto const col_proxy = col_ptr->getProxy(); + InsertContextHolder::set(&idx, col_proxy); + +#if vt_check_enabled(lblite) + col_ptr->getStats().startTime(); +#endif + + auto&& result = runnable::invoke(ptr, std::forward(args)...); + +#if vt_check_enabled(lblite) + col_ptr->getStats().stopTime(); +#endif + + return std::move(result); +} + +template +runnable::IsVoidReturn CollectionManager::invoke( + VirtualElmProxyType const& proxy, Args... args +) { + using IndexT = typename ColT::IndexType; + + auto idx = proxy.getElementProxy().getIndex(); + auto elm_holder = + theCollection()->findElmHolder(proxy.getCollectionProxy()); + + vtAssert(elm_holder != nullptr, "Must have elm holder"); + vtAssert( + elm_holder->exists(idx), + fmt::format( + "Element with idx:{} doesn't exist on node:{}\n", idx, + theContext()->getNode())); + + auto& inner_holder = elm_holder->lookup(idx); + auto const col_ptr = inner_holder.getCollection(); + void* raw_ptr = static_cast(col_ptr); + auto ptr = reinterpret_cast(raw_ptr); + + auto const col_proxy = col_ptr->getProxy(); + InsertContextHolder::set(&idx, col_proxy); + +#if vt_check_enabled(lblite) + col_ptr->getStats().startTime(); +#endif + + runnable::invoke(ptr, std::forward(args)...); + +#if vt_check_enabled(lblite) + col_ptr->getStats().stopTime(); +#endif +} + template < typename MsgT, ActiveColTypedFnType* f > @@ -787,7 +901,6 @@ void CollectionManager::invokeMsg( using ColT = typename MsgT::CollectionType; auto& msgPtr = msg.msg_; - msgPtr->setMember(false); msgPtr->setVrtHandler( auto_registry::makeAutoHandlerCollection() ); @@ -807,7 +920,6 @@ void CollectionManager::invokeMsg( using ColT = typename MsgT::CollectionType; auto& msgPtr = msg.msg_; - msgPtr->setMember(true); msgPtr->setVrtHandler( auto_registry::makeAutoHandlerCollectionMem() ); @@ -870,21 +982,23 @@ void CollectionManager::invokeMsgImpl( theMsg()->pushEpoch(cur_epoch); + auto const han = msgPtr->getVrtHandler(); + trace::TraceEventIDType trace_event = trace::no_trace_event; #if vt_check_enabled(trace_enabled) - auto reg_type = msgPtr->getMember() ? + + auto reg_type = HandlerManager::isHandlerMember(han) ? auto_registry::RegistryTypeEnum::RegVrtCollectionMember : auto_registry::RegistryTypeEnum::RegVrtCollection; auto msg_size = vt::serialization::MsgSizer::get(msgPtr.get()); trace_event = theMsg()->makeTraceCreationSend( - msgPtr, msgPtr->getVrtHandler(), reg_type, msg_size, false + msgPtr, han, reg_type, msg_size, false ); #endif collectionAutoMsgDeliver( - msgPtr.get(), col_ptr, msgPtr->getVrtHandler(), msgPtr->getMember(), from, - trace_event + msgPtr.get(), col_ptr, han, from, trace_event ); theMsg()->popEpoch(cur_epoch); From d6b793babf9ebddffde79e4d5dc6960c92d9671a Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Tue, 17 Nov 2020 01:07:19 +0100 Subject: [PATCH 08/18] #1051: runnable: Fix issue with incorrectly generated Trace name for invoke's Callable --- src/vt/runnable/invoke.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/vt/runnable/invoke.h b/src/vt/runnable/invoke.h index 87ef872e8b..7588d92495 100644 --- a/src/vt/runnable/invoke.h +++ b/src/vt/runnable/invoke.h @@ -56,35 +56,35 @@ template struct CallableWrapper; template -constexpr decltype(auto) CreatetEventTypeCStyleFunc() { +static decltype(auto) CreatetEventTypeCStyleFunc() { using TE = vt::util::demangle::TemplateExtract; using DU = vt::util::demangle::DemanglerUtils; - auto ns = TE::getNamespace(TE::getValueName()); + auto ns = TE::getNamespace(TE::getValueName, f>()); if (ns.empty()) ns = "(none)"; return DU::removeSpaces(ns); } template -constexpr decltype(auto) CreatetEventTypeMemberFunc() { +static decltype(auto) CreatetEventTypeMemberFunc() { using TE = vt::util::demangle::TemplateExtract; using DU = vt::util::demangle::DemanglerUtils; - auto typeName = TE::getTypeName(); + auto typeName = TE::getTypeName>(); if (typeName.empty()) typeName = "(none)"; return DU::removeSpaces(typeName); } template -constexpr decltype(auto) CreateEventName() { +static decltype(auto) CreateEventName() { using TE = vt::util::demangle::TemplateExtract; using DU = vt::util::demangle::DemanglerUtils; std::vector arg_types = {TE::getTypeName()...}; auto argsV = DU::join(",", arg_types); - auto valueName = TE::getValueName(); + auto valueName = TE::lastNamedPfType(TE::prettyFunctionForValue(), "T"); auto barename = TE::getBarename(valueName); return DU::removeSpaces(barename + "(" + argsV + ")"); } @@ -97,7 +97,7 @@ struct CallableWrapper { static decltype(auto) GetTraceID() { return trace::TraceRegistry::registerEventHashed( CreatetEventTypeCStyleFunc(), - CreateEventName()); + CreateEventName()); } }; @@ -110,7 +110,7 @@ struct CallableWrapper { static decltype(auto) GetTraceID() { return trace::TraceRegistry::registerEventHashed( - CreatetEventTypeMemberFunc(), CreateEventName() + CreatetEventTypeMemberFunc(), CreateEventName() ); } }; @@ -140,14 +140,16 @@ using NotCopyable = std::enable_if_t< Ret >; +#if vt_check_enabled(trace_enabled) template -constexpr decltype(auto) BeginProcessingInvokeEvent() { +static decltype(auto) BeginProcessingInvokeEvent() { const auto trace_id = CallableWrapper::GetTraceID(); const auto trace_event = theTrace()->localInvoke(trace_id); const auto from_node = theContext()->getNode(); return theTrace()->beginProcessing(trace_id, 0, trace_event, from_node); } +#endif template < typename Fn, typename Type, typename T1, @@ -173,7 +175,7 @@ decltype(auto) invokeImpl(RetT (*f)(Args...), Args&&... args) { } template -constexpr inline Copyable invoke(Args&&... args) { +Copyable invoke(Args&&... args) { #if vt_check_enabled(trace_enabled) const auto processing_tag = BeginProcessingInvokeEvent(); @@ -189,7 +191,7 @@ constexpr inline Copyable invoke(Args&&... args) { } template -constexpr inline NotCopyable invoke(Args&&... args) { +NotCopyable invoke(Args&&... args) { #if vt_check_enabled(trace_enabled) const auto processing_tag = BeginProcessingInvokeEvent(); @@ -205,7 +207,7 @@ constexpr inline NotCopyable invoke(Args&&... args) { } template -constexpr inline IsVoidReturn invoke(Args&&... args) { +IsVoidReturn invoke(Args&&... args) { #if vt_check_enabled(trace_enabled) const auto processing_tag = BeginProcessingInvokeEvent(); From 1b43d37cca9baf0af74f55c3a9f3b888001a0dca Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Fri, 20 Nov 2020 14:56:07 +0100 Subject: [PATCH 09/18] #1051: runnable: Use explicit return time for invoke.h function when possible --- src/vt/runnable/invoke.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vt/runnable/invoke.h b/src/vt/runnable/invoke.h index 7588d92495..192982d7a7 100644 --- a/src/vt/runnable/invoke.h +++ b/src/vt/runnable/invoke.h @@ -56,7 +56,7 @@ template struct CallableWrapper; template -static decltype(auto) CreatetEventTypeCStyleFunc() { +static std::string CreatetEventTypeCStyleFunc() { using TE = vt::util::demangle::TemplateExtract; using DU = vt::util::demangle::DemanglerUtils; @@ -67,7 +67,7 @@ static decltype(auto) CreatetEventTypeCStyleFunc() { } template -static decltype(auto) CreatetEventTypeMemberFunc() { +static std::string CreatetEventTypeMemberFunc() { using TE = vt::util::demangle::TemplateExtract; using DU = vt::util::demangle::DemanglerUtils; @@ -78,7 +78,7 @@ static decltype(auto) CreatetEventTypeMemberFunc() { } template -static decltype(auto) CreateEventName() { +static std::string CreateEventName() { using TE = vt::util::demangle::TemplateExtract; using DU = vt::util::demangle::DemanglerUtils; @@ -94,7 +94,7 @@ struct CallableWrapper { using ReturnType = Ret; using Type = Ret(*)(Args...); - static decltype(auto) GetTraceID() { + static trace::TraceEntryIDType GetTraceID() { return trace::TraceRegistry::registerEventHashed( CreatetEventTypeCStyleFunc(), CreateEventName()); @@ -108,7 +108,7 @@ struct CallableWrapper { using ReturnType = Ret; using Type = Ret (Class::*)(Args...); - static decltype(auto) GetTraceID() { + static trace::TraceEntryIDType GetTraceID() { return trace::TraceRegistry::registerEventHashed( CreatetEventTypeMemberFunc(), CreateEventName() ); @@ -142,7 +142,7 @@ using NotCopyable = std::enable_if_t< #if vt_check_enabled(trace_enabled) template -static decltype(auto) BeginProcessingInvokeEvent() { +static trace::TraceProcessingTag BeginProcessingInvokeEvent() { const auto trace_id = CallableWrapper::GetTraceID(); const auto trace_event = theTrace()->localInvoke(trace_id); const auto from_node = theContext()->getNode(); @@ -170,7 +170,7 @@ decltype(auto) invokeImpl(Type Fn::*f, T1&& obj, Args&&... args) { } template -decltype(auto) invokeImpl(RetT (*f)(Args...), Args&&... args) { +RetT invokeImpl(RetT (*f)(Args...), Args&&... args) { return (*f)(std::forward(args)...); } From e937a1579f46f3b0849f9a2e3d680ab5d08cd81b Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Fri, 20 Nov 2020 14:57:05 +0100 Subject: [PATCH 10/18] #1051: vrt-collection: Cleanup invoke related code in vrt-collection --- src/vt/vrt/collection/manager.h | 11 ++++ src/vt/vrt/collection/manager.impl.h | 75 +++++++--------------------- 2 files changed, 30 insertions(+), 56 deletions(-) diff --git a/src/vt/vrt/collection/manager.h b/src/vt/vrt/collection/manager.h index af42091350..c71bf87eec 100644 --- a/src/vt/vrt/collection/manager.h +++ b/src/vt/vrt/collection/manager.h @@ -1446,6 +1446,17 @@ struct CollectionManager ); private: + + /** + * \internal \brief Get the collection element pointer for given proxy + * + * \param[in] proxy the collection proxy + * + * \return the collection element pointer + */ + template + ColT* getCollectionPtrForInvoke(VirtualElmProxyType const& proxy); + /** * \internal \brief Get the entire collection system holder * diff --git a/src/vt/vrt/collection/manager.impl.h b/src/vt/vrt/collection/manager.impl.h index 573fce4965..283810fe8a 100644 --- a/src/vt/vrt/collection/manager.impl.h +++ b/src/vt/vrt/collection/manager.impl.h @@ -777,12 +777,10 @@ template } } -template -runnable::Copyable CollectionManager::invoke( - VirtualElmProxyType const& proxy, Args... args +template +ColT* CollectionManager::getCollectionPtrForInvoke( + VirtualElmProxyType const& proxy ) { - using IndexT = typename ColT::IndexType; - auto idx = proxy.getElementProxy().getIndex(); auto elm_holder = theCollection()->findElmHolder(proxy.getCollectionProxy()); @@ -795,22 +793,25 @@ runnable::Copyable CollectionManager::invoke( theContext()->getNode())); auto& inner_holder = elm_holder->lookup(idx); - auto const col_ptr = inner_holder.getCollection(); - void* raw_ptr = static_cast(col_ptr); - auto ptr = reinterpret_cast(raw_ptr); - auto const col_proxy = col_ptr->getProxy(); - InsertContextHolder::set(&idx, col_proxy); + return static_cast(inner_holder.getCollection()); +} + +template +runnable::Copyable CollectionManager::invoke( + VirtualElmProxyType const& proxy, Args... args +) { + auto ptr = getCollectionPtrForInvoke(proxy); #if vt_check_enabled(lblite) - col_ptr->getStats().startTime(); + ptr->getStats().startTime(); #endif const auto& result = runnable::invoke(ptr, std::forward(args)...); #if vt_check_enabled(lblite) - col_ptr->getStats().stopTime(); + ptr->getStats().stopTime(); #endif return result; @@ -820,35 +821,16 @@ template runnable::NotCopyable CollectionManager::invoke( VirtualElmProxyType const& proxy, Args... args ) { - using IndexT = typename ColT::IndexType; - - auto idx = proxy.getElementProxy().getIndex(); - auto elm_holder = - theCollection()->findElmHolder(proxy.getCollectionProxy()); - - vtAssert(elm_holder != nullptr, "Must have elm holder"); - vtAssert( - elm_holder->exists(idx), - fmt::format( - "Element with idx:{} doesn't exist on node:{}\n", idx, - theContext()->getNode())); - - auto& inner_holder = elm_holder->lookup(idx); - auto const col_ptr = inner_holder.getCollection(); - void* raw_ptr = static_cast(col_ptr); - auto ptr = reinterpret_cast(raw_ptr); - - auto const col_proxy = col_ptr->getProxy(); - InsertContextHolder::set(&idx, col_proxy); + auto ptr = getCollectionPtrForInvoke(proxy); #if vt_check_enabled(lblite) - col_ptr->getStats().startTime(); + ptr->getStats().startTime(); #endif auto&& result = runnable::invoke(ptr, std::forward(args)...); #if vt_check_enabled(lblite) - col_ptr->getStats().stopTime(); + ptr->getStats().stopTime(); #endif return std::move(result); @@ -858,35 +840,16 @@ template runnable::IsVoidReturn CollectionManager::invoke( VirtualElmProxyType const& proxy, Args... args ) { - using IndexT = typename ColT::IndexType; - - auto idx = proxy.getElementProxy().getIndex(); - auto elm_holder = - theCollection()->findElmHolder(proxy.getCollectionProxy()); - - vtAssert(elm_holder != nullptr, "Must have elm holder"); - vtAssert( - elm_holder->exists(idx), - fmt::format( - "Element with idx:{} doesn't exist on node:{}\n", idx, - theContext()->getNode())); - - auto& inner_holder = elm_holder->lookup(idx); - auto const col_ptr = inner_holder.getCollection(); - void* raw_ptr = static_cast(col_ptr); - auto ptr = reinterpret_cast(raw_ptr); - - auto const col_proxy = col_ptr->getProxy(); - InsertContextHolder::set(&idx, col_proxy); + auto ptr = getCollectionPtrForInvoke(proxy); #if vt_check_enabled(lblite) - col_ptr->getStats().startTime(); + ptr->getStats().startTime(); #endif runnable::invoke(ptr, std::forward(args)...); #if vt_check_enabled(lblite) - col_ptr->getStats().stopTime(); + ptr->getStats().stopTime(); #endif } From 6d5139373374161401f2b52c7a10261ee04a4856 Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Sat, 21 Nov 2020 00:06:33 +0100 Subject: [PATCH 11/18] #1051: runnable: Extract functions for trace names generation used in invoke function --- src/vt/runnable/invoke.h | 41 ++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/vt/runnable/invoke.h b/src/vt/runnable/invoke.h index 192982d7a7..10474bd645 100644 --- a/src/vt/runnable/invoke.h +++ b/src/vt/runnable/invoke.h @@ -52,9 +52,6 @@ namespace vt { namespace runnable { -template -struct CallableWrapper; - template static std::string CreatetEventTypeCStyleFunc() { using TE = vt::util::demangle::TemplateExtract; @@ -63,6 +60,7 @@ static std::string CreatetEventTypeCStyleFunc() { auto ns = TE::getNamespace(TE::getValueName, f>()); if (ns.empty()) ns = "(none)"; + return DU::removeSpaces(ns); } @@ -74,6 +72,7 @@ static std::string CreatetEventTypeMemberFunc() { auto typeName = TE::getTypeName>(); if (typeName.empty()) typeName = "(none)"; + return DU::removeSpaces(typeName); } @@ -84,20 +83,34 @@ static std::string CreateEventName() { std::vector arg_types = {TE::getTypeName()...}; auto argsV = DU::join(",", arg_types); - auto valueName = TE::lastNamedPfType(TE::prettyFunctionForValue(), "T"); + auto valueName = + TE::lastNamedPfType(TE::prettyFunctionForValue(), "T" + ); auto barename = TE::getBarename(valueName); + return DU::removeSpaces(barename + "(" + argsV + ")"); } +template +struct CallableWrapper; + template struct CallableWrapper { using ReturnType = Ret; using Type = Ret(*)(Args...); + static std::string GetEventTypeName() { + return CreatetEventTypeCStyleFunc(); + } + + static std::string GetEventName() { + return CreateEventName(); + } + static trace::TraceEntryIDType GetTraceID() { return trace::TraceRegistry::registerEventHashed( - CreatetEventTypeCStyleFunc(), - CreateEventName()); + GetEventTypeName(), GetEventName() + ); } }; @@ -108,9 +121,17 @@ struct CallableWrapper { using ReturnType = Ret; using Type = Ret (Class::*)(Args...); + static std::string GetEventTypeName() { + return CreatetEventTypeMemberFunc(); + } + + static std::string GetEventName() { + return CreateEventName(); + } + static trace::TraceEntryIDType GetTraceID() { return trace::TraceRegistry::registerEventHashed( - CreatetEventTypeMemberFunc(), CreateEventName() + GetEventTypeName(), GetEventName() ); } }; @@ -169,9 +190,9 @@ decltype(auto) invokeImpl(Type Fn::*f, T1&& obj, Args&&... args) { return (std::forward(obj).*f)(std::forward(args)...); } -template -RetT invokeImpl(RetT (*f)(Args...), Args&&... args) { - return (*f)(std::forward(args)...); +template +decltype(auto) invokeImpl(Callable&& f, Args&&... args) { + return std::forward(f)(std::forward(args)...); } template From 20c78cccc23276d91faff9c1a0c9310eac54af6f Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Sat, 21 Nov 2020 00:07:50 +0100 Subject: [PATCH 12/18] #1051: runnable: Add more unittests for invoke function --- tests/unit/collection/test_invoke.cc | 51 ++++++++--- tests/unit/objgroup/test_objgroup.cc | 12 +++ tests/unit/objgroup/test_objgroup_common.h | 8 ++ tests/unit/runnable/test_invoke.cc | 102 +++++++++++++++++++++ 4 files changed, 161 insertions(+), 12 deletions(-) create mode 100644 tests/unit/runnable/test_invoke.cc diff --git a/tests/unit/collection/test_invoke.cc b/tests/unit/collection/test_invoke.cc index 820c94a456..48d26fb2f1 100644 --- a/tests/unit/collection/test_invoke.cc +++ b/tests/unit/collection/test_invoke.cc @@ -42,32 +42,40 @@ //@HEADER */ -#include - #include "test_parallel_harness.h" #include "test_collection_common.h" #include "vt/transport.h" +#include +#include + namespace vt { namespace tests { namespace unit { namespace invoke { -static bool handlerInvoked = false; +static bool handler_invoked = false; template struct TestMsg : CollectionMessage { using IdxType = typename TestCol::IndexType; - explicit TestMsg(IdxType indexVal) { - indexValue_ = indexVal; + explicit TestMsg(IdxType index_value) { + index_value_ = index_value; } - IdxType indexValue_ = IdxType{-1}; + IdxType index_value_ = IdxType{-1}; }; struct TestCol : public Collection { - void MemberHandler(TestMsg* msg) { - handlerInvoked = true; - EXPECT_EQ(getIndex(), msg->indexValue_); + void memberHandler(TestMsg* msg) { + handler_invoked = true; + EXPECT_EQ(getIndex(), msg->index_value_); + } + + int accumulateVec(IndexType idx, const std::vector& vec) { + handler_invoked = true; + EXPECT_EQ(getIndex(), idx); + + return std::accumulate(std::begin(vec), std::end(vec), 0); } }; @@ -80,10 +88,29 @@ TEST_F(TestCollectionInvoke, test_collection_invoke_1) { auto proxy = theCollection()->constructCollective(num_elems); - auto const destElem = Index1D{this_node + num_elems.x() / num_nodes - 1}; - proxy[destElem].invoke, &TestCol::MemberHandler>(destElem); + auto const dest_elem = Index1D{this_node + num_elems.x() / num_nodes - 1}; - EXPECT_EQ(handlerInvoked, true); + // Message handler + { + proxy[dest_elem].invoke, &TestCol::memberHandler>( + dest_elem); + + EXPECT_EQ(handler_invoked, true); + + handler_invoked = false; + } + + // Non-message function + { + auto const accumulate_result = + proxy[dest_elem] + .invoke( + dest_elem, std::vector{2, 4, 5} + ); + + EXPECT_EQ(accumulate_result, 11); + EXPECT_EQ(handler_invoked, true); + } } }}}} // end namespace vt::tests::unit::invoke diff --git a/tests/unit/objgroup/test_objgroup.cc b/tests/unit/objgroup/test_objgroup.cc index 75aeaaaab6..d4a1452288 100644 --- a/tests/unit/objgroup/test_objgroup.cc +++ b/tests/unit/objgroup/test_objgroup.cc @@ -275,9 +275,21 @@ TEST_F(TestObjGroup, test_proxy_invoke) { auto const& this_node = theContext()->getNode(); auto proxy = vt::theObjGroup()->makeCollective(); + + + // Message handler proxy[this_node].invoke(); EXPECT_EQ(proxy.get()->recv_, 1); + + // Non-message function + auto const accumulate_result = + proxy[this_node] + .invoke( + std::vector{2, 4, 5}); + + EXPECT_EQ(accumulate_result, 11); + EXPECT_EQ(proxy.get()->recv_, 2); } }}} // end namespace vt::tests::unit diff --git a/tests/unit/objgroup/test_objgroup_common.h b/tests/unit/objgroup/test_objgroup_common.h index 4fadc2ed7b..b11929f39d 100644 --- a/tests/unit/objgroup/test_objgroup_common.h +++ b/tests/unit/objgroup/test_objgroup_common.h @@ -45,6 +45,8 @@ #include "test_parallel_harness.h" #include "vt/transport.h" +#include + #if !defined INCLUDED_TEST_OBJGROUP_COMMON_H #define INCLUDED_TEST_OBJGROUP_COMMON_H @@ -81,6 +83,12 @@ struct MyObjA { recv_++; } + int accumulateVec(const std::vector& vec) { + recv_++; + + return std::accumulate(std::begin(vec), std::end(vec), 0); + } + int id_ = -1; int recv_ = 0; static int next_id; diff --git a/tests/unit/runnable/test_invoke.cc b/tests/unit/runnable/test_invoke.cc new file mode 100644 index 0000000000..94440faa1b --- /dev/null +++ b/tests/unit/runnable/test_invoke.cc @@ -0,0 +1,102 @@ +/* +//@HEADER +// ***************************************************************************** +// +// test_invoke.cc +// DARMA Toolkit v. 1.0.0 +// DARMA/vt => Virtual Transport +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#include "test_parallel_harness.h" +#include "vt/runnable/invoke.h" +#include + +#include +#include +#include + +namespace vt { namespace tests { namespace unit { + +struct TestInvoke : TestParallelHarness { + virtual void addAdditionalArgs() override { + static char traceon[]{"--vt_trace=1"}; + addArgs(traceon); + } +}; + +static int test_value = -1; + +struct A { + virtual ~A() = default; + + virtual int memberFunc(const std::vector& vec) = 0; +}; + +struct B : A { + ~B() override = default; + + int memberFunc(const std::vector& vec) override { + test_value = 30; + return std::accumulate(std::begin(vec), std::end(vec), 0); + } +}; + +void voidWithArg(int in_val) { test_value = in_val; } + +std::unique_ptr nonCopyableFun() { + test_value = 20; + return std::make_unique(); +} + +TEST_F(TestInvoke, test_invoke_call) { + vt::runnable::invoke(10); + EXPECT_EQ(test_value, 10); + + auto b = vt::runnable::invoke(); + EXPECT_EQ(test_value, 20); + + auto accumulate_result = + vt::runnable::invoke( + b.get(), std::vector{10, 20, 30} + ); + EXPECT_EQ(accumulate_result, 60); + EXPECT_EQ(test_value, 30); +} + + +}}} // end namespace vt::tests::unit From db4ce8b740cef2b4a95548485fd3dce2359e7f6d Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Sun, 22 Nov 2020 20:00:13 +0100 Subject: [PATCH 13/18] #1051: runnable: Move return type SFINAE checks (used for invoke function) to separate file --- src/vt/runnable/invoke.h | 35 +------ .../utils/static_checks/function_ret_check.h | 97 +++++++++++++++++++ src/vt/vrt/collection/manager.h | 6 +- src/vt/vrt/collection/manager.impl.h | 6 +- 4 files changed, 108 insertions(+), 36 deletions(-) create mode 100644 src/vt/utils/static_checks/function_ret_check.h diff --git a/src/vt/runnable/invoke.h b/src/vt/runnable/invoke.h index 10474bd645..9ed25f5b88 100644 --- a/src/vt/runnable/invoke.h +++ b/src/vt/runnable/invoke.h @@ -47,6 +47,8 @@ #include "vt/config.h" #include "vt/utils/demangle/demangle.h" +#include "vt/utils/static_checks/function_ret_check.h" +#include "vt/trace/trace_registry.h" #include @@ -96,7 +98,6 @@ struct CallableWrapper; template struct CallableWrapper { - using ReturnType = Ret; using Type = Ret(*)(Args...); static std::string GetEventTypeName() { @@ -118,7 +119,6 @@ template < typename Ret, typename Class, typename... Args, Ret (Class::*f)(Args...) > struct CallableWrapper { - using ReturnType = Ret; using Type = Ret (Class::*)(Args...); static std::string GetEventTypeName() { @@ -136,31 +136,6 @@ struct CallableWrapper { } }; -template -using IsVoidReturn = std::enable_if_t< - std::is_same< - typename CallableWrapper::ReturnType, void>::value, - void ->; - -template < - typename FunctionType, - typename Ret = typename CallableWrapper::ReturnType -> -using Copyable = std::enable_if_t< - !std::is_same::value && std::is_copy_constructible::value, - Ret ->; - -template < - typename FunctionType, - typename Ret = typename CallableWrapper::ReturnType -> -using NotCopyable = std::enable_if_t< - !std::is_same::value && !std::is_copy_constructible::value, - Ret ->; - #if vt_check_enabled(trace_enabled) template static trace::TraceProcessingTag BeginProcessingInvokeEvent() { @@ -196,7 +171,7 @@ decltype(auto) invokeImpl(Callable&& f, Args&&... args) { } template -Copyable invoke(Args&&... args) { +util::Copyable invoke(Args&&... args) { #if vt_check_enabled(trace_enabled) const auto processing_tag = BeginProcessingInvokeEvent(); @@ -212,7 +187,7 @@ Copyable invoke(Args&&... args) { } template -NotCopyable invoke(Args&&... args) { +util::NotCopyable invoke(Args&&... args) { #if vt_check_enabled(trace_enabled) const auto processing_tag = BeginProcessingInvokeEvent(); @@ -228,7 +203,7 @@ NotCopyable invoke(Args&&... args) { } template -IsVoidReturn invoke(Args&&... args) { +util::IsVoidReturn invoke(Args&&... args) { #if vt_check_enabled(trace_enabled) const auto processing_tag = BeginProcessingInvokeEvent(); diff --git a/src/vt/utils/static_checks/function_ret_check.h b/src/vt/utils/static_checks/function_ret_check.h new file mode 100644 index 0000000000..77311be2a4 --- /dev/null +++ b/src/vt/utils/static_checks/function_ret_check.h @@ -0,0 +1,97 @@ +/* +//@HEADER +// ***************************************************************************** +// +// function_ret_check.h +// DARMA Toolkit v. 1.0.0 +// DARMA/vt => Virtual Transport +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_UTILS_STATIC_CHECKS_FUNCTION_RET_CHECK_H +#define INCLUDED_UTILS_STATIC_CHECKS_FUNCTION_RET_CHECK_H + +#include + +namespace vt { namespace util { + +template +struct FunctionWrapper; + +template +struct FunctionWrapper { + using ReturnType = ReturnT; + using Type = ReturnT(*)(ArgsT...); +}; + +template < + typename ReturnT, typename FunctorT, typename... ArgsT +> +struct FunctionWrapper { + using ReturnType = ReturnT; + using Type = ReturnT (FunctorT::*)(ArgsT...); +}; + + +template +using IsVoidReturn = std::enable_if_t< + std::is_same< + typename FunctionWrapper::ReturnType, void>::value, + void +>; + +template < + typename FunctionType, + typename Ret = typename FunctionWrapper::ReturnType +> +using Copyable = std::enable_if_t< + !std::is_same::value && std::is_copy_constructible::value, + Ret +>; + +template < + typename FunctionType, + typename Ret = typename FunctionWrapper::ReturnType +> +using NotCopyable = std::enable_if_t< + !std::is_same::value && !std::is_copy_constructible::value, + Ret +>; + +}} /* end namespace vt::util */ + +#endif /*INCLUDED_UTILS_STATIC_CHECKS_FUNCTION_RET_CHECK_H*/ diff --git a/src/vt/vrt/collection/manager.h b/src/vt/vrt/collection/manager.h index c71bf87eec..47d3294dda 100644 --- a/src/vt/vrt/collection/manager.h +++ b/src/vt/vrt/collection/manager.h @@ -800,7 +800,7 @@ struct CollectionManager * \param[in] args function params */ template - runnable::Copyable + util::Copyable invoke(VirtualElmProxyType const& proxy, Args... args); /** @@ -811,7 +811,7 @@ struct CollectionManager * \param[in] args function params */ template - runnable::NotCopyable + util::NotCopyable invoke(VirtualElmProxyType const& proxy, Args... args); /** @@ -822,7 +822,7 @@ struct CollectionManager * \param[in] args function params */ template - runnable::IsVoidReturn + util::IsVoidReturn invoke(VirtualElmProxyType const& proxy, Args... args); /** diff --git a/src/vt/vrt/collection/manager.impl.h b/src/vt/vrt/collection/manager.impl.h index 283810fe8a..28dea1fff1 100644 --- a/src/vt/vrt/collection/manager.impl.h +++ b/src/vt/vrt/collection/manager.impl.h @@ -798,7 +798,7 @@ ColT* CollectionManager::getCollectionPtrForInvoke( } template -runnable::Copyable CollectionManager::invoke( +util::Copyable CollectionManager::invoke( VirtualElmProxyType const& proxy, Args... args ) { auto ptr = getCollectionPtrForInvoke(proxy); @@ -818,7 +818,7 @@ runnable::Copyable CollectionManager::invoke( } template -runnable::NotCopyable CollectionManager::invoke( +util::NotCopyable CollectionManager::invoke( VirtualElmProxyType const& proxy, Args... args ) { auto ptr = getCollectionPtrForInvoke(proxy); @@ -837,7 +837,7 @@ runnable::NotCopyable CollectionManager::invoke( } template -runnable::IsVoidReturn CollectionManager::invoke( +util::IsVoidReturn CollectionManager::invoke( VirtualElmProxyType const& proxy, Args... args ) { auto ptr = getCollectionPtrForInvoke(proxy); From 98410466fca02c9e798e78a9fcec15a5992c7f89 Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Sun, 22 Nov 2020 20:01:05 +0100 Subject: [PATCH 14/18] #1051: objgroup: Remove warnings --- src/vt/objgroup/manager.impl.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/vt/objgroup/manager.impl.h b/src/vt/objgroup/manager.impl.h index c485da017c..c469b55bef 100644 --- a/src/vt/objgroup/manager.impl.h +++ b/src/vt/objgroup/manager.impl.h @@ -264,32 +264,36 @@ void ObjGroupManager::send(ProxyElmType proxy, MsgSharedPtr msg) { } template fn> -void ObjGroupManager::invoke(ProxyElmType proxy, messaging::MsgPtrThief msg) { +void ObjGroupManager::invoke( + ProxyElmType proxy, messaging::MsgPtrThief msg +) { auto const proxy_bits = proxy.getProxy(); auto const dest_node = proxy.getNode(); auto const ctrl = proxy::ObjGroupProxy::getID(proxy_bits); - auto const han = auto_registry::makeAutoHandlerObjGroup(ctrl); + auto const han = auto_registry::makeAutoHandlerObjGroup(ctrl); + vt_debug_print( objgroup, node, "ObjGroupManager::invoke: proxy={:x}, node={}, ctrl={:x}, han={:x}\n", proxy_bits, dest_node, ctrl, han ); + invoke(msg, han, dest_node); } template decltype(auto) ObjGroupManager::invoke(ProxyElmType proxy, Args&&... args) { - auto const proxy_bits = proxy.getProxy(); auto const dest_node = proxy.getNode(); auto const this_node = theContext()->getNode(); - auto const ctrl = proxy::ObjGroupProxy::getID(proxy_bits); vtAssert( dest_node == this_node, fmt::format( - "Attempting to invoke handler on node:{} instead of node:{}!", this_node, - dest_node)); + "Attempting to invoke handler on node:{} instead of node:{}!\n", this_node, + dest_node + ) + ); return runnable::invoke(get(proxy), std::forward(args)...); } @@ -300,12 +304,14 @@ void ObjGroupManager::broadcast(ProxyType proxy, MsgSharedPtr msg) { auto const proxy_bits = proxy.getProxy(); auto const ctrl = proxy::ObjGroupProxy::getID(proxy_bits); auto const han = auto_registry::makeAutoHandlerObjGroup(ctrl); + vt_debug_print( objgroup, node, "ObjGroupManager::broadcast: proxy={:x}, ctrl={:x}, han={:x}\n", proxy_bits, ctrl, han ); - broadcast(msg,han); + + broadcast(msg, han); } template From 25079466cf972578be4a766802edb9bd4e6b2f22 Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Sun, 22 Nov 2020 20:54:28 +0100 Subject: [PATCH 15/18] #1051: runnable: Use LocalInvoke enum value in outputTraces function --- src/vt/trace/trace.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vt/trace/trace.cc b/src/vt/trace/trace.cc index 0f0a65cd3e..5188d90a8e 100644 --- a/src/vt/trace/trace.cc +++ b/src/vt/trace/trace.cc @@ -1026,7 +1026,8 @@ void Trace::writeTracesFile(int flush, bool is_incremental_flush) { ); break; } - case TraceConstantsType::Creation: { + case TraceConstantsType::Creation: + case TraceConstantsType::LocalInvoke: { auto const& sdata = log.sys_data(); gzprintf( gzfile, From 7d7551cdd0095bf2b95636adf9c04ac967dc8dbd Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Thu, 26 Nov 2020 23:38:34 +0100 Subject: [PATCH 16/18] #1051: trace: Use Create event type for local invoke --- src/vt/trace/trace.cc | 6 ++---- src/vt/trace/trace_constants.h | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/vt/trace/trace.cc b/src/vt/trace/trace.cc index 5188d90a8e..44495a2d60 100644 --- a/src/vt/trace/trace.cc +++ b/src/vt/trace/trace.cc @@ -641,7 +641,7 @@ Trace::localInvoke(TraceEntryIDType const ep, double const time) { return no_trace_event; } - auto const type = TraceConstantsType::LocalInvoke; + auto const type = TraceConstantsType::Creation; NodeType const node = theContext()->getNode(); @@ -770,7 +770,6 @@ TraceEventIDType Trace::logEvent(LogType&& log) { case TraceConstantsType::Creation: case TraceConstantsType::CreationBcast: case TraceConstantsType::MessageRecv: - case TraceConstantsType::LocalInvoke: log.event = cur_event_++; break; case TraceConstantsType::BeginIdle: @@ -1026,8 +1025,7 @@ void Trace::writeTracesFile(int flush, bool is_incremental_flush) { ); break; } - case TraceConstantsType::Creation: - case TraceConstantsType::LocalInvoke: { + case TraceConstantsType::Creation: { auto const& sdata = log.sys_data(); gzprintf( gzfile, diff --git a/src/vt/trace/trace_constants.h b/src/vt/trace/trace_constants.h index e8075aed20..e76827df21 100644 --- a/src/vt/trace/trace_constants.h +++ b/src/vt/trace/trace_constants.h @@ -83,8 +83,7 @@ enum class eTraceConstants : int32_t { UserStat = 32, BeginUserEventPair = 98, EndUserEventPair = 99, - UserEventPair = 100, - LocalInvoke = 101 + UserEventPair = 100 }; From 3c6a3903f5f551a7f03926fed3e81d4ec678ef5b Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Fri, 27 Nov 2020 16:02:52 +0100 Subject: [PATCH 17/18] #1051: vrt-collection: Add doxygen documentation for invokable struct --- src/vt/vrt/collection/invoke/invokable.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/vt/vrt/collection/invoke/invokable.h b/src/vt/vrt/collection/invoke/invokable.h index b38d76d1f4..c8a31c2841 100644 --- a/src/vt/vrt/collection/invoke/invokable.h +++ b/src/vt/vrt/collection/invoke/invokable.h @@ -58,17 +58,35 @@ struct Invokable : BaseProxyT { typename BaseProxyT::ElementProxyType const& in_elm ); + /** + * \brief Invoke member message handler on a collection element + * The function will be invoked inline without going through scheduler + * + * \param[in] args arguments for creating the message + */ template < typename MsgT, ActiveColMemberTypedFnType f, typename... Args > void invoke(Args&&... args) const; + /** + * \brief Invoke message handler on a collection element + * The function will be invoked inline without going through scheduler + * + * \param[in] args arguments for creating the message + */ template < typename MsgT, ActiveColTypedFnType* f, typename... Args > void invoke(Args&&... args) const; + /** + * \brief Invoke function 'f' on a collection element + * The function will be invoked inline without going through scheduler + * + * \param[in] args function arguments + */ template decltype(auto) invoke(Args&&... args) const; }; From e1d4ad481d984aabd6ff4cadc9d6a273f3c9f9ff Mon Sep 17 00:00:00 2001 From: Jakub Domagala Date: Thu, 3 Dec 2020 20:17:18 +0100 Subject: [PATCH 18/18] #1051: trace: Fix incorrect trace name for invoke and remove localInvoke function from trace module --- src/vt/runnable/invoke.h | 20 +++++++++++++------- src/vt/trace/trace.cc | 13 ------------- src/vt/trace/trace.h | 11 ----------- 3 files changed, 13 insertions(+), 31 deletions(-) diff --git a/src/vt/runnable/invoke.h b/src/vt/runnable/invoke.h index 9ed25f5b88..ccd5a3ee75 100644 --- a/src/vt/runnable/invoke.h +++ b/src/vt/runnable/invoke.h @@ -85,9 +85,7 @@ static std::string CreateEventName() { std::vector arg_types = {TE::getTypeName()...}; auto argsV = DU::join(",", arg_types); - auto valueName = - TE::lastNamedPfType(TE::prettyFunctionForValue(), "T" - ); + auto valueName = TE::getValueName(); auto barename = TE::getBarename(valueName); return DU::removeSpaces(barename + "(" + argsV + ")"); @@ -140,11 +138,19 @@ struct CallableWrapper { template static trace::TraceProcessingTag BeginProcessingInvokeEvent() { const auto trace_id = CallableWrapper::GetTraceID(); - const auto trace_event = theTrace()->localInvoke(trace_id); + const auto trace_event = theTrace()->messageCreation(trace_id, 0); const auto from_node = theContext()->getNode(); return theTrace()->beginProcessing(trace_id, 0, trace_event, from_node); } + +template +static void EndProcessingInvokeEvent(trace::TraceProcessingTag processing_tag) { + theTrace()->endProcessing(processing_tag); + + const auto trace_id = CallableWrapper::GetTraceID(); + theTrace()->messageCreation(trace_id, 0); +} #endif template < @@ -180,7 +186,7 @@ util::Copyable invoke(Args&&... args) { const auto& returnVal = invokeImpl(f, std::forward(args)...); #if vt_check_enabled(trace_enabled) - theTrace()->endProcessing(processing_tag); + EndProcessingInvokeEvent(processing_tag); #endif return returnVal; @@ -196,7 +202,7 @@ util::NotCopyable invoke(Args&&... args) { auto&& returnVal = invokeImpl(f, std::forward(args)...); #if vt_check_enabled(trace_enabled) - theTrace()->endProcessing(processing_tag); + EndProcessingInvokeEvent(processing_tag); #endif return std::move(returnVal); @@ -212,7 +218,7 @@ util::IsVoidReturn invoke(Args&&... args) { invokeImpl(f, std::forward(args)...); #if vt_check_enabled(trace_enabled) - theTrace()->endProcessing(processing_tag); + EndProcessingInvokeEvent(processing_tag); #endif } diff --git a/src/vt/trace/trace.cc b/src/vt/trace/trace.cc index 44495a2d60..af5f390527 100644 --- a/src/vt/trace/trace.cc +++ b/src/vt/trace/trace.cc @@ -635,19 +635,6 @@ void Trace::endIdle(double const time) { emitTraceForTopProcessingEvent(time, TraceConstantsType::BeginProcessing); } -TraceEventIDType -Trace::localInvoke(TraceEntryIDType const ep, double const time) { - if (not checkDynamicRuntimeEnabled()) { - return no_trace_event; - } - - auto const type = TraceConstantsType::Creation; - - NodeType const node = theContext()->getNode(); - - return logEvent(LogType{time, ep, type, node, 0}); -} - TraceEventIDType Trace::messageCreation( TraceEntryIDType const ep, TraceMsgLenType const len, double const time ) { diff --git a/src/vt/trace/trace.h b/src/vt/trace/trace.h index 59084c5852..1c29e2fef4 100644 --- a/src/vt/trace/trace.h +++ b/src/vt/trace/trace.h @@ -384,17 +384,6 @@ struct Trace : runtime::component::Component { double const time = getCurrentTime() ); - /** - * \brief Log a local function invoke - * - * \param[in] ep the registered function's event ID - * \param[in] time the time of the event - * - * \return the trace event ID - */ - TraceEventIDType - localInvoke(TraceEntryIDType const ep, double const time = getCurrentTime()); - /** * \brief Log a message send *