Skip to content

Commit e54dfd8

Browse files
authored
[C++ worker] Ray actor task for RAY_REMOTE (ray-project#15039)
1 parent 9c5a0cf commit e54dfd8

17 files changed

+539
-249
lines changed

cpp/example/example.cc

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ class Counter {
2020
int count;
2121

2222
Counter(int init) { count = init; }
23+
template <typename... Args>
24+
static Counter *GenericFactoryCreate(Args... args) {
25+
return FactoryCreate(args...);
26+
}
2327
static Counter *FactoryCreate() { return new Counter(0); }
2428
static Counter *FactoryCreate(int init) { return new Counter(init); }
2529
static Counter *FactoryCreate(int init1, int init2) {
@@ -73,20 +77,21 @@ int main(int argc, char **argv) {
7377
std::cout << "task_result2 = " << task_result2 << std::endl;
7478

7579
/// actor task without args
76-
ActorHandle<Counter> actor1 = Ray::Actor(Counter::FactoryCreate).Remote();
80+
ActorHandle<Counter> actor1 = Ray::Actor(Counter::GenericFactoryCreate<>).Remote();
7781
auto actor_object1 = actor1.Task(&Counter::Plus1).Remote();
7882
int actor_result1 = *(Ray::Get(actor_object1));
7983
std::cout << "actor_result1 = " << actor_result1 << std::endl;
8084

8185
/// actor task with args
82-
ActorHandle<Counter> actor2 = Ray::Actor(Counter::FactoryCreate, 1).Remote();
83-
auto actor_object2 = actor2.Task(&Counter::Add, 5).Remote();
86+
ActorHandle<Counter> actor2 = Ray::Actor(Counter::GenericFactoryCreate<int>).Remote(1);
87+
auto actor_object2 = actor2.Task(&Counter::Add).Remote(5);
8488
int actor_result2 = *(Ray::Get(actor_object2));
8589
std::cout << "actor_result2 = " << actor_result2 << std::endl;
8690

8791
/// actor task with args which pass by reference
88-
ActorHandle<Counter> actor3 = Ray::Actor(Counter::FactoryCreate, 6, 0).Remote();
89-
auto actor_object3 = actor3.Task(&Counter::Add, actor_object2).Remote();
92+
ActorHandle<Counter> actor3 =
93+
Ray::Actor(Counter::GenericFactoryCreate<int, int>).Remote(6, 0);
94+
auto actor_object3 = actor3.Task(&Counter::Add).Remote(actor_object2);
9095
int actor_result3 = *(Ray::Get(actor_object3));
9196
std::cout << "actor_result3 = " << actor_result3 << std::endl;
9297

@@ -107,17 +112,18 @@ int main(int argc, char **argv) {
107112
<< std::endl;
108113

109114
/// create actor and actor function remote call with args passed by value
110-
ActorHandle<Counter> actor4 = Ray::Actor(Counter::FactoryCreate, 10).Remote();
111-
auto r10 = actor4.Task(&Counter::Add, 8).Remote();
115+
ActorHandle<Counter> actor4 = Ray::Actor(Counter::GenericFactoryCreate<int>).Remote(10);
116+
auto r10 = actor4.Task(&Counter::Add).Remote(8);
112117
int actor_result4 = *(Ray::Get(r10));
113118
std::cout << "actor_result4 = " << actor_result4 << std::endl;
114119

115120
/// create actor and task function remote call with args passed by reference
116-
ActorHandle<Counter> actor5 = Ray::Actor(Counter::FactoryCreate, r10, 0).Remote();
117-
auto r11 = actor5.Task(&Counter::Add, r0).Remote();
118-
auto r12 = actor5.Task(&Counter::Add, r11).Remote();
119-
auto r13 = actor5.Task(&Counter::Add, r10).Remote();
120-
auto r14 = actor5.Task(&Counter::Add, r13).Remote();
121+
ActorHandle<Counter> actor5 =
122+
Ray::Actor(Counter::GenericFactoryCreate<int, int>).Remote(r10, 0);
123+
auto r11 = actor5.Task(&Counter::Add).Remote(r0);
124+
auto r12 = actor5.Task(&Counter::Add).Remote(r11);
125+
auto r13 = actor5.Task(&Counter::Add).Remote(r10);
126+
auto r14 = actor5.Task(&Counter::Add).Remote(r13);
121127
auto r15 = Ray::Task(Plus).Remote(r0, r11);
122128
auto r16 = Ray::Task(Plus1).Remote(r15);
123129
int result12 = *(Ray::Get(r12));

cpp/include/ray/api.h

Lines changed: 33 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -79,42 +79,23 @@ class Ray {
7979
/// \param[in] args The function arguments passed by a value or ObjectRef.
8080
/// \return TaskCaller.
8181
template <typename F>
82-
static TaskCaller<boost::callable_traits::return_type_t<F>> Task(F func);
82+
static TaskCaller<F> Task(F func);
8383

8484
/// Generic version of creating an actor
8585
/// It is used for creating an actor, such as: ActorCreator<Counter> creator =
86-
/// Ray::Actor(Counter::FactoryCreate, 1).
86+
/// Ray::Actor(Counter::FactoryCreate<int>).Remote(1);
8787
template <typename ActorType, typename... Args>
88-
static ActorCreator<ActorType> Actor(
89-
CreateActorFunc<ActorType, typename FilterArgType<Args>::type...> create_func,
90-
Args... args);
91-
92-
/// TODO: The bellow specific version of creating an actor will be replaced with generic
93-
/// version later.
94-
#include <ray/api/generated/create_funcs.generated.h>
95-
96-
#include "api/generated/create_actors.generated.h"
88+
static ActorCreator<ActorType> Actor(CreateActorFunc<ActorType, Args...> create_func);
9789

9890
private:
9991
static std::once_flag is_inited_;
10092

101-
template <typename ReturnType, typename FuncType>
102-
static TaskCaller<ReturnType> TaskInternal(FuncType &func);
93+
template <typename FuncType>
94+
static TaskCaller<FuncType> TaskInternal(FuncType &func);
10395

104-
template <typename ActorType, typename FuncType, typename ExecFuncType,
105-
typename... ArgTypes>
96+
template <typename ActorType, typename FuncType, typename ExecFuncType>
10697
static ActorCreator<ActorType> CreateActorInternal(FuncType &func,
107-
ExecFuncType &exec_func,
108-
ArgTypes &... args);
109-
110-
/// Include the `Call` methods for calling actor methods.
111-
/// Used by ActorHandle to implement .Call()
112-
/// It is called by ActorHandle: Ray::Task(&Counter::Add, counter/*instance of
113-
/// Counter*/, 1);
114-
template <typename ReturnType, typename ActorType, typename... Args>
115-
static ActorTaskCaller<ReturnType> Task(
116-
ActorFunc<ActorType, ReturnType, typename FilterArgType<Args>::type...> actor_func,
117-
ActorHandle<ActorType> &actor, Args... args);
98+
ExecFuncType &exec_func);
11899
};
119100

120101
} // namespace api
@@ -170,8 +151,8 @@ inline WaitResult Ray::Wait(const std::vector<ObjectID> &ids, int num_objects,
170151
return ray::internal::RayRuntime()->Wait(ids, num_objects, timeout_ms);
171152
}
172153

173-
template <typename ReturnType, typename FuncType>
174-
inline TaskCaller<ReturnType> Ray::TaskInternal(FuncType &func) {
154+
template <typename FuncType>
155+
inline TaskCaller<FuncType> Ray::TaskInternal(FuncType &func) {
175156
RemoteFunctionPtrHolder ptr{};
176157
ptr.function_pointer = reinterpret_cast<uintptr_t>(func);
177158
if (ray::api::RayConfig::GetInstance()->use_ray_remote) {
@@ -182,55 +163,42 @@ inline TaskCaller<ReturnType> Ray::TaskInternal(FuncType &func) {
182163
}
183164
ptr.function_name = std::move(function_name);
184165
}
185-
return TaskCaller<ReturnType>(ray::internal::RayRuntime().get(), ptr);
166+
return TaskCaller<FuncType>(ray::internal::RayRuntime().get(), ptr);
186167
}
187168

188-
template <typename ActorType, typename FuncType, typename ExecFuncType,
189-
typename... ArgTypes>
169+
template <typename ActorType, typename FuncType, typename ExecFuncType>
190170
inline ActorCreator<ActorType> Ray::CreateActorInternal(FuncType &create_func,
191-
ExecFuncType &exec_func,
192-
ArgTypes &... args) {
193-
std::vector<std::unique_ptr<::ray::TaskArg>> task_args;
194-
Arguments::WrapArgs(&task_args, args...);
195-
RemoteFunctionPtrHolder ptr;
196-
ptr.function_pointer = reinterpret_cast<uintptr_t>(create_func);
197-
ptr.exec_function_pointer = reinterpret_cast<uintptr_t>(exec_func);
198-
return ActorCreator<ActorType>(ray::internal::RayRuntime().get(), ptr,
199-
std::move(task_args));
171+
ExecFuncType &exec_func) {
172+
RemoteFunctionPtrHolder ptr{};
173+
if (ray::api::RayConfig::GetInstance()->use_ray_remote) {
174+
auto function_name =
175+
ray::internal::FunctionManager::Instance().GetFunctionName(create_func);
176+
if (function_name.empty()) {
177+
throw RayException(
178+
"Function not found. Please use RAY_REMOTE to register this function.");
179+
}
180+
181+
ptr.function_name = std::move(function_name);
182+
} else {
183+
ptr.function_pointer = reinterpret_cast<uintptr_t>(create_func);
184+
ptr.exec_function_pointer = reinterpret_cast<uintptr_t>(exec_func);
185+
}
186+
187+
return ActorCreator<ActorType>(ray::internal::RayRuntime().get(), ptr);
200188
}
201189

202190
/// Normal task.
203191
template <typename F>
204-
TaskCaller<boost::callable_traits::return_type_t<F>> Ray::Task(F func) {
205-
using ReturnType = boost::callable_traits::return_type_t<F>;
206-
207-
return TaskInternal<ReturnType>(func);
192+
TaskCaller<F> Ray::Task(F func) {
193+
return TaskInternal<F>(func);
208194
}
209195

210-
/// Generic version of creating an actor.
196+
/// Creating an actor.
211197
template <typename ActorType, typename... Args>
212-
ActorCreator<ActorType> Ray::Actor(
213-
CreateActorFunc<ActorType, typename FilterArgType<Args>::type...> create_func,
214-
Args... args) {
198+
ActorCreator<ActorType> Ray::Actor(CreateActorFunc<ActorType, Args...> create_func) {
215199
return CreateActorInternal<ActorType>(
216200
create_func,
217-
CreateActorExecFunction<ActorType *, typename FilterArgType<Args>::type...>,
218-
args...);
219-
}
220-
221-
/// TODO: The bellow specific version of creating an actor will be replaced with generic
222-
/// version later.
223-
#include <ray/api/generated/create_actors_impl.generated.h>
224-
225-
/// Actor task.
226-
template <typename ReturnType, typename ActorType, typename... Args>
227-
ActorTaskCaller<ReturnType> Ray::Task(
228-
ActorFunc<ActorType, ReturnType, typename FilterArgType<Args>::type...> actor_func,
229-
ActorHandle<ActorType> &actor, Args... args) {
230-
return CallActorInternal<ReturnType, ActorType>(
231-
actor_func,
232-
ActorExecFunction<ReturnType, ActorType, typename FilterArgType<Args>::type...>,
233-
actor, args...);
201+
CreateActorExecFunction<ActorType *, typename FilterArgType<Args>::type...>);
234202
}
235203

236204
} // namespace api

cpp/include/ray/api/actor_creator.h

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ class ActorCreator {
1212
public:
1313
ActorCreator();
1414

15-
ActorCreator(RayRuntime *runtime, RemoteFunctionPtrHolder ptr,
16-
std::vector<std::unique_ptr<::ray::TaskArg>> &&args);
15+
ActorCreator(RayRuntime *runtime, RemoteFunctionPtrHolder ptr)
16+
: runtime_(runtime), ptr_(ptr) {}
1717

18-
ActorHandle<ActorType> Remote();
18+
template <typename... Args>
19+
ActorHandle<ActorType> Remote(Args... args);
1920

2021
private:
2122
RayRuntime *runtime_;
@@ -29,12 +30,9 @@ template <typename ActorType>
2930
ActorCreator<ActorType>::ActorCreator() {}
3031

3132
template <typename ActorType>
32-
ActorCreator<ActorType>::ActorCreator(RayRuntime *runtime, RemoteFunctionPtrHolder ptr,
33-
std::vector<std::unique_ptr<::ray::TaskArg>> &&args)
34-
: runtime_(runtime), ptr_(ptr), args_(std::move(args)) {}
35-
36-
template <typename ActorType>
37-
ActorHandle<ActorType> ActorCreator<ActorType>::Remote() {
33+
template <typename... Args>
34+
ActorHandle<ActorType> ActorCreator<ActorType>::Remote(Args... args) {
35+
Arguments::WrapArgs(&args_, args...);
3836
auto returned_actor_id = runtime_->CreateActor(ptr_, args_);
3937
return ActorHandle<ActorType>(returned_actor_id);
4038
}

cpp/include/ray/api/actor_handle.h

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,6 @@
1111
namespace ray {
1212
namespace api {
1313

14-
template <typename T>
15-
struct FilterArgType {
16-
using type = T;
17-
};
18-
19-
template <typename T>
20-
struct FilterArgType<ObjectRef<T>> {
21-
using type = T;
22-
};
23-
2414
template <typename ActorType, typename ReturnType, typename... Args>
2515
using ActorFunc = ReturnType (ActorType::*)(Args...);
2616

@@ -39,11 +29,8 @@ class ActorHandle {
3929
const ActorID &ID() const;
4030

4131
/// Include the `Call` methods for calling remote functions.
42-
43-
template <typename ReturnType, typename... Args>
44-
ActorTaskCaller<ReturnType> Task(
45-
ActorFunc<ActorType, ReturnType, typename FilterArgType<Args>::type...> actor_func,
46-
Args... args);
32+
template <typename F>
33+
ActorTaskCaller<F> Task(F actor_func);
4734

4835
/// Make ActorHandle serializable
4936
MSGPACK_DEFINE(id_);
@@ -53,22 +40,6 @@ class ActorHandle {
5340
};
5441

5542
// ---------- implementation ----------
56-
template <typename ReturnType, typename ActorType, typename FuncType,
57-
typename ExecFuncType, typename... ArgTypes>
58-
inline ActorTaskCaller<ReturnType> CallActorInternal(FuncType &actor_func,
59-
ExecFuncType &exec_func,
60-
ActorHandle<ActorType> &actor,
61-
ArgTypes &... args) {
62-
std::vector<std::unique_ptr<::ray::TaskArg>> task_args;
63-
Arguments::WrapArgs(&task_args, args...);
64-
RemoteFunctionPtrHolder ptr;
65-
MemberFunctionPtrHolder holder = *(MemberFunctionPtrHolder *)(&actor_func);
66-
ptr.function_pointer = reinterpret_cast<uintptr_t>(holder.value[0]);
67-
ptr.exec_function_pointer = reinterpret_cast<uintptr_t>(exec_func);
68-
return ActorTaskCaller<ReturnType>(internal::RayRuntime().get(), actor.ID(), ptr,
69-
std::move(task_args));
70-
}
71-
7243
template <typename ActorType>
7344
ActorHandle<ActorType>::ActorHandle() {}
7445

@@ -83,14 +54,23 @@ const ActorID &ActorHandle<ActorType>::ID() const {
8354
}
8455

8556
template <typename ActorType>
86-
template <typename ReturnType, typename... Args>
87-
ActorTaskCaller<ReturnType> ActorHandle<ActorType>::Task(
88-
ActorFunc<ActorType, ReturnType, typename FilterArgType<Args>::type...> actor_func,
89-
Args... args) {
90-
return CallActorInternal<ReturnType, ActorType>(
91-
actor_func,
92-
ActorExecFunction<ReturnType, ActorType, typename FilterArgType<Args>::type...>,
93-
*this, args...);
57+
template <typename F>
58+
ActorTaskCaller<F> ActorHandle<ActorType>::Task(F actor_func) {
59+
RemoteFunctionPtrHolder ptr{};
60+
if (ray::api::RayConfig::GetInstance()->use_ray_remote) {
61+
auto function_name =
62+
ray::internal::FunctionManager::Instance().GetFunctionName(actor_func);
63+
if (function_name.empty()) {
64+
throw RayException(
65+
"Function not found. Please use RAY_REMOTE to register this function.");
66+
}
67+
ptr.function_name = std::move(function_name);
68+
return ActorTaskCaller<F>(internal::RayRuntime().get(), id_, ptr);
69+
}
70+
71+
MemberFunctionPtrHolder holder = *(MemberFunctionPtrHolder *)(&actor_func);
72+
ptr.function_pointer = reinterpret_cast<uintptr_t>(holder.value[0]);
73+
return ActorTaskCaller<F>(internal::RayRuntime().get(), id_, ptr);
9474
}
9575

9676
} // namespace api
Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,29 @@
11

22
#pragma once
33

4+
#include <ray/api/arguments.h>
5+
#include <ray/api/exec_funcs.h>
46
#include <ray/api/object_ref.h>
7+
#include <ray/api/static_check.h>
58
#include "ray/core.h"
69

710
namespace ray {
811
namespace api {
912

10-
template <typename ReturnType>
13+
template <typename F>
1114
class ActorTaskCaller {
1215
public:
13-
ActorTaskCaller();
16+
ActorTaskCaller() = default;
1417

1518
ActorTaskCaller(RayRuntime *runtime, ActorID id, RemoteFunctionPtrHolder ptr,
16-
std::vector<std::unique_ptr<::ray::TaskArg>> &&args);
19+
std::vector<std::unique_ptr<::ray::TaskArg>> &&args)
20+
: runtime_(runtime), id_(id), ptr_(ptr), args_(std::move(args)) {}
1721

18-
ObjectRef<ReturnType> Remote();
22+
ActorTaskCaller(RayRuntime *runtime, ActorID id, RemoteFunctionPtrHolder ptr)
23+
: runtime_(runtime), id_(id), ptr_(ptr) {}
24+
25+
template <typename... Args>
26+
ObjectRef<boost::callable_traits::return_type_t<F>> Remote(Args... args);
1927

2028
private:
2129
RayRuntime *runtime_;
@@ -26,19 +34,23 @@ class ActorTaskCaller {
2634

2735
// ---------- implementation ----------
2836

29-
template <typename ReturnType>
30-
ActorTaskCaller<ReturnType>::ActorTaskCaller() {}
31-
32-
template <typename ReturnType>
33-
ActorTaskCaller<ReturnType>::ActorTaskCaller(
34-
RayRuntime *runtime, ActorID id, RemoteFunctionPtrHolder ptr,
35-
std::vector<std::unique_ptr<::ray::TaskArg>> &&args)
36-
: runtime_(runtime), id_(id), ptr_(ptr), args_(std::move(args)) {}
37-
38-
template <typename ReturnType>
39-
ObjectRef<ReturnType> ActorTaskCaller<ReturnType>::Remote() {
37+
template <typename F>
38+
template <typename... Args>
39+
ObjectRef<boost::callable_traits::return_type_t<F>> ActorTaskCaller<F>::Remote(
40+
Args... args) {
41+
using ActorType = boost::callable_traits::class_of_t<F>;
42+
using ReturnType = boost::callable_traits::return_type_t<F>;
43+
StaticCheck<F, Args...>();
44+
if (!ray::api::RayConfig::GetInstance()->use_ray_remote) {
45+
auto exe_func =
46+
ActorExecFunction<ReturnType, ActorType, typename FilterArgType<Args>::type...>;
47+
ptr_.exec_function_pointer = reinterpret_cast<uintptr_t>(exe_func);
48+
}
49+
50+
Arguments::WrapArgs(&args_, args...);
4051
auto returned_object_id = runtime_->CallActor(ptr_, id_, args_);
4152
return ObjectRef<ReturnType>(returned_object_id);
4253
}
54+
4355
} // namespace api
4456
} // namespace ray

0 commit comments

Comments
 (0)