def __init__(self, *args, **kwargs): self._ray_actor_id = random_actor_id() self._ray_actor_methods = { k: v for (k, v) in inspect.getmembers( Class, predicate=(lambda x: (inspect.isfunction(x) or inspect.ismethod(x)))) } # Extract the signatures of each of the methods. This will be used to # catch some errors if the methods are called with inappropriate # arguments. self._ray_method_signatures = dict() for k, v in self._ray_actor_methods.items(): # Print a warning message if the method signature is not supported. # We don't raise an exception because if the actor inherits from a # class that has a method whose signature we don't support, we # there may not be much the user can do about it. signature.check_signature_supported(v, warn=True) self._ray_method_signatures[ k] = signature.extract_signature(v, ignore_first=True) export_actor(self._ray_actor_id, Class, self._ray_actor_methods.keys(), num_cpus, num_gpus, ray.worker.global_worker) # Call __init__ as a remote function. if "__init__" in self._ray_actor_methods.keys(): actor_method_call( self._ray_actor_id, "__init__", self._ray_method_signatures["__init__"], *args, **kwargs) else: print("WARNING: this object has no __init__ method.")
def __init__(self, modified_class, class_id, max_reconstructions, num_cpus, num_gpus, memory, object_store_memory, resources): self.modified_class = modified_class self.class_id = class_id self.class_name = modified_class.__name__ self.max_reconstructions = max_reconstructions self.num_cpus = num_cpus self.num_gpus = num_gpus self.memory = memory self.object_store_memory = object_store_memory self.resources = resources self.last_export_session_and_job = None self.actor_methods = inspect.getmembers( self.modified_class, ray.utils.is_function_or_method) self.actor_method_names = [ method_name for method_name, _ in self.actor_methods ] constructor_name = "__init__" if constructor_name not in self.actor_method_names: # Add __init__ if it does not exist. # Actor creation will be executed with __init__ together. # Assign an __init__ function will avoid many checks later on. def __init__(self): pass self.modified_class.__init__ = __init__ self.actor_method_names.append(constructor_name) self.actor_methods.append((constructor_name, __init__)) # Extract the signatures of each of the methods. This will be used # to catch some errors if the methods are called with inappropriate # arguments. self.method_decorators = {} self.method_signatures = {} self.actor_method_num_return_vals = {} for method_name, method in self.actor_methods: # Print a warning message if the method signature is not # supported. We don't raise an exception because if the actor # inherits from a class that has a method whose signature we # don't support, there may not be much the user can do about it. signature.check_signature_supported(method, warn=True) self.method_signatures[method_name] = signature.extract_signature( method, ignore_first=not ray.utils.is_class_method(method)) # Set the default number of return values for this method. if hasattr(method, "__ray_num_return_vals__"): self.actor_method_num_return_vals[method_name] = ( method.__ray_num_return_vals__) else: self.actor_method_num_return_vals[method_name] = ( ray_constants.DEFAULT_ACTOR_METHOD_NUM_RETURN_VALS) if hasattr(method, "__ray_invocation_decorator__"): self.method_decorators[method_name] = ( method.__ray_invocation_decorator__)
def _manual_init(self, *args, **kwargs): self._ray_actor_id = random_actor_id() # The number of actor method invocations that we've called so far. self._ray_actor_counter = 0 # The actor cursor is a dummy object representing the most recent # actor method invocation. For each subsequent method invocation, # the current cursor should be added as a dependency, and then # updated to reflect the new invocation. self._ray_actor_cursor = None ray_actor_methods = inspect.getmembers( Class, predicate=(lambda x: (inspect.isfunction(x) or inspect.ismethod(x)))) self._ray_actor_methods = {} for actor_method_name, actor_method in ray_actor_methods: self._ray_actor_methods[actor_method_name] = actor_method # Extract the signatures of each of the methods. This will be used # to catch some errors if the methods are called with inappropriate # arguments. self._ray_method_signatures = dict() for k, v in self._ray_actor_methods.items(): # Print a warning message if the method signature is not # supported. We don't raise an exception because if the actor # inherits from a class that has a method whose signature we # don't support, we there may not be much the user can do about # it. signature.check_signature_supported(v, warn=True) self._ray_method_signatures[k] = signature.extract_signature( v, ignore_first=True) # Do not export the actor class or the actor if run in PYTHON_MODE # Instead, instantiate the actor locally and add it to # global_worker's dictionary if ray.worker.global_worker.mode == ray.PYTHON_MODE: ray.worker.global_worker.actors[self._ray_actor_id] = ( Class.__new__(Class)) else: # Export the actor class if it has not been exported yet. if len(exported) == 0: export_actor_class(class_id, Class, self._ray_actor_methods.keys(), checkpoint_interval, ray.worker.global_worker) exported.append(0) # Export the actor. export_actor(self._ray_actor_id, class_id, self._ray_actor_methods.keys(), num_cpus, num_gpus, ray.worker.global_worker) # Call __init__ as a remote function. if "__init__" in self._ray_actor_methods.keys(): self._actor_method_call("__init__", args=args, kwargs=kwargs) else: print("WARNING: this object has no __init__ method.")
def __init__(self, modified_class, class_id, max_reconstructions, num_cpus, num_gpus, resources, actor_method_cpus): self._modified_class = modified_class self._class_id = class_id self._class_name = modified_class.__name__ self._max_reconstructions = max_reconstructions self._num_cpus = num_cpus self._num_gpus = num_gpus self._resources = resources self._actor_method_cpus = actor_method_cpus self._exported = False self._actor_methods = inspect.getmembers( self._modified_class, ray.utils.is_function_or_method) self._actor_method_names = [ method_name for method_name, _ in self._actor_methods ] constructor_name = "__init__" if constructor_name not in self._actor_method_names: # Add __init__ if it does not exist. # Actor creation will be executed with __init__ together. # Assign an __init__ function will avoid many checks later on. def __init__(self): pass self._modified_class.__init__ = __init__ self._actor_method_names.append(constructor_name) self._actor_methods.append((constructor_name, __init__)) # Extract the signatures of each of the methods. This will be used # to catch some errors if the methods are called with inappropriate # arguments. self._method_signatures = {} self._actor_method_num_return_vals = {} for method_name, method in self._actor_methods: # Print a warning message if the method signature is not # supported. We don't raise an exception because if the actor # inherits from a class that has a method whose signature we # don't support, there may not be much the user can do about it. signature.check_signature_supported(method, warn=True) self._method_signatures[method_name] = signature.extract_signature( method, ignore_first=not ray.utils.is_class_method(method)) # Set the default number of return values for this method. if hasattr(method, "__ray_num_return_vals__"): self._actor_method_num_return_vals[method_name] = ( method.__ray_num_return_vals__) else: self._actor_method_num_return_vals[method_name] = ( DEFAULT_ACTOR_METHOD_NUM_RETURN_VALS)
def _manual_init(self, *args, **kwargs): self._ray_actor_id = random_actor_id() self._ray_actor_methods = { k: v for (k, v) in inspect.getmembers( Class, predicate=(lambda x: (inspect.isfunction(x) or inspect.ismethod(x)))) } # Extract the signatures of each of the methods. This will be used # to catch some errors if the methods are called with inappropriate # arguments. self._ray_method_signatures = dict() for k, v in self._ray_actor_methods.items(): # Print a warning message if the method signature is not # supported. We don't raise an exception because if the actor # inherits from a class that has a method whose signature we # don't support, we there may not be much the user can do about # it. signature.check_signature_supported(v, warn=True) self._ray_method_signatures[k] = signature.extract_signature( v, ignore_first=True) # Create objects to wrap method invocations. This is done so that # we can invoke methods with actor.method.remote() instead of # actor.method(). self._actor_method_invokers = dict() for k, v in self._ray_actor_methods.items(): self._actor_method_invokers[k] = ActorMethod( k, self._ray_actor_id, self._ray_method_signatures[k]) # Export the actor class if it has not been exported yet. if len(exported) == 0: export_actor_class(class_id, Class, self._ray_actor_methods.keys(), checkpoint_interval, ray.worker.global_worker) exported.append(0) # Export the actor. export_actor(self._ray_actor_id, class_id, self._ray_actor_methods.keys(), num_cpus, num_gpus, ray.worker.global_worker) # Call __init__ as a remote function. if "__init__" in self._ray_actor_methods.keys(): actor_method_call(self._ray_actor_id, "__init__", self._ray_method_signatures["__init__"], *args, **kwargs) else: print("WARNING: this object has no __init__ method.")
def create(cls, modified_class, actor_creation_function_descriptor): # Try to create an instance from cache. cached_meta = cls._cache.get(actor_creation_function_descriptor) if cached_meta is not None: return cached_meta # Create an instance without __init__ called. self = cls.__new__(cls) actor_methods = inspect.getmembers(modified_class, ray.utils.is_function_or_method) self.methods = dict(actor_methods) # Extract the signatures of each of the methods. This will be used # to catch some errors if the methods are called with inappropriate # arguments. self.decorators = {} self.signatures = {} self.num_return_vals = {} for method_name, method in actor_methods: # Whether or not this method requires binding of its first # argument. For class and static methods, we do not want to bind # the first argument, but we do for instance methods is_bound = (ray.utils.is_class_method(method) or ray.utils.is_static_method(modified_class, method_name)) # Print a warning message if the method signature is not # supported. We don't raise an exception because if the actor # inherits from a class that has a method whose signature we # don't support, there may not be much the user can do about it. self.signatures[method_name] = signature.extract_signature( method, ignore_first=not is_bound) # Set the default number of return values for this method. if hasattr(method, "__ray_num_return_vals__"): self.num_return_vals[method_name] = ( method.__ray_num_return_vals__) else: self.num_return_vals[method_name] = ( ray_constants.DEFAULT_ACTOR_METHOD_NUM_RETURN_VALS) if hasattr(method, "__ray_invocation_decorator__"): self.decorators[method_name] = ( method.__ray_invocation_decorator__) # Update cache. cls._cache[actor_creation_function_descriptor] = self return self
def __init__(self, modified_class, class_id, checkpoint_interval, num_cpus, num_gpus, resources, actor_method_cpus): self._modified_class = modified_class self._class_id = class_id self._class_name = modified_class.__name__ self._checkpoint_interval = checkpoint_interval self._num_cpus = num_cpus self._num_gpus = num_gpus self._resources = resources self._actor_method_cpus = actor_method_cpus self._exported = False # Get the actor methods of the given class. def pred(x): return (inspect.isfunction(x) or inspect.ismethod(x) or is_cython(x)) self._actor_methods = inspect.getmembers(self._modified_class, predicate=pred) # Extract the signatures of each of the methods. This will be used # to catch some errors if the methods are called with inappropriate # arguments. self._method_signatures = {} self._actor_method_num_return_vals = {} for method_name, method in self._actor_methods: # Print a warning message if the method signature is not # supported. We don't raise an exception because if the actor # inherits from a class that has a method whose signature we # don't support, there may not be much the user can do about it. signature.check_signature_supported(method, warn=True) self._method_signatures[method_name] = signature.extract_signature( method, ignore_first=True) # Set the default number of return values for this method. if hasattr(method, "__ray_num_return_vals__"): self._actor_method_num_return_vals[method_name] = ( method.__ray_num_return_vals__) else: self._actor_method_num_return_vals[method_name] = ( DEFAULT_ACTOR_METHOD_NUM_RETURN_VALS) self._actor_method_names = [ method_name for method_name, _ in self._actor_methods ]
def _submit(self, args, kwargs, num_cpus=None, num_gpus=None, resources=None): """Create an actor. This method allows more flexibility than the remote method because resource requirements can be specified and override the defaults in the decorator. Args: args: The arguments to forward to the actor constructor. kwargs: The keyword arguments to forward to the actor constructor. num_cpus: The number of CPUs required by the actor creation task. num_gpus: The number of GPUs required by the actor creation task. resources: The custom resources required by the actor creation task. Returns: A handle to the newly created actor. """ if ray.worker.global_worker.mode is None: raise Exception("Actors cannot be created before ray.init() " "has been called.") actor_id = ray.local_scheduler.ObjectID(_random_string()) # The actor cursor is a dummy object representing the most recent # actor method invocation. For each subsequent method invocation, # the current cursor should be added as a dependency, and then # updated to reflect the new invocation. actor_cursor = None # Get the actor methods of the given class. def pred(x): return (inspect.isfunction(x) or inspect.ismethod(x) or is_cython(x)) actor_methods = inspect.getmembers(self._modified_class, predicate=pred) # Extract the signatures of each of the methods. This will be used # to catch some errors if the methods are called with inappropriate # arguments. method_signatures = dict() for k, v in actor_methods: # Print a warning message if the method signature is not # supported. We don't raise an exception because if the actor # inherits from a class that has a method whose signature we # don't support, there may not be much the user can do about it. signature.check_signature_supported(v, warn=True) method_signatures[k] = signature.extract_signature( v, ignore_first=True) actor_method_names = [method_name for method_name, _ in actor_methods] actor_method_num_return_vals = [] for _, method in actor_methods: if hasattr(method, "__ray_num_return_vals__"): actor_method_num_return_vals.append( method.__ray_num_return_vals__) else: actor_method_num_return_vals.append(1) # Do not export the actor class or the actor if run in PYTHON_MODE # Instead, instantiate the actor locally and add it to # global_worker's dictionary if ray.worker.global_worker.mode == ray.PYTHON_MODE: ray.worker.global_worker.actors[actor_id] = ( self._modified_class.__new__(self._modified_class)) else: # Export the actor. if not self._exported: export_actor_class(self._class_id, self._modified_class, actor_method_names, actor_method_num_return_vals, self._checkpoint_interval, ray.worker.global_worker) self._exported = True actor_cursor = export_actor(actor_id, self._class_id, self._class_name, actor_method_names, actor_method_num_return_vals, self._actor_creation_resources, self._actor_method_cpus, ray.worker.global_worker) # We initialize the actor counter at 1 to account for the actor # creation task. actor_counter = 1 actor_handle = ActorHandle(actor_id, self._class_name, actor_cursor, actor_counter, actor_method_names, actor_method_num_return_vals, method_signatures, actor_cursor, self._actor_method_cpus, ray.worker.global_worker.task_driver_id) # Call __init__ as a remote function. if "__init__" in actor_handle._ray_actor_method_names: actor_handle.__init__.remote(*args, **kwargs) else: if len(args) != 0 or len(kwargs) != 0: raise Exception("Arguments cannot be passed to the actor " "constructor because this actor class has no " "__init__ method.") return actor_handle
def remote(cls, *args, **kwargs): if ray.worker.global_worker.mode is None: raise Exception("Actors cannot be created before ray.init() " "has been called.") actor_id = random_actor_id() # The ID for this instance of ActorHandle. These should be unique # across instances with the same _ray_actor_id. actor_handle_id = ray.local_scheduler.ObjectID( ray.worker.NIL_ACTOR_ID) # The actor cursor is a dummy object representing the most recent # actor method invocation. For each subsequent method invocation, # the current cursor should be added as a dependency, and then # updated to reflect the new invocation. actor_cursor = None # The number of actor method invocations that we've called so far. actor_counter = 0 # Get the actor methods of the given class. actor_methods = inspect.getmembers( Class, predicate=(lambda x: (inspect.isfunction(x) or inspect.ismethod(x) or is_cython(x)))) # Extract the signatures of each of the methods. This will be used # to catch some errors if the methods are called with inappropriate # arguments. method_signatures = dict() for k, v in actor_methods: # Print a warning message if the method signature is not # supported. We don't raise an exception because if the actor # inherits from a class that has a method whose signature we # don't support, we there may not be much the user can do about # it. signature.check_signature_supported(v, warn=True) method_signatures[k] = signature.extract_signature( v, ignore_first=True) actor_method_names = [method_name for method_name, _ in actor_methods] actor_method_num_return_vals = [] for _, method in actor_methods: if hasattr(method, "__ray_num_return_vals__"): actor_method_num_return_vals.append( method.__ray_num_return_vals__) else: actor_method_num_return_vals.append(1) # Do not export the actor class or the actor if run in PYTHON_MODE # Instead, instantiate the actor locally and add it to # global_worker's dictionary if ray.worker.global_worker.mode == ray.PYTHON_MODE: ray.worker.global_worker.actors[actor_id] = ( Class.__new__(Class)) else: # Export the actor. if not exported: export_actor_class(class_id, Class, actor_method_names, actor_method_num_return_vals, checkpoint_interval, ray.worker.global_worker) exported.append(0) actor_cursor = export_actor(actor_id, class_id, class_name, actor_method_names, actor_method_num_return_vals, actor_creation_resources, actor_method_cpus, ray.worker.global_worker) # Instantiate the actor handle. actor_object = cls.__new__(cls) actor_object._manual_init(actor_id, class_id, actor_handle_id, actor_cursor, actor_counter, actor_method_names, actor_method_num_return_vals, method_signatures, checkpoint_interval, actor_cursor, actor_creation_resources, actor_method_cpus) # Call __init__ as a remote function. if "__init__" in actor_object._ray_actor_method_names: actor_object._actor_method_call("__init__", args=args, kwargs=kwargs, dependency=actor_cursor) else: print("WARNING: this object has no __init__ method.") return actor_object