Remove actor handle IDs (#5889)

* Remove actor handle ID from main ActorHandle constructor

* Set the actor caller ID when calling submit task instead of in the actor handle

* Remove ActorHandle::Fork, remove actor handle ID from protobuf

* Make inner actor handle const, remove new_actor_handles

* Move caller ID into the common task spec, start refactoring raylet

* Some fixes for forking actor handles

* Store ActorHandle state in CoreWorker, only expose actor ID to Python

* Remove some unused fields

* lint

* doc

* fix merge

* Remove ActorHandleID from python/cpp

* doc

* Fix core worker test

* Move actor table subscription to CoreWorker, reset actor handles on actor failure

* lint

* Remove GCS client from direct actor

* fix tests

* Fix

* Fix tests for raylet codepath

* Fix local mode

* Fix multithreaded test

* Fix AsyncSubscribe issue...

* doc

* fix serve

* Revert bazel
This commit is contained in:
Stephanie Wang
2019-10-17 12:36:34 -04:00
committed by GitHub
parent d70abcfd70
commit 3ac8592dcf
37 changed files with 507 additions and 656 deletions
-2
View File
@@ -65,7 +65,6 @@ except ImportError as e:
from ray._raylet import (
ActorCheckpointID,
ActorClassID,
ActorHandleID,
ActorID,
ClientID,
Config as _Config,
@@ -154,7 +153,6 @@ __all__ = [
__all__ += [
"ActorCheckpointID",
"ActorClassID",
"ActorHandleID",
"ActorID",
"ClientID",
"JobID",
+43 -5
View File
@@ -23,6 +23,7 @@ from libcpp.vector cimport vector as c_vector
from cython.operator import dereference, postincrement
from ray.includes.common cimport (
CActorHandle,
CLanguage,
CRayObject,
CRayStatus,
@@ -432,6 +433,13 @@ cdef class CoreWorker:
with nogil:
self.core_worker.get().SetCurrentTaskId(c_task_id)
def set_actor_id(self, ActorID actor_id):
cdef:
CActorID c_actor_id = actor_id.native()
with nogil:
self.core_worker.get().SetActorId(c_actor_id)
def get_current_task_id(self):
return TaskID(self.core_worker.get().GetCurrentTaskId().Binary())
@@ -622,6 +630,7 @@ cdef class CoreWorker:
CRayFunction ray_function
c_vector[CTaskArg] args_vector
c_vector[CObjectID] return_ids
CTaskID caller_id
with profiling.profile("submit_task"):
prepare_resources(resources, &c_resources)
@@ -629,9 +638,11 @@ cdef class CoreWorker:
ray_function = CRayFunction(
LANGUAGE_PYTHON, string_vector_from_list(function_descriptor))
prepare_args(args, &args_vector)
caller_id = self.core_worker.get().GetCallerId()
with nogil:
check_status(self.core_worker.get().Tasks().SubmitTask(
caller_id,
ray_function, args_vector, task_options, &return_ids))
return VectorToObjectIDs(return_ids)
@@ -643,12 +654,13 @@ cdef class CoreWorker:
resources,
placement_resources):
cdef:
ActorHandle actor_handle = ActorHandle.__new__(ActorHandle)
unique_ptr[CActorHandle] actor_handle
CRayFunction ray_function
c_vector[CTaskArg] args_vector
c_vector[c_string] dynamic_worker_options
unordered_map[c_string, double] c_resources
unordered_map[c_string, double] c_placement_resources
CTaskID caller_id
with profiling.profile("submit_task"):
prepare_resources(resources, &c_resources)
@@ -656,30 +668,38 @@ cdef class CoreWorker:
ray_function = CRayFunction(
LANGUAGE_PYTHON, string_vector_from_list(function_descriptor))
prepare_args(args, &args_vector)
caller_id = self.core_worker.get().GetCallerId()
with nogil:
check_status(self.core_worker.get().Tasks().CreateActor(
caller_id,
ray_function, args_vector,
CActorCreationOptions(
max_reconstructions, False, c_resources,
c_placement_resources, dynamic_worker_options),
&actor_handle.inner))
&actor_handle))
return actor_handle
actor_id = ActorID(actor_handle.get().GetActorID().Binary())
inserted = self.core_worker.get().AddActorHandle(
move(actor_handle))
assert inserted, "Actor {} already exists".format(actor_id)
return actor_id
def submit_actor_task(self,
ActorHandle handle,
ActorID actor_id,
function_descriptor,
args,
int num_return_vals,
resources):
cdef:
CActorID c_actor_id = actor_id.native()
unordered_map[c_string, double] c_resources
CTaskOptions task_options
CRayFunction ray_function
c_vector[CTaskArg] args_vector
c_vector[CObjectID] return_ids
CTaskID caller_id
with profiling.profile("submit_task"):
prepare_resources(resources, &c_resources)
@@ -687,10 +707,13 @@ cdef class CoreWorker:
ray_function = CRayFunction(
LANGUAGE_PYTHON, string_vector_from_list(function_descriptor))
prepare_args(args, &args_vector)
caller_id = self.core_worker.get().GetCallerId()
with nogil:
check_status(self.core_worker.get().Tasks().SubmitActorTask(
handle.inner.get()[0], ray_function,
caller_id,
self.core_worker.get().GetActorHandle(c_actor_id),
ray_function,
args_vector, task_options, &return_ids))
return VectorToObjectIDs(return_ids)
@@ -702,3 +725,18 @@ cdef class CoreWorker:
return ProfileEvent.make(
self.core_worker.get().CreateProfileEvent(c_event_type),
extra_data)
def deserialize_actor_handle(self, c_string bytes):
cdef:
unique_ptr[CActorHandle] actor_handle
actor_handle.reset(new CActorHandle(bytes))
actor_id = ActorID(actor_handle.get().GetActorID().Binary())
self.core_worker.get().AddActorHandle(move(actor_handle))
return actor_id
def serialize_actor_handle(self, ActorID actor_id):
cdef:
CActorID c_actor_id = actor_id.native()
c_string output
self.core_worker.get().GetActorHandle(c_actor_id).Serialize(&output)
return output
+19 -20
View File
@@ -16,7 +16,7 @@ import ray.ray_constants as ray_constants
import ray._raylet
import ray.signature as signature
import ray.worker
from ray import ActorID, ActorHandleID, ActorClassID, profiling
from ray import ActorID, ActorClassID, profiling
logger = logging.getLogger(__name__)
@@ -372,9 +372,6 @@ class ActorClass(object):
actor_id = ActorID.from_random()
worker.actors[actor_id] = meta.modified_class(
*copy.deepcopy(args), **copy.deepcopy(kwargs))
core_handle = ray._raylet.ActorHandle(
actor_id, ActorHandleID.nil(), worker.current_job_id,
function_descriptor.get_function_descriptor_list())
else:
# Export the actor.
if (meta.last_export_session_and_job !=
@@ -404,13 +401,13 @@ class ActorClass(object):
function_signature = meta.method_signatures[function_name]
creation_args = signature.extend_args(function_signature, args,
kwargs)
core_handle = worker.core_worker.create_actor(
actor_id = worker.core_worker.create_actor(
function_descriptor.get_function_descriptor_list(),
creation_args, meta.max_reconstructions, resources,
actor_placement_resources)
actor_handle = ActorHandle(
core_handle,
actor_id,
meta.modified_class.__module__,
meta.class_name,
meta.actor_method_names,
@@ -436,7 +433,7 @@ class ActorHandle(object):
cloudpickle).
Attributes:
_ray_core_handle: Core worker actor handle for this actor.
_ray_actor_id: Actor ID.
_ray_module_name: The module name of this actor.
_ray_actor_method_names: The names of the actor methods.
_ray_method_decorators: Optional decorators for the function
@@ -454,7 +451,7 @@ class ActorHandle(object):
"""
def __init__(self,
core_handle,
actor_id,
module_name,
class_name,
actor_method_names,
@@ -464,7 +461,7 @@ class ActorHandle(object):
actor_method_cpus,
session_and_job,
original_handle=False):
self._ray_core_handle = core_handle
self._ray_actor_id = actor_id
self._ray_module_name = module_name
self._ray_original_handle = original_handle
self._ray_actor_method_names = actor_method_names
@@ -518,7 +515,7 @@ class ActorHandle(object):
function, function_descriptor, args, num_return_vals)
else:
object_ids = worker.core_worker.submit_actor_task(
self._ray_core_handle,
self._ray_actor_id,
function_descriptor.get_function_descriptor_list(), args,
num_return_vals, {"CPU": self._ray_actor_method_cpus})
@@ -579,8 +576,8 @@ class ActorHandle(object):
# and we don't need to send `__ray_terminate__` again.
logger.warning(
"Actor is garbage collected in the wrong driver." +
" Actor id = %s, class name = %s.",
self._ray_core_handle.actor_id(), self._ray_class_name)
" Actor id = %s, class name = %s.", self._ray_actor_id,
self._ray_class_name)
return
if worker.connected and self._ray_original_handle:
# TODO(rkn): Should we be passing in the actor cursor as a
@@ -589,11 +586,7 @@ class ActorHandle(object):
@property
def _actor_id(self):
return self._ray_core_handle.actor_id()
@property
def _actor_handle_id(self):
return self._ray_core_handle.actor_handle_id()
return self._ray_actor_id
def _serialization_helper(self, ray_forking):
"""This is defined in order to make pickling work.
@@ -605,8 +598,13 @@ class ActorHandle(object):
Returns:
A dictionary of the information needed to reconstruct the object.
"""
worker = ray.worker.get_global_worker()
worker.check_connected()
state = {
"core_handle": self._ray_core_handle.fork(ray_forking).to_bytes(),
# Local mode just uses the actor ID.
"core_handle": worker.core_worker.serialize_actor_handle(
self._ray_actor_id)
if hasattr(worker, "core_worker") else self._ray_actor_id,
"module_name": self._ray_module_name,
"class_name": self._ray_class_name,
"actor_method_names": self._ray_actor_method_names,
@@ -632,8 +630,9 @@ class ActorHandle(object):
self.__init__(
# TODO(swang): Accessing the worker's current task ID is not
# thread-safe.
ray._raylet.ActorHandle.from_bytes(state["core_handle"],
worker.current_task_id),
# Local mode just uses the actor ID.
worker.core_worker.deserialize_actor_handle(state["core_handle"])
if hasattr(worker, "core_worker") else state["core_handle"],
state["module_name"],
state["class_name"],
state["actor_method_names"],
+2 -2
View File
@@ -27,11 +27,11 @@ class MetricMonitor:
return True
def add_target(self, target_handle):
hex_id = target_handle._ray_core_handle.actor_id().hex()
hex_id = target_handle._actor_id.hex()
self.actor_handles[hex_id] = target_handle
def remove_target(self, target_handle):
hex_id = target_handle._ray_core_handle.actor_id().hex()
hex_id = target_handle._actor_id.hex()
self.actor_handles.pop(hex_id)
def scrape(self):
+1 -12
View File
@@ -8,7 +8,6 @@ from libcpp.vector cimport vector as c_vector
from ray.includes.unique_ids cimport (
CActorID,
CActorHandleID,
CJobID,
CWorkerID,
CObjectID,
@@ -199,19 +198,9 @@ cdef extern from "ray/core_worker/task_interface.h" nogil:
const c_vector[c_string] &dynamic_worker_options)
cdef cppclass CActorHandle "ray::ActorHandle":
CActorHandle(
const CActorID &actor_id, const CActorHandleID &actor_handle_id,
const CJobID &job_id, const CObjectID &initial_cursor,
const CLanguage actor_language, c_bool is_direct_call,
const c_vector[c_string] &actor_creation_task_function_descriptor)
CActorHandle(CActorHandle &other, c_bool in_band)
CActorHandle(
const c_string &serialized, const CTaskID &current_task_id)
CActorHandle(const c_string &serialized)
CActorID GetActorID() const
CActorHandleID GetActorHandleID() const
unique_ptr[CActorHandle] Fork()
unique_ptr[CActorHandle] ForkForSerialization()
void Serialize(c_string *output)
cdef extern from "ray/gcs/gcs_client_interface.h" nogil:
-46
View File
@@ -3,7 +3,6 @@ from libcpp.string cimport string as c_string
from libcpp.vector cimport vector as c_vector
from ray.includes.common cimport (
CActorHandle,
CGcsClientOptions,
)
@@ -25,48 +24,3 @@ cdef class GcsClientOptions:
cdef CGcsClientOptions* native(self):
return <CGcsClientOptions*>(self.inner.get())
cdef class ActorHandle:
"""Cython wrapper class of C++ `ray::ActorHandle`."""
cdef:
unique_ptr[CActorHandle] inner
def __init__(self, ActorID actor_id, ActorHandleID actor_handle_id,
JobID job_id, list creation_function_descriptor):
cdef:
c_vector[c_string] c_descriptor
ObjectID cursor = ObjectID.from_random()
c_descriptor = string_vector_from_list(creation_function_descriptor)
self.inner.reset(new CActorHandle(
actor_id.native(), actor_handle_id.native(), job_id.native(),
cursor.native(), LANGUAGE_PYTHON, False, c_descriptor))
def fork(self, c_bool ray_forking):
cdef:
ActorHandle other = ActorHandle.__new__(ActorHandle)
if ray_forking:
other.inner = self.inner.get().Fork()
else:
other.inner = self.inner.get().ForkForSerialization()
return other
@staticmethod
def from_bytes(c_string bytes, TaskID current_task_id):
cdef:
ActorHandle self = ActorHandle.__new__(ActorHandle)
self.inner.reset(new CActorHandle(bytes, current_task_id.native()))
return self
def to_bytes(self):
cdef:
c_string output
self.inner.get().Serialize(&output)
return output
def actor_id(self):
return ActorID(self.inner.get().GetActorID().Binary())
def actor_handle_id(self):
return ActorHandleID(self.inner.get().GetActorHandleID().Binary())
+9
View File
@@ -5,6 +5,7 @@ from libcpp.string cimport string as c_string
from libcpp.vector cimport vector as c_vector
from ray.includes.unique_ids cimport (
CActorID,
CJobID,
CTaskID,
CObjectID,
@@ -32,13 +33,16 @@ cdef extern from "ray/core_worker/profiling.h" nogil:
cdef extern from "ray/core_worker/task_interface.h" namespace "ray" nogil:
cdef cppclass CTaskSubmissionInterface "CoreWorkerTaskInterface":
CRayStatus SubmitTask(
const CTaskID &caller_id,
const CRayFunction &function, const c_vector[CTaskArg] &args,
const CTaskOptions &options, c_vector[CObjectID] *return_ids)
CRayStatus CreateActor(
const CTaskID &caller_id,
const CRayFunction &function, const c_vector[CTaskArg] &args,
const CActorCreationOptions &options,
unique_ptr[CActorHandle] *handle)
CRayStatus SubmitActorTask(
const CTaskID &caller_id,
CActorHandle &handle, const CRayFunction &function,
const c_vector[CTaskArg] &args, const CTaskOptions &options,
c_vector[CObjectID] *return_ids)
@@ -87,3 +91,8 @@ cdef extern from "ray/core_worker/core_worker.h" nogil:
void SetCurrentJobId(const CJobID &job_id)
CTaskID GetCurrentTaskId()
void SetCurrentTaskId(const CTaskID &task_id)
void SetActorId(const CActorID &actor_id)
const CActorID &GetActorId()
CTaskID GetCallerId()
c_bool AddActorHandle(unique_ptr[CActorHandle] handle)
CActorHandle &GetActorHandle(const CActorID &actor_id)
-3
View File
@@ -10,7 +10,6 @@ from ray.includes.common cimport (
ResourceSet,
)
from ray.includes.unique_ids cimport (
CActorHandleID,
CActorID,
CJobID,
CObjectID,
@@ -71,10 +70,8 @@ cdef extern from "ray/common/task/task_spec.h" nogil:
CObjectID PreviousActorTaskDummyObjectId() const
uint64_t MaxActorReconstructions() const
CActorID ActorId() const
CActorHandleID ActorHandleId() const
uint64_t ActorCounter() const
CObjectID ActorDummyObject() const
c_vector[CActorHandleID] NewActorHandles() const
cdef extern from "ray/common/task/task_execution_spec.h" nogil:
-5
View File
@@ -68,11 +68,6 @@ cdef extern from "ray/common/id.h" namespace "ray" nogil:
CActorID Of(CJobID job_id, CTaskID parent_task_id,
int64_t parent_task_counter)
cdef cppclass CActorHandleID "ray::ActorHandleID"(CUniqueID):
@staticmethod
CActorHandleID FromBinary(const c_string &binary)
cdef cppclass CClientID "ray::ClientID"(CUniqueID):
@staticmethod
-12
View File
@@ -11,7 +11,6 @@ import os
from ray.includes.unique_ids cimport (
CActorCheckpointID,
CActorClassID,
CActorHandleID,
CActorID,
CClientID,
CConfigID,
@@ -343,16 +342,6 @@ cdef class ActorID(BaseID):
return self.data.Hash()
cdef class ActorHandleID(UniqueID):
def __init__(self, id):
check_id(id)
self.data = CActorHandleID.FromBinary(<c_string>id)
cdef CActorHandleID native(self):
return <CActorHandleID>self.data
cdef class ActorCheckpointID(UniqueID):
def __init__(self, id):
@@ -385,7 +374,6 @@ cdef class ActorClassID(UniqueID):
_ID_TYPES = [
ActorCheckpointID,
ActorClassID,
ActorHandleID,
ActorID,
ClientID,
JobID,
+5 -5
View File
@@ -1447,14 +1447,14 @@ def test_multithreading(ray_start_2_cpus):
time.sleep(delay_ms / 1000.0)
return value
@ray.remote
class Echo(object):
def echo(self, value):
return value
def test_api_in_multi_threads():
"""Test using Ray api in multiple threads."""
@ray.remote
class Echo(object):
def echo(self, value):
return value
# Test calling remote functions in multiple threads.
def test_remote_call():
value = random.randint(0, 1000000)
+2
View File
@@ -867,7 +867,9 @@ class Worker(object):
# TODO(rkn): It would be preferable for actor creation tasks to share
# more of the code path with regular task execution.
if task.is_actor_creation_task():
# TODO: Remove Worker.actor_id and just use CoreWorker.GetActorId.
self.actor_id = task.actor_creation_id()
self.core_worker.set_actor_id(task.actor_creation_id())
self.actor_creation_task_id = task.task_id()
actor_class = self.function_actor_manager.load_actor_class(
job_id, function_descriptor)