mirror of
https://github.com/wassname/ray.git
synced 2026-07-13 01:17:37 +08:00
[minor] Perf optimizations for direct actor task submission (#6044)
* merge optimizations * fix * fix memory err * optimize * fix tests * fix serialization of method handles * document weakref * fix check * bazel format * disable on 2
This commit is contained in:
+50
-39
@@ -7,6 +7,7 @@ import inspect
|
||||
import logging
|
||||
import six
|
||||
import sys
|
||||
import weakref
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from collections import namedtuple
|
||||
@@ -57,9 +58,8 @@ def method(*args, **kwargs):
|
||||
class ActorMethod(object):
|
||||
"""A class used to invoke an actor method.
|
||||
|
||||
Note: This class is instantiated only while the actor method is being
|
||||
invoked (so that it doesn't keep a reference to the actor handle and
|
||||
prevent it from going out of scope).
|
||||
Note: This class only keeps a weak ref to the actor, unless it has been
|
||||
passed to a remote function. This avoids delays in GC of the actor.
|
||||
|
||||
Attributes:
|
||||
_actor: A handle to the actor.
|
||||
@@ -75,8 +75,13 @@ class ActorMethod(object):
|
||||
"test_decorated_method" in "python/ray/tests/test_actor.py".
|
||||
"""
|
||||
|
||||
def __init__(self, actor, method_name, num_return_vals, decorator=None):
|
||||
self._actor = actor
|
||||
def __init__(self,
|
||||
actor,
|
||||
method_name,
|
||||
num_return_vals,
|
||||
decorator=None,
|
||||
hardref=False):
|
||||
self._actor_ref = weakref.ref(actor)
|
||||
self._method_name = method_name
|
||||
self._num_return_vals = num_return_vals
|
||||
# This is a decorator that is used to wrap the function invocation (as
|
||||
@@ -86,6 +91,11 @@ class ActorMethod(object):
|
||||
# and return the resulting ObjectIDs.
|
||||
self._decorator = decorator
|
||||
|
||||
# Acquire a hard ref to the actor, this is useful mainly when passing
|
||||
# actor method handles to remote functions.
|
||||
if hardref:
|
||||
self._actor_hard_ref = actor
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
raise Exception("Actor methods cannot be called directly. Instead "
|
||||
"of running 'object.{}()', try "
|
||||
@@ -96,15 +106,14 @@ class ActorMethod(object):
|
||||
return self._remote(args, kwargs)
|
||||
|
||||
def _remote(self, args=None, kwargs=None, num_return_vals=None):
|
||||
if args is None:
|
||||
args = []
|
||||
if kwargs is None:
|
||||
kwargs = {}
|
||||
if num_return_vals is None:
|
||||
num_return_vals = self._num_return_vals
|
||||
|
||||
def invocation(args, kwargs):
|
||||
return self._actor._actor_method_call(
|
||||
actor = self._actor_ref()
|
||||
if actor is None:
|
||||
raise RuntimeError("Lost reference to actor")
|
||||
return actor._actor_method_call(
|
||||
self._method_name,
|
||||
args=args,
|
||||
kwargs=kwargs,
|
||||
@@ -116,6 +125,22 @@ class ActorMethod(object):
|
||||
|
||||
return invocation(args, kwargs)
|
||||
|
||||
def __getstate__(self):
|
||||
return {
|
||||
"actor": self._actor_ref(),
|
||||
"method_name": self._method_name,
|
||||
"num_return_vals": self._num_return_vals,
|
||||
"decorator": self._decorator,
|
||||
}
|
||||
|
||||
def __setstate__(self, state):
|
||||
self.__init__(
|
||||
state["actor"],
|
||||
state["method_name"],
|
||||
state["num_return_vals"],
|
||||
state["decorator"],
|
||||
hardref=True)
|
||||
|
||||
|
||||
class ActorClassMetadata(object):
|
||||
"""Metadata for an actor class.
|
||||
@@ -502,6 +527,14 @@ class ActorHandle(object):
|
||||
for method_name in self._ray_method_signatures.keys()
|
||||
}
|
||||
|
||||
for method_name in actor_method_names:
|
||||
method = ActorMethod(
|
||||
self,
|
||||
method_name,
|
||||
self._ray_method_num_return_vals[method_name],
|
||||
decorator=self._ray_method_decorators.get(method_name))
|
||||
setattr(self, method_name, method)
|
||||
|
||||
def _actor_method_call(self,
|
||||
method_name,
|
||||
args=None,
|
||||
@@ -526,13 +559,15 @@ class ActorHandle(object):
|
||||
"""
|
||||
worker = ray.worker.get_global_worker()
|
||||
|
||||
worker.check_connected()
|
||||
|
||||
function_signature = self._ray_method_signatures[method_name]
|
||||
args = args or []
|
||||
kwargs = kwargs or {}
|
||||
function_signature = self._ray_method_signatures[method_name]
|
||||
|
||||
list_args = signature.flatten_args(function_signature, args, kwargs)
|
||||
if not args and not kwargs and not function_signature:
|
||||
list_args = []
|
||||
else:
|
||||
list_args = signature.flatten_args(function_signature, args,
|
||||
kwargs)
|
||||
if worker.mode == ray.LOCAL_MODE:
|
||||
function = getattr(worker.actors[self._actor_id], method_name)
|
||||
object_ids = worker.local_mode_manager.execute(
|
||||
@@ -541,7 +576,7 @@ class ActorHandle(object):
|
||||
object_ids = worker.core_worker.submit_actor_task(
|
||||
self._ray_actor_id,
|
||||
self._ray_function_descriptor_lists[method_name], list_args,
|
||||
num_return_vals, {"CPU": self._ray_actor_method_cpus})
|
||||
num_return_vals, self._ray_actor_method_cpus)
|
||||
|
||||
if len(object_ids) == 1:
|
||||
object_ids = object_ids[0]
|
||||
@@ -554,30 +589,6 @@ class ActorHandle(object):
|
||||
def __dir__(self):
|
||||
return self._ray_actor_method_names
|
||||
|
||||
def __getattribute__(self, attr):
|
||||
try:
|
||||
# Check whether this is an actor method.
|
||||
actor_method_names = object.__getattribute__(
|
||||
self, "_ray_actor_method_names")
|
||||
if attr in actor_method_names:
|
||||
# We create the ActorMethod on the fly here so that the
|
||||
# ActorHandle doesn't need a reference to the ActorMethod.
|
||||
# The ActorMethod has a reference to the ActorHandle and
|
||||
# this was causing cyclic references which were prevent
|
||||
# object deallocation from behaving in a predictable
|
||||
# manner.
|
||||
return ActorMethod(
|
||||
self,
|
||||
attr,
|
||||
self._ray_method_num_return_vals[attr],
|
||||
decorator=self._ray_method_decorators.get(attr))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# If the requested attribute is not a registered method, fall back
|
||||
# to default __getattribute__.
|
||||
return object.__getattribute__(self, attr)
|
||||
|
||||
def __repr__(self):
|
||||
return "Actor({}, {})".format(self._ray_class_name,
|
||||
self._actor_id.hex())
|
||||
|
||||
Reference in New Issue
Block a user