[C++ worker]Support ActorHandle type return value (#28077)

Before we support `ActorHandle` type as parameter, this PR adds support for `ActorHandle` type as return type.
This commit is contained in:
Tao Wang 2022-08-25 10:05:05 +08:00 committed by GitHub
parent 7e560ad92c
commit b6fe6156f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 41 additions and 17 deletions

View file

@ -17,6 +17,7 @@
#include <ray/api/actor_creator.h> #include <ray/api/actor_creator.h>
#include <ray/api/actor_handle.h> #include <ray/api/actor_handle.h>
#include <ray/api/actor_task_caller.h> #include <ray/api/actor_task_caller.h>
#include <ray/api/function_manager.h>
#include <ray/api/logging.h> #include <ray/api/logging.h>
#include <ray/api/object_ref.h> #include <ray/api/object_ref.h>
#include <ray/api/ray_config.h> #include <ray/api/ray_config.h>
@ -270,7 +271,8 @@ inline ray::internal::TaskCaller<F> Task(F func) {
static_assert(!ray::internal::is_python_v<F>, "Must be a cpp function."); static_assert(!ray::internal::is_python_v<F>, "Must be a cpp function.");
static_assert(!std::is_member_function_pointer_v<F>, static_assert(!std::is_member_function_pointer_v<F>,
"Incompatible type: member function cannot be called with ray::Task."); "Incompatible type: member function cannot be called with ray::Task.");
ray::internal::RemoteFunctionHolder remote_func_holder(std::move(func)); auto func_name = internal::FunctionManager::Instance().GetFunctionName(func);
ray::internal::RemoteFunctionHolder remote_func_holder(std::move(func_name));
return ray::internal::TaskCaller<F>(ray::internal::GetRayRuntime().get(), return ray::internal::TaskCaller<F>(ray::internal::GetRayRuntime().get(),
std::move(remote_func_holder)); std::move(remote_func_holder));
} }
@ -278,7 +280,8 @@ inline ray::internal::TaskCaller<F> Task(F func) {
/// Creating an actor. /// Creating an actor.
template <typename F> template <typename F>
inline ray::internal::ActorCreator<F> Actor(F create_func) { inline ray::internal::ActorCreator<F> Actor(F create_func) {
ray::internal::RemoteFunctionHolder remote_func_holder(std::move(create_func)); auto func_name = internal::FunctionManager::Instance().GetFunctionName(create_func);
ray::internal::RemoteFunctionHolder remote_func_holder(std::move(func_name));
return ray::internal::ActorCreator<F>(ray::internal::GetRayRuntime().get(), return ray::internal::ActorCreator<F>(ray::internal::GetRayRuntime().get(),
std::move(remote_func_holder)); std::move(remote_func_holder));
} }

View file

@ -15,6 +15,7 @@
#pragma once #pragma once
#include <ray/api/actor_task_caller.h> #include <ray/api/actor_task_caller.h>
#include <ray/api/function_manager.h>
#include <ray/api/ray_runtime_holder.h> #include <ray/api/ray_runtime_holder.h>
namespace ray { namespace ray {
@ -47,7 +48,8 @@ class ActorHandle {
static_assert( static_assert(
std::is_same<ActorType, Self>::value || std::is_base_of<Self, ActorType>::value, std::is_same<ActorType, Self>::value || std::is_base_of<Self, ActorType>::value,
"Class types must be same."); "Class types must be same.");
ray::internal::RemoteFunctionHolder remote_func_holder(actor_func); auto func_name = internal::FunctionManager::Instance().GetFunctionName(actor_func);
ray::internal::RemoteFunctionHolder remote_func_holder(func_name);
return ray::internal::ActorTaskCaller<F>( return ray::internal::ActorTaskCaller<F>(
internal::GetRayRuntime().get(), id_, std::move(remote_func_holder)); internal::GetRayRuntime().get(), id_, std::move(remote_func_holder));
} }

View file

@ -42,5 +42,15 @@ struct TaskArg {
std::string_view meta_str; std::string_view meta_str;
}; };
using ArgsBuffer = msgpack::sbuffer;
using ArgsBufferList = std::vector<ArgsBuffer>;
using RemoteFunction = std::function<msgpack::sbuffer(const ArgsBufferList &)>;
using RemoteFunctionMap_t = std::unordered_map<std::string, RemoteFunction>;
using RemoteMemberFunction =
std::function<msgpack::sbuffer(msgpack::sbuffer *, const ArgsBufferList &)>;
using RemoteMemberFunctionMap_t = std::unordered_map<std::string, RemoteMemberFunction>;
} // namespace internal } // namespace internal
} // namespace ray } // namespace ray

View file

