Skip to content

Commit

Permalink
Merge pull request #2039 from DARMA-tasking/2027-objgroup-invoke-does…
Browse files Browse the repository at this point in the history
…-not-create-a-runnable

2027: Create Runnable inside Objgroup's invoke
  • Loading branch information
lifflander authored Feb 8, 2023
2 parents cf4c06a + 8820ec9 commit 5444a54
Show file tree
Hide file tree
Showing 24 changed files with 75 additions and 122 deletions.
2 changes: 1 addition & 1 deletion examples/collection/jacobi1d_vt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ struct LinearPb1DJacobi : vt::Collection<LinearPb1DJacobi,vt::Index1D> {

bool isWorkDone( vt::objgroup::proxy::Proxy<NodeObj> const& proxy){
auto const this_node = vt::theContext()->getNode();
return proxy[this_node].invoke<decltype(&NodeObj::isWorkFinished), &NodeObj::isWorkFinished>();
return proxy[this_node].invoke<&NodeObj::isWorkFinished>();
}

int main(int argc, char** argv) {
Expand Down
2 changes: 1 addition & 1 deletion examples/collection/jacobi2d_vt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ struct LinearPb2DJacobi : vt::Collection<LinearPb2DJacobi,vt::Index2D> {

bool isWorkDone( vt::objgroup::proxy::Proxy<NodeObj> const& proxy){
auto const this_node = vt::theContext()->getNode();
return proxy[this_node].invoke<decltype(&NodeObj::isWorkFinished), &NodeObj::isWorkFinished>();
return proxy[this_node].invoke<&NodeObj::isWorkFinished>();
}

int main(int argc, char** argv) {
Expand Down
5 changes: 3 additions & 2 deletions src/vt/objgroup/manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@

#include "vt/config.h"
#include "vt/runtime/component/component_pack.h"
#include "vt/utils/static_checks/function_ret_check.h"
#include "vt/objgroup/common.h"
#include "vt/objgroup/manager.fwd.h"
#include "vt/objgroup/proxy/proxy_objgroup.h"
Expand Down Expand Up @@ -233,8 +234,8 @@ struct ObjGroupManager : runtime::component::Component<ObjGroupManager> {
* \param[in] proxy proxy to the object group
* \param[in] args function arguments
*/
template <typename ObjT, typename Type, Type f, typename... Args>
decltype(auto) invoke(ProxyElmType<ObjT> proxy, Args&&... args);
template <typename ObjT, auto f, typename... Args>
auto invoke(ProxyElmType<ObjT> proxy, Args&&... args);

/**
* \internal \brief Broadcast a message to all nodes in object group
Expand Down
14 changes: 7 additions & 7 deletions src/vt/objgroup/manager.impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,21 +210,21 @@ void ObjGroupManager::invoke(
invoke<MsgT>(msg, han, dest_node);
}

template <typename ObjT, typename Type, Type f, typename... Args>
decltype(auto)
template <typename ObjT, auto f, typename... Args>
auto
ObjGroupManager::invoke(ProxyElmType<ObjT> proxy, Args&&... args) {
auto const dest_node = proxy.getNode();
auto const this_node = theContext()->getNode();

vtAssert(
dest_node == this_node,
fmt::format(
"Attempting to invoke handler on node:{} instead of node:{}!\n", this_node,
dest_node
)
);
"Attempting to invoke handler on node:{} instead of node:{}!\n",
this_node, dest_node));

return runnable::invoke<Type, f>(get(proxy), std::forward<Args>(args)...);
return runnable::makeRunnableVoid(false, uninitialized_handler, this_node)
.withObjGroup(get(proxy))
.runLambda(f, get(proxy), std::forward<Args>(args)...);
}


Expand Down
2 changes: 1 addition & 1 deletion src/vt/objgroup/proxy/proxy_objgroup_elm.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ struct ProxyElm {
*
* \param[in] args function arguments
*/
template <typename Type, Type f, typename... Args>
template <auto f, typename... Args>
decltype(auto) invoke(Args&&... args) const;

/**
Expand Down
10 changes: 3 additions & 7 deletions src/vt/objgroup/proxy/proxy_objgroup_elm.impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,10 @@ void ProxyElm<ObjT>::invoke(Args&&... args) const {
}

template <typename ObjT>
template <typename Type, Type f, typename... Args>
decltype(auto) ProxyElm<ObjT>::invoke(
Args&&... args
) const
{
template <auto f, typename... Args>
decltype(auto) ProxyElm<ObjT>::invoke(Args&&... args) const {
auto proxy = ProxyElm<ObjT>(*this);
return theObjGroup()->invoke<ObjT, Type, f>(
proxy, std::forward<Args>(args)...);
return theObjGroup()->invoke<ObjT, f>(proxy, std::forward<Args>(args)...);
}

template <typename ObjT>
Expand Down
7 changes: 4 additions & 3 deletions src/vt/runnable/make_runnable.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,13 @@ struct RunnableMaker {
/**
* \brief Run the runnable immediately with a lambda
*/
void runLambda(ActionType&& action) {
template <typename Callable, typename... Args>
auto runLambda(Callable&& c, Args&&... args) {
setup();
impl_->runLambda(std::move(action));
delete impl_;
auto local_impl = std::unique_ptr<RunnableNew>(impl_);
impl_ = nullptr;
is_done_ = true;
return local_impl->runLambda(std::forward<Callable>(c), std::forward<Args>(args)...);
}

/**
Expand Down
6 changes: 0 additions & 6 deletions src/vt/runnable/runnable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,6 @@ void RunnableNew::setupHandlerElement(
obj_ = elm;
}

void RunnableNew::runLambda(ActionType action) {
start();
action();
finish();
}

void RunnableNew::run() {
#if vt_check_enabled(fcontext)
vtAbortIf(
Expand Down
13 changes: 12 additions & 1 deletion src/vt/runnable/runnable.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,18 @@ struct RunnableNew {
/**
* \brief Run the task as a lambda!
*/
void runLambda(ActionType action);
template <typename Callable, typename... Args>
decltype(auto) runLambda(Callable&& c, Args&&... args) {
start();
if constexpr(std::is_void_v<std::invoke_result_t<Callable, Args...>>) {
std::invoke(std::forward<Callable>(c), std::forward<Args>(args)...);
finish();
} else {
decltype(auto) r{std::invoke(std::forward<Callable>(c), std::forward<Args>(args)...)};
finish();
return r;
}
}

#if vt_check_enabled(fcontext)
/**
Expand Down
2 changes: 1 addition & 1 deletion src/vt/vrt/collection/invoke/invokable.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ struct Invokable : BaseProxyT {
*
* \param[in] args function arguments
*/
template <typename Type, Type f, typename... Args>
template <auto f, typename... Args>
decltype(auto) invoke(Args&&... args) const;
};

Expand Down
4 changes: 2 additions & 2 deletions src/vt/vrt/collection/invoke/invokable.impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ void Invokable<ColT, IndexT, BaseProxyT>::invoke(Args&&... args) const
}

template <typename ColT, typename IndexT, typename BaseProxyT>
template <typename Type, Type f, typename... Args>
template <auto f, typename... Args>
decltype(auto)
Invokable<ColT, IndexT, BaseProxyT>::invoke(Args&&... args) const {
auto const& proxy = VrtElmProxy<ColT, IndexT>(
this->getCollectionProxy(), this->getElementProxy());

return theCollection()->invoke<ColT, Type, f, Args...>(
return theCollection()->invoke<ColT, f, Args...>(
proxy, std::forward<Args>(args)...
);
}
Expand Down
30 changes: 3 additions & 27 deletions src/vt/vrt/collection/manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -665,37 +665,13 @@ struct CollectionManager
static void recordLBData(ColT* col_ptr, MsgT* msg);

/**
* \brief Invoke function 'f' (with copyable return type) inline without going
* through scheduler
* \brief Invoke function 'f' inline without going through scheduler
*
* \param[in] proxy the collection proxy
* \param[in] args function params
*/
template <typename ColT, typename Type, Type f, typename... Args>
util::Copyable<Type>
invoke(VirtualElmProxyType<ColT> 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 <typename ColT, typename Type, Type f, typename... Args>
util::NotCopyable<Type>
invoke(VirtualElmProxyType<ColT> 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 <typename ColT, typename Type, Type f, typename... Args>
util::IsVoidReturn<Type>
invoke(VirtualElmProxyType<ColT> const& proxy, Args... args);
template <typename ColT, auto f, typename... Args>
auto invoke(VirtualElmProxyType<ColT> const& proxy, Args&&... args);

/**
* \brief Invoke message action function handler without going through
Expand Down
51 changes: 5 additions & 46 deletions src/vt/vrt/collection/manager.impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,59 +461,18 @@ void CollectionManager::invokeCollectiveMsg(
});
}

template <typename ColT, typename Type, Type f, typename... Args>
util::Copyable<Type> CollectionManager::invoke(
VirtualElmProxyType<ColT> const& proxy, Args... args
template <typename ColT, auto f, typename... Args>
auto CollectionManager::invoke(
VirtualElmProxyType<ColT> const& proxy, Args&&... args
) {
auto ptr = getCollectionPtrForInvoke(proxy);

auto const this_node = theContext()->getNode();
util::Copyable<Type> result;

runnable::makeRunnableVoid(false, uninitialized_handler, this_node)
return runnable::makeRunnableVoid(false, uninitialized_handler, this_node)
.withCollection(ptr)
.withLBDataVoidMsg(ptr)
.runLambda([&]{
result = runnable::invoke<Type, f>(ptr, std::forward<Args>(args)...);
});

return result;
}

template <typename ColT, typename Type, Type f, typename... Args>
util::NotCopyable<Type> CollectionManager::invoke(
VirtualElmProxyType<ColT> const& proxy, Args... args
) {
auto ptr = getCollectionPtrForInvoke(proxy);

auto const this_node = theContext()->getNode();
util::NotCopyable<Type> result;

runnable::makeRunnableVoid(false, uninitialized_handler, this_node)
.withCollection(ptr)
.withLBDataVoidMsg(ptr)
.runLambda([&]{
auto&& ret = runnable::invoke<Type, f>(ptr, std::forward<Args>(args)...);
result = std::move(ret);
});

return std::move(result);
}

template <typename ColT, typename Type, Type f, typename... Args>
util::IsVoidReturn<Type> CollectionManager::invoke(
VirtualElmProxyType<ColT> const& proxy, Args... args
) {
auto ptr = getCollectionPtrForInvoke(proxy);

auto const this_node = theContext()->getNode();

runnable::makeRunnableVoid(false, uninitialized_handler, this_node)
.withCollection(ptr)
.withLBDataVoidMsg(ptr)
.runLambda([&]{
runnable::invoke<Type, f>(ptr, std::forward<Args>(args)...);
});
.runLambda(f, ptr, std::forward<Args>(args)...);
}

template <
Expand Down
2 changes: 1 addition & 1 deletion tests/perf/collection_local_send.cc
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ VT_PERF_TEST(MyTest, test_collection_local_send) {
"test_collection_local_send", this
);

grp_proxy[my_node_].invoke<decltype(&NodeObj::initialize), &NodeObj::initialize>();
grp_proxy[my_node_].invoke<&NodeObj::initialize>();

if (theContext()->getNode() == 0) {
grp_proxy[my_node_].send<MyMsg, &NodeObj::perfMakeRunnable>();
Expand Down
2 changes: 1 addition & 1 deletion tests/perf/collection_local_send_prealloc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ VT_PERF_TEST(MyTest, test_collection_local_send_preallocate) {
"test_collection_local_send_preallocate", this
);

grp_proxy[my_node_].invoke<decltype(&NodeObj::initialize), &NodeObj::initialize>();
grp_proxy[my_node_].invoke<&NodeObj::initialize>();

if (theContext()->getNode() == 0) {
grp_proxy[my_node_].send<MyMsg, &NodeObj::perfMakeRunnablePreAllocate>();
Expand Down
2 changes: 1 addition & 1 deletion tests/perf/make_runnable_micro.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ VT_PERF_TEST(MyTest, test_make_runnable_micro) {
"test_make_runnable_micro", this
);

grp_proxy[my_node_].invoke<decltype(&NodeObj::initialize), &NodeObj::initialize>();
grp_proxy[my_node_].invoke<&NodeObj::initialize>();

if (theContext()->getNode() == 0) {
grp_proxy[my_node_].send<MyMsg, &NodeObj::perfMakeRunnable>();
Expand Down
2 changes: 1 addition & 1 deletion tests/perf/objgroup_local_send.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ VT_PERF_TEST(MyTest, test_objgroup_local_send) {
"test_objgroup_local_send", this
);

grp_proxy[my_node_].invoke<decltype(&NodeObj::initialize), &NodeObj::initialize>();
grp_proxy[my_node_].invoke<&NodeObj::initialize>();

if (theContext()->getNode() == 0) {
grp_proxy[my_node_].send<MyMsg, &NodeObj::perfMakeRunnable>();
Expand Down
3 changes: 1 addition & 2 deletions tests/perf/ping_pong.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,7 @@ VT_PERF_TEST(MyTest, test_ping_pong) {
auto grp_proxy = vt::theObjGroup()->makeCollective<NodeObj>(
"test_ping_pong", this
);
grp_proxy[my_node_]
.invoke<decltype(&NodeObj::initialize), &NodeObj::initialize>();
grp_proxy[my_node_].invoke<&NodeObj::initialize>();

if (theContext()->getNode() == 0) {
theTerm()->disableTD();
Expand Down
4 changes: 2 additions & 2 deletions tests/perf/ping_pong_am.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ struct NodeObj {

void handlerFinished(MyMsg* msg) {
if (i >= num_iters) {
global_proxy[0].invoke<decltype(&NodeObj::complete), &NodeObj::complete>();
global_proxy[0].invoke<&NodeObj::complete>();
} else {
i++;
auto msg = makeMessage<MyMsg>();
Expand All @@ -117,7 +117,7 @@ VT_PERF_TEST(MyTest, test_ping_pong_am) {
theTerm()->disableTD();
}

grp_proxy[my_node_].invoke<decltype(&NodeObj::initialize), &NodeObj::initialize>();
grp_proxy[my_node_].invoke<&NodeObj::initialize>();

if (theContext()->getNode() == 0) {
grp_proxy[my_node_].send<MyMsg, &NodeObj::perfPingPong>();
Expand Down
2 changes: 1 addition & 1 deletion tests/perf/reduce.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ VT_PERF_TEST(MyTest, test_reduce) {
theTerm()->disableTD();
}

grp_proxy[my_node_].invoke<decltype(&NodeObj::initialize), &NodeObj::initialize>();
grp_proxy[my_node_].invoke<&NodeObj::initialize>();

using MsgType = typename NodeObj::MyMsg;
grp_proxy[my_node_].send<MsgType, &NodeObj::perfReduce>();
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/active/test_async_op_threads.cc
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ struct MyCol : vt::Collection<MyCol, vt::Index1D> {
);

auto p = getCollectionProxy();
p[this_node].invoke<decltype(&MyCol::handlerToInvoke), &MyCol::handlerToInvoke>(std::move(op1),std::move(op2));
p[this_node].invoke<&MyCol::handlerToInvoke>(std::move(op1),std::move(op2));
}

void handlerToInvoke(
Expand Down
7 changes: 3 additions & 4 deletions tests/unit/collection/test_invoke.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,9 @@ TEST_F(TestCollectionInvoke, test_collection_invoke_1) {
// Non-message function
{
auto const accumulate_result =
proxy[dest_elem]
.invoke<decltype(&TestCol::accumulateVec), &TestCol::accumulateVec>(
dest_elem, std::vector<int32_t>{2, 4, 5}
);
proxy[dest_elem].invoke<&TestCol::accumulateVec>(
dest_elem, std::vector<int32_t>{2, 4, 5}
);

EXPECT_EQ(accumulate_result, 11);
EXPECT_EQ(handler_invoked, true);
Expand Down
16 changes: 13 additions & 3 deletions tests/unit/objgroup/test_objgroup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -287,12 +287,22 @@ TEST_F(TestObjGroup, test_proxy_invoke) {

// Non-message function
auto const accumulate_result =
proxy[this_node]
.invoke<decltype(&MyObjA::accumulateVec), &MyObjA::accumulateVec>(
std::vector<int32_t>{2, 4, 5});
proxy[this_node].invoke<&MyObjA::accumulateVec>(
std::vector<int32_t>{2, 4, 5}
);

EXPECT_EQ(accumulate_result, 11);
EXPECT_EQ(proxy.get()->recv_, 2);

// Non-copyable
std::unique_ptr<int32_t> s{};
auto result = proxy[this_node].invoke<&MyObjA::modifyNonCopyableStruct>(
std::move(s)
);

EXPECT_TRUE(result);
EXPECT_EQ(*result, 10);
EXPECT_EQ(proxy.get()->recv_, 3);
}

TEST_F(TestObjGroup, test_pending_send) {
Expand Down
Loading

0 comments on commit 5444a54

Please sign in to comment.