@ -15,6 +15,7 @@
#pragma once #pragma once
#include <ray/api/common_types.h> #include <ray/api/common_types.h>
#include <ray/api/ray_runtime_holder.h>
#include <ray/api/serializer.h> #include <ray/api/serializer.h>
#include <ray/api/type_traits.h> #include <ray/api/type_traits.h>
@ -33,6 +34,11 @@ namespace internal {
template <typename T> template <typename T>
inline static std::enable_if_t<!std::is_pointer<T>::value, msgpack::sbuffer> inline static std::enable_if_t<!std::is_pointer<T>::value, msgpack::sbuffer>
PackReturnValue(T result) { PackReturnValue(T result) {
if constexpr (is_actor_handle_v<T>) {
auto serialized_actor_handle =
RayRuntimeHolder::Instance().Runtime()->SerializeActorHandle(result.ID());
return Serializer::Serialize(serialized_actor_handle);
}
return Serializer::Serialize(std::move(result)); return Serializer::Serialize(std::move(result));
} }
@ -48,16 +54,6 @@ inline static msgpack::sbuffer PackVoid() {
msgpack::sbuffer PackError(std::string error_msg); msgpack::sbuffer PackError(std::string error_msg);
using ArgsBuffer = msgpack::sbuffer;
using ArgsBufferList = std::vector<ArgsBuffer>;
using RemoteFunction = std::function<msgpack::sbuffer(const ArgsBufferList &)>;
using RemoteFunctionMap_t = std::unordered_map<std::string, RemoteFunction>;
using RemoteMemberFunction =
std::function<msgpack::sbuffer(msgpack::sbuffer *, const ArgsBufferList &)>;
using RemoteMemberFunctionMap_t = std::unordered_map<std::string, RemoteMemberFunction>;
/// It's help to invoke functions and member functions, the class Invoker<Function> help /// It's help to invoke functions and member functions, the class Invoker<Function> help
/// do type erase. /// do type erase.
template <typename Function> template <typename Function>

View file

@ -16,6 +16,7 @@
#include <ray/api/ray_runtime_holder.h> #include <ray/api/ray_runtime_holder.h>
#include <ray/api/serializer.h> #include <ray/api/serializer.h>
#include <ray/api/type_traits.h>
#include <memory> #include <memory>
#include <msgpack.hpp> #include <msgpack.hpp>
@ -118,6 +119,12 @@ inline static std::shared_ptr<T> GetFromRuntime(const ObjectRef<T> &object) {
packed_object->data(), packed_object->size(), internal::XLANG_HEADER_LEN); packed_object->data(), packed_object->size(), internal::XLANG_HEADER_LEN);
} }
if constexpr (ray::internal::is_actor_handle_v<T>) {
auto actor_handle = ray::internal::Serializer::Deserialize<std::string>(
packed_object->data(), packed_object->size());
return std::make_shared<T>(T::FromBytes(actor_handle));
}
return ray::internal::Serializer::Deserialize<std::shared_ptr<T>>( return ray::internal::Serializer::Deserialize<std::shared_ptr<T>>(
packed_object->data(), packed_object->size()); packed_object->data(), packed_object->size());
} }

View file

@ -14,7 +14,7 @@
#pragma once #pragma once
#include <ray/api/function_manager.h> #include <ray/api/common_types.h>
#include <ray/api/task_options.h> #include <ray/api/task_options.h>
#include <ray/api/xlang_function.h> #include <ray/api/xlang_function.h>
@ -38,9 +38,7 @@ struct RemoteFunctionHolder {
this->class_name = class_name; this->class_name = class_name;
this->lang_type = lang_type; this->lang_type = lang_type;
} }
template <typename F> RemoteFunctionHolder(std::string func_name) {
RemoteFunctionHolder(F func) {
auto func_name = FunctionManager::Instance().GetFunctionName(func);
if (func_name.empty()) { if (func_name.empty()) {
throw RayException( throw RayException(
"Function not found. Please use RAY_REMOTE to register this function."); "Function not found. Please use RAY_REMOTE to register this function.");

View file

@ -14,6 +14,8 @@
#pragma once #pragma once
#include <ray/api/ray_exception.h>
#include <cmath> #include <cmath>
namespace ray { namespace ray {

View file

@ -242,9 +242,15 @@ TEST(RayClusterModeTest, ActorHandleTest) {
auto actor1 = ray::Actor(RAY_FUNC(Counter::FactoryCreate)).Remote(); auto actor1 = ray::Actor(RAY_FUNC(Counter::FactoryCreate)).Remote();
auto obj1 = actor1.Task(&Counter::Plus1).Remote(); auto obj1 = actor1.Task(&Counter::Plus1).Remote();
EXPECT_EQ(1, *obj1.Get()); EXPECT_EQ(1, *obj1.Get());
// Test `ActorHandle` type object as parameter.
auto actor2 = ray::Actor(RAY_FUNC(Counter::FactoryCreate)).Remote(); auto actor2 = ray::Actor(RAY_FUNC(Counter::FactoryCreate)).Remote();
auto obj2 = actor2.Task(&Counter::Plus1ForActor).Remote(actor1); auto obj2 = actor2.Task(&Counter::Plus1ForActor).Remote(actor1);
EXPECT_EQ(2, *obj2.Get()); EXPECT_EQ(2, *obj2.Get());
// Test `ActorHandle` type object as return value.
std::string child_actor_name = "child_actor_name";
auto child_actor =
actor1.Task(&Counter::CreateChildActor).Remote(child_actor_name).Get();
EXPECT_EQ(1, *child_actor->Task(&Counter::Plus1).Remote().Get());
} }
TEST(RayClusterModeTest, PythonInvocationTest) { TEST(RayClusterModeTest, PythonInvocationTest) {