mirror of
https://github.com/wassname/ray.git
synced 2026-07-25 13:30:52 +08:00
Change Python's ObjectID to ObjectRef (#9353)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# This workload stresses distributed reference counting by passing and
|
||||
# returning serialized ObjectIDs.
|
||||
# returning serialized ObjectRefs.
|
||||
|
||||
import time
|
||||
import json
|
||||
@@ -50,8 +50,8 @@ def churn():
|
||||
|
||||
@ray.remote(max_retries=0)
|
||||
def child(*xs):
|
||||
oid = ray.put(np.zeros(1024 * 1024, dtype=np.uint8))
|
||||
return oid
|
||||
obj_ref = ray.put(np.zeros(1024 * 1024, dtype=np.uint8))
|
||||
return obj_ref
|
||||
|
||||
|
||||
@ray.remote(max_retries=0)
|
||||
|
||||
@@ -110,7 +110,7 @@ def create_array(size):
|
||||
@ray.remote
|
||||
def no_op(*values):
|
||||
# The reason that this function takes *values is so that we can pass in
|
||||
# an arbitrary number of object IDs to create task dependencies.
|
||||
# an arbitrary number of object refs to create task dependencies.
|
||||
return 1
|
||||
|
||||
|
||||
@@ -134,16 +134,16 @@ def warm_up_cluster(num_nodes, object_store_memory):
|
||||
size = object_store_memory * 2 // 5
|
||||
num_objects = 2
|
||||
while size > 0:
|
||||
object_ids = []
|
||||
object_refs = []
|
||||
for i in range(num_nodes):
|
||||
for _ in range(num_objects):
|
||||
object_ids += [
|
||||
object_refs += [
|
||||
create_array._remote(args=[size], resources={str(i): 1})
|
||||
]
|
||||
size = size // 2
|
||||
num_objects = min(num_objects * 2, 1000)
|
||||
for object_id in object_ids:
|
||||
ray.get(object_id)
|
||||
for object_ref in object_refs:
|
||||
ray.get(object_ref)
|
||||
logger.warning("Finished warming up the object store.")
|
||||
|
||||
# Invoke all of the remote functions once so that the definitions are
|
||||
|
||||
@@ -70,8 +70,8 @@ class Network(object):
|
||||
# yapf: disable
|
||||
# __actor_start__
|
||||
NetworkActor = Network.remote()
|
||||
result_object_id = NetworkActor.train.remote()
|
||||
ray.get(result_object_id)
|
||||
result_object_ref = NetworkActor.train.remote()
|
||||
ray.get(result_object_ref)
|
||||
# __actor_end__
|
||||
# yapf: enable
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ if __name__ == "__main__":
|
||||
# Similarly, full_grad is a function which takes some parameters theta, and
|
||||
# computes the gradient of the loss. Internally, these functions use Ray to
|
||||
# distribute the computation of the loss and the gradient over the data
|
||||
# that is represented by the remote object IDs x_batches and y_batches and
|
||||
# that is represented by the remote object refs x_batches and y_batches and
|
||||
# which is potentially distributed over a cluster. However, these details
|
||||
# are hidden from scipy.optimize.fmin_l_bfgs_b, which simply uses it to run
|
||||
# the L-BFGS algorithm.
|
||||
|
||||
@@ -169,16 +169,16 @@ def evaluate_hyperparameters(config):
|
||||
# Keep track of the best hyperparameters and the best accuracy.
|
||||
best_hyperparameters = None
|
||||
best_accuracy = 0
|
||||
# A list holding the object IDs for all of the experiments that we have
|
||||
# A list holding the object refs for all of the experiments that we have
|
||||
# launched but have not yet been processed.
|
||||
remaining_ids = []
|
||||
# A dictionary mapping an experiment's object ID to its hyperparameters.
|
||||
# A dictionary mapping an experiment's object ref to its hyperparameters.
|
||||
# hyerparameters used for that experiment.
|
||||
hyperparameters_mapping = {}
|
||||
|
||||
###########################################################################
|
||||
# Launch asynchronous parallel tasks for evaluating different
|
||||
# hyperparameters. ``accuracy_id`` is an ObjectID that acts as a handle to
|
||||
# hyperparameters. ``accuracy_id`` is an ObjectRef that acts as a handle to
|
||||
# the remote task. It is used later to fetch the result of the task
|
||||
# when the task finishes.
|
||||
|
||||
@@ -195,7 +195,7 @@ for i in range(num_evaluations):
|
||||
|
||||
# Fetch and print the results of the tasks in the order that they complete.
|
||||
while remaining_ids:
|
||||
# Use ray.wait to get the object ID of the first task that completes.
|
||||
# Use ray.wait to get the object ref of the first task that completes.
|
||||
done_ids, remaining_ids = ray.wait(remaining_ids)
|
||||
# There is only one return result by default.
|
||||
result_id = done_ids[0]
|
||||
|
||||
@@ -145,7 +145,7 @@ instead of
|
||||
then each task that got sent to the scheduler (one for every element of
|
||||
``batch_ids``) would have had a copy of ``theta`` serialized inside of it. Since
|
||||
``theta`` here consists of the parameters of a potentially large model, this is
|
||||
inefficient. *Large objects should be passed by object ID to remote functions
|
||||
inefficient. *Large objects should be passed by object ref to remote functions
|
||||
and not by value*.
|
||||
|
||||
We use remote actors and remote objects internally in the implementation of
|
||||
|
||||
@@ -47,7 +47,7 @@ When the above actor is instantiated, the following events happen.
|
||||
Actor Methods
|
||||
-------------
|
||||
|
||||
Any method of the actor can return multiple object IDs with the ``ray.method`` decorator:
|
||||
Any method of the actor can return multiple object refs with the ``ray.method`` decorator:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -60,9 +60,9 @@ Any method of the actor can return multiple object IDs with the ``ray.method`` d
|
||||
|
||||
f = Foo.remote()
|
||||
|
||||
obj_id1, obj_id2 = f.bar.remote()
|
||||
assert ray.get(obj_id1) == 1
|
||||
assert ray.get(obj_id2) == 2
|
||||
obj_ref1, obj_ref2 = f.bar.remote()
|
||||
assert ray.get(obj_ref1) == 1
|
||||
assert ray.get(obj_ref2) == 2
|
||||
|
||||
.. _actor-resource-guide:
|
||||
|
||||
@@ -146,7 +146,7 @@ If necessary, you can manually terminate an actor by calling
|
||||
``ray.actor.exit_actor()`` from within one of the actor methods. This will kill
|
||||
the actor process and release resources associated/assigned to the actor. This
|
||||
approach should generally not be necessary as actors are automatically garbage
|
||||
collected. The ``ObjectID`` resulting from the task can be waited on to wait
|
||||
collected. The ``ObjectRef`` resulting from the task can be waited on to wait
|
||||
for the actor to exit (calling ``ray.get()`` on it will raise a ``RayActorError``).
|
||||
Note that this method of termination will wait until any previously submitted
|
||||
tasks finish executing. If you want to terminate an actor immediately, you can
|
||||
|
||||
@@ -97,7 +97,7 @@ For example, consider the following.
|
||||
|
||||
@ray.remote
|
||||
def g():
|
||||
# Call f 4 times and return the resulting object IDs.
|
||||
# Call f 4 times and return the resulting object refs.
|
||||
return [f.remote() for _ in range(4)]
|
||||
|
||||
@ray.remote
|
||||
@@ -111,10 +111,10 @@ Then calling ``g`` and ``h`` produces the following behavior.
|
||||
.. code:: python
|
||||
|
||||
>>> ray.get(g.remote())
|
||||
[ObjectID(b1457ba0911ae84989aae86f89409e953dd9a80e),
|
||||
ObjectID(7c14a1d13a56d8dc01e800761a66f09201104275),
|
||||
ObjectID(99763728ffc1a2c0766a2000ebabded52514e9a6),
|
||||
ObjectID(9c2f372e1933b04b2936bb6f58161285829b9914)]
|
||||
[ObjectRef(b1457ba0911ae84989aae86f89409e953dd9a80e),
|
||||
ObjectRef(7c14a1d13a56d8dc01e800761a66f09201104275),
|
||||
ObjectRef(99763728ffc1a2c0766a2000ebabded52514e9a6),
|
||||
ObjectRef(9c2f372e1933b04b2936bb6f58161285829b9914)]
|
||||
|
||||
>>> ray.get(h.remote())
|
||||
[1, 1, 1, 1]
|
||||
|
||||
@@ -33,9 +33,9 @@ that supports top level ``await``:
|
||||
await actor.run_concurrent.remote()
|
||||
|
||||
|
||||
ObjectIDs as asyncio.Futures
|
||||
----------------------------
|
||||
ObjectIDs can be translated to asyncio.Future. This feature
|
||||
ObjectRefs as asyncio.Futures
|
||||
-----------------------------
|
||||
ObjectRefs can be translated to asyncio.Future. This feature
|
||||
make it possible to ``await`` on ray futures in existing concurrent
|
||||
applications.
|
||||
|
||||
|
||||
@@ -3,43 +3,43 @@ Memory Management
|
||||
|
||||
This page describes how memory management works in Ray and how you can set memory quotas to ensure memory-intensive applications run predictably and reliably.
|
||||
|
||||
ObjectID Reference Counting
|
||||
---------------------------
|
||||
ObjectRef Reference Counting
|
||||
----------------------------
|
||||
|
||||
Ray implements distributed reference counting so that any ``ObjectID`` in scope in the cluster is pinned in the object store. This includes local python references, arguments to pending tasks, and IDs serialized inside of other objects.
|
||||
Ray implements distributed reference counting so that any ``ObjectRef`` in scope in the cluster is pinned in the object store. This includes local python references, arguments to pending tasks, and IDs serialized inside of other objects.
|
||||
|
||||
Frequently Asked Questions (FAQ)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**My application failed with ObjectStoreFullError. What happened?**
|
||||
|
||||
Ensure that you're removing ``ObjectID`` references when they're no longer needed. See `Debugging using 'ray memory'`_ for information on how to identify what objects are in scope in your application.
|
||||
Ensure that you're removing ``ObjectRef`` references when they're no longer needed. See `Debugging using 'ray memory'`_ for information on how to identify what objects are in scope in your application.
|
||||
|
||||
This exception is raised when the object store on a node was full of pinned objects when the application tried to create a new object (either by calling ``ray.put()`` or returning an object from a task). If you're sure that the configured object store size was large enough for your application to run, ensure that you're removing ``ObjectID`` references when they're no longer in use so their objects can be evicted from the object store.
|
||||
This exception is raised when the object store on a node was full of pinned objects when the application tried to create a new object (either by calling ``ray.put()`` or returning an object from a task). If you're sure that the configured object store size was large enough for your application to run, ensure that you're removing ``ObjectRef`` references when they're no longer in use so their objects can be evicted from the object store.
|
||||
|
||||
**I'm running Ray inside IPython or a Jupyter Notebook and there are ObjectID references causing problems even though I'm not storing them anywhere.**
|
||||
**I'm running Ray inside IPython or a Jupyter Notebook and there are ObjectRef references causing problems even though I'm not storing them anywhere.**
|
||||
|
||||
Try `Enabling LRU Fallback`_, which will cause unused objects referenced by IPython to be LRU evicted when the object store is full instead of erroring.
|
||||
|
||||
IPython stores the output of every cell in a local Python variable indefinitely. This causes Ray to pin the objects even though your application may not actually be using them.
|
||||
IPython stores the output of every cell in a local Python variable indefinitely. This causes Ray to pin the objects even though your application may not actually be using them.
|
||||
|
||||
**My application used to run on previous versions of Ray but now I'm getting ObjectStoreFullError.**
|
||||
|
||||
Either modify your application to remove ``ObjectID`` references when they're no longer needed or try `Enabling LRU Fallback`_ to revert to the old behavior.
|
||||
Either modify your application to remove ``ObjectRef`` references when they're no longer needed or try `Enabling LRU Fallback`_ to revert to the old behavior.
|
||||
|
||||
In previous versions of Ray, there was no reference counting and instead objects in the object store were LRU evicted once the object store ran out of space. Some applications (e.g., applications that keep references to all objects ever created) may have worked with LRU eviction but do not with reference counting.
|
||||
In previous versions of Ray, there was no reference counting and instead objects in the object store were LRU evicted once the object store ran out of space. Some applications (e.g., applications that keep references to all objects ever created) may have worked with LRU eviction but do not with reference counting.
|
||||
|
||||
Debugging using 'ray memory'
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``ray memory`` command can be used to help track down what ``ObjectID`` references are in scope and may be causing an ``ObjectStoreFullError``.
|
||||
The ``ray memory`` command can be used to help track down what ``ObjectRef`` references are in scope and may be causing an ``ObjectStoreFullError``.
|
||||
|
||||
Running ``ray memory`` from the command line while a Ray application is running will give you a dump of all of the ``ObjectID`` references that are currently held by the driver, actors, and tasks in the cluster.
|
||||
Running ``ray memory`` from the command line while a Ray application is running will give you a dump of all of the ``ObjectRef`` references that are currently held by the driver, actors, and tasks in the cluster.
|
||||
|
||||
.. code-block::
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
Object ID Reference Type Object Size Reference Creation Site
|
||||
Object Ref Reference Type Object Size Reference Creation Site
|
||||
=====================================================================================================
|
||||
; worker pid=18301
|
||||
45b95b1c8bd3a9c4ffffffff010000c801000000 LOCAL_REFERENCE ? (deserialize task arg) __main__..f
|
||||
@@ -50,11 +50,11 @@ Running ``ray memory`` from the command line while a Ray application is running
|
||||
ffffffffffffffffffffffff0100008801000000 LOCAL_REFERENCE 77 (put object) test.py:<module>:9
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
|
||||
Each entry in this output corresponds to an ``ObjectID`` that's currently pinning an object in the object store along with where the reference is (in the driver, in a worker, etc.), what type of reference it is (see below for details on the types of references), the size of the object in bytes, and where in the application the reference was created.
|
||||
Each entry in this output corresponds to an ``ObjectRef`` that's currently pinning an object in the object store along with where the reference is (in the driver, in a worker, etc.), what type of reference it is (see below for details on the types of references), the size of the object in bytes, and where in the application the reference was created.
|
||||
|
||||
There are five types of references that can keep an object pinned:
|
||||
|
||||
**1. Local ObjectID references**
|
||||
**1. Local ObjectRef references**
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -70,7 +70,7 @@ In this example, we create references to two objects: one that is ``ray.put()``
|
||||
.. code-block::
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
Object ID Reference Type Object Size Reference Creation Site
|
||||
Object Ref Reference Type Object Size Reference Creation Site
|
||||
=====================================================================================================
|
||||
; driver pid=18867
|
||||
ffffffffffffffffffffffff0100008801000000 LOCAL_REFERENCE 77 (put object) ../test.py:<module>:9
|
||||
@@ -89,12 +89,12 @@ In the output from ``ray memory``, we can see that each of these is marked as a
|
||||
b = ray.get(a)
|
||||
del a
|
||||
|
||||
In this example, we create a ``numpy`` array and then store it in the object store. Then, we fetch the same numpy array from the object store and delete its ``ObjectID``. In this case, the object is still pinned in the object store because the deserialized copy (stored in ``b``) points directly to the memory in the object store.
|
||||
In this example, we create a ``numpy`` array and then store it in the object store. Then, we fetch the same numpy array from the object store and delete its ``ObjectRef``. In this case, the object is still pinned in the object store because the deserialized copy (stored in ``b``) points directly to the memory in the object store.
|
||||
|
||||
.. code-block::
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
Object ID Reference Type Object Size Reference Creation Site
|
||||
Object Ref Reference Type Object Size Reference Creation Site
|
||||
=====================================================================================================
|
||||
; driver pid=25090
|
||||
ffffffffffffffffffffffff0100008801000000 PINNED_IN_MEMORY 229 test.py:<module>:7
|
||||
@@ -119,7 +119,7 @@ In this example, we first create an object via ``ray.put()`` and then submit a t
|
||||
.. code-block::
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
Object ID Reference Type Object Size Reference Creation Site
|
||||
Object Ref Reference Type Object Size Reference Creation Site
|
||||
=====================================================================================================
|
||||
; worker pid=18971
|
||||
ffffffffffffffffffffffff0100008801000000 PINNED_IN_MEMORY 77 (deserialize task arg) __main__..f
|
||||
@@ -130,7 +130,7 @@ In this example, we first create an object via ``ray.put()`` and then submit a t
|
||||
|
||||
While the task is running, we see that ``ray memory`` shows both a ``LOCAL_REFERENCE`` and a ``USED_BY_PENDING_TASK`` reference for the object in the driver process. The worker process also holds a reference to the object because it is ``PINNED_IN_MEMORY``, because the Python ``arg`` is directly referencing the memory in the plasma, so it can't be evicted.
|
||||
|
||||
**4. Serialized ObjectID references**
|
||||
**4. Serialized ObjectRef references**
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -147,7 +147,7 @@ In this example, we again create an object via ``ray.put()``, but then pass it t
|
||||
.. code-block::
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
Object ID Reference Type Object Size Reference Creation Site
|
||||
Object Ref Reference Type Object Size Reference Creation Site
|
||||
=====================================================================================================
|
||||
; worker pid=19002
|
||||
ffffffffffffffffffffffff0100008801000000 LOCAL_REFERENCE 77 (deserialize task arg) __main__..f
|
||||
@@ -156,9 +156,9 @@ In this example, we again create an object via ``ray.put()``, but then pass it t
|
||||
45b95b1c8bd3a9c4ffffffff010000c801000000 LOCAL_REFERENCE ? (task call) ../test.py:<module>:10
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
|
||||
Now, both the driver and the worker process running the task hold a ``LOCAL_REFERENCE`` to the object in addition to it being ``USED_BY_PENDING_TASK`` on the driver. If this was an actor task, the actor could even hold a ``LOCAL_REFERENCE`` after the task completes by storing the ``ObjectID`` in a member variable.
|
||||
Now, both the driver and the worker process running the task hold a ``LOCAL_REFERENCE`` to the object in addition to it being ``USED_BY_PENDING_TASK`` on the driver. If this was an actor task, the actor could even hold a ``LOCAL_REFERENCE`` after the task completes by storing the ``ObjectRef`` in a member variable.
|
||||
|
||||
**5. Captured ObjectID references**
|
||||
**5. Captured ObjectRef references**
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -166,12 +166,12 @@ Now, both the driver and the worker process running the task hold a ``LOCAL_REFE
|
||||
b = ray.put([a])
|
||||
del a
|
||||
|
||||
In this example, we first create an object via ``ray.put()``, then capture its ``ObjectID`` inside of another ``ray.put()`` object, and delete the first ``ObjectID``. In this case, both objects are still pinned.
|
||||
In this example, we first create an object via ``ray.put()``, then capture its ``ObjectRef`` inside of another ``ray.put()`` object, and delete the first ``ObjectRef``. In this case, both objects are still pinned.
|
||||
|
||||
.. code-block::
|
||||
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
Object ID Reference Type Object Size Reference Creation Site
|
||||
Object Ref Reference Type Object Size Reference Creation Site
|
||||
=====================================================================================================
|
||||
; driver pid=19047
|
||||
ffffffffffffffffffffffff0100008802000000 LOCAL_REFERENCE 1551 (put object) ../test.py:<module>:10
|
||||
|
||||
@@ -144,7 +144,7 @@ Note that this is the same information as displayed in the `ray memory command <
|
||||
|
||||
Inspect Memory Usage
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
You can detect local memory anomalies through the Logical View tab. If NumObjectIdsInScope,
|
||||
You can detect local memory anomalies through the Logical View tab. If NumObjectRefsInScope,
|
||||
NumLocalObjects, or UsedLocalObjectMemory keeps growing without bound, it can lead to out
|
||||
of memory errors or eviction of objectIDs that your program still wants to use.
|
||||
|
||||
@@ -254,10 +254,10 @@ Logical View (Experimental)
|
||||
|
||||
**Excuted**: A number of executed tasks for this actor.
|
||||
|
||||
**NumObjectIdsInScope**: Number of object IDs in scope for this actor. object IDs
|
||||
**NumObjectRefsInScope**: Number of object refs in scope for this actor. object refs
|
||||
in scope will not be evicted unless object stores are full.
|
||||
|
||||
**NumLocalObjects**: Number of object IDs that are in this actor's local memory.
|
||||
**NumLocalObjects**: Number of object refs that are in this actor's local memory.
|
||||
Only big objects (>100KB) are residing in plasma object stores, and other small
|
||||
objects are staying in local memory.
|
||||
|
||||
@@ -319,7 +319,7 @@ Memory
|
||||
|
||||
**Type**: Type of a process. It is either a driver or worker.
|
||||
|
||||
**Object ID**: Object ID of a Ray object.
|
||||
**Object Ref**: Object ref of a Ray object.
|
||||
|
||||
**Object Size** Object Size of a Ray object in bytes.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ Parallelizing Python Functions with Ray Tasks
|
||||
|
||||
First, import ray and ``init`` the Ray service.
|
||||
Then decorate your function with ``@ray.remote`` to declare that you want to run this function
|
||||
remotely. Lastly, call that function with ``.remote()`` instead of calling it normally. This remote call yields a future, or ``ObjectID`` that you can then
|
||||
remotely. Lastly, call that function with ``.remote()`` instead of calling it normally. This remote call yields a future, or ``ObjectRef`` that you can then
|
||||
fetch with ``ray.get``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -93,8 +93,8 @@ Below is an example of using ``ray.register_custom_serializer``:
|
||||
ray.register_custom_serializer(
|
||||
Foo, serializer=custom_serializer, deserializer=custom_deserializer)
|
||||
|
||||
object_id = ray.put(Foo(100))
|
||||
assert ray.get(object_id).value == 100
|
||||
object_ref = ray.put(Foo(100))
|
||||
assert ray.get(object_ref).value == 100
|
||||
|
||||
|
||||
If you find cases where Ray serialization doesn't work or does something unexpected, please `let us know`_ so we can fix it.
|
||||
|
||||
@@ -111,7 +111,7 @@ Let's deploy the new version to the same endpoint. Don't forget to set
|
||||
To query the backend via Python API, we can use ``serve.get_handle`` to receive
|
||||
a handle to the corresponding "endpoint". To enqueue a query, you can call
|
||||
``handle.remote(argument_name=argument_value)``. This call returns immediately
|
||||
with a :ref:`Ray ObjectID<ray-object-ids>`. You can call `ray.get` to retrieve
|
||||
with a :ref:`Ray ObjectRef<ray-object-ids>`. You can call `ray.get` to retrieve
|
||||
the result.
|
||||
|
||||
.. literalinclude:: ../../../../python/ray/serve/examples/doc/tutorial_batch.py
|
||||
|
||||
+24
-24
@@ -5,7 +5,7 @@ This walkthrough will overview the core concepts of Ray:
|
||||
|
||||
1. Starting Ray
|
||||
2. Using remote functions (tasks) [``ray.remote``]
|
||||
3. Fetching results (object IDs) [``ray.put``, ``ray.get``, ``ray.wait``]
|
||||
3. Fetching results (object refs) [``ray.put``, ``ray.get``, ``ray.wait``]
|
||||
4. Using remote classes (actors) [``ray.remote``]
|
||||
|
||||
With Ray, your code will work on a single machine and can be easily scaled to large cluster.
|
||||
@@ -55,16 +55,16 @@ Ray enables arbitrary Python functions to be executed asynchronously. These asyn
|
||||
This causes a few changes in behavior:
|
||||
|
||||
1. **Invocation:** The regular version is called with ``regular_function()``, whereas the remote version is called with ``remote_function.remote()``.
|
||||
2. **Return values:** ``regular_function`` immediately executes and returns ``1``, whereas ``remote_function`` immediately returns an object ID (a future) and then creates a task that will be executed on a worker process. The result can be retrieved with ``ray.get``.
|
||||
2. **Return values:** ``regular_function`` immediately executes and returns ``1``, whereas ``remote_function`` immediately returns an object ref (a future) and then creates a task that will be executed on a worker process. The result can be retrieved with ``ray.get``.
|
||||
|
||||
.. code:: python
|
||||
|
||||
assert regular_function() == 1
|
||||
|
||||
object_id = remote_function.remote()
|
||||
object_ref = remote_function.remote()
|
||||
|
||||
# The value of the original `regular_function`
|
||||
assert ray.get(object_id) == 1
|
||||
assert ray.get(object_ref) == 1
|
||||
|
||||
3. **Parallelism:** Invocations of ``regular_function`` happen
|
||||
**serially**, for example
|
||||
@@ -91,7 +91,7 @@ See the `ray.remote package reference <package-ref.html>`__ page for specific do
|
||||
|
||||
.. _ray-object-ids:
|
||||
|
||||
**Object IDs** can also be passed into remote functions. When the function actually gets executed, **the argument will be a retrieved as a regular Python object**. For example, take this function:
|
||||
**Object refs** can also be passed into remote functions. When the function actually gets executed, **the argument will be a retrieved as a regular Python object**. For example, take this function:
|
||||
|
||||
.. code:: python
|
||||
|
||||
@@ -162,7 +162,7 @@ Below are more examples of resource specifications:
|
||||
def f():
|
||||
return 1
|
||||
|
||||
Further, remote functions can return multiple object IDs.
|
||||
Further, remote functions can return multiple object refs.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -172,7 +172,7 @@ Further, remote functions can return multiple object IDs.
|
||||
|
||||
a_id, b_id, c_id = return_multiple.remote()
|
||||
|
||||
Remote functions can be canceled by calling ``ray.cancel`` on the returned Object ID. Remote actor functions can be stopped by killing the actor using the ``ray.kill`` interface.
|
||||
Remote functions can be canceled by calling ``ray.cancel`` on the returned Object ref. Remote actor functions can be stopped by killing the actor using the ``ray.kill`` interface.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -181,8 +181,8 @@ Remote functions can be canceled by calling ``ray.cancel`` on the returned Objec
|
||||
time.sleep(10e6)
|
||||
return 100
|
||||
|
||||
obj_id = blocking_operation.remote()
|
||||
ray.cancel(obj_id)
|
||||
obj_ref = blocking_operation.remote()
|
||||
ray.cancel(obj_ref)
|
||||
|
||||
.. autofunction:: ray.cancel
|
||||
:noindex:
|
||||
@@ -190,13 +190,13 @@ Remote functions can be canceled by calling ``ray.cancel`` on the returned Objec
|
||||
Objects in Ray
|
||||
--------------
|
||||
|
||||
In Ray, we can create and compute on objects. We refer to these objects as **remote objects**, and we use **object IDs** to refer to them. Remote objects are stored in `shared-memory <https://en.wikipedia.org/wiki/Shared_memory>`__ **object stores**, and there is one object store per node in the cluster. In the cluster setting, we may not actually know which machine each object lives on.
|
||||
In Ray, we can create and compute on objects. We refer to these objects as **remote objects**, and we use **object refs** to refer to them. Remote objects are stored in `shared-memory <https://en.wikipedia.org/wiki/Shared_memory>`__ **object stores**, and there is one object store per node in the cluster. In the cluster setting, we may not actually know which machine each object lives on.
|
||||
|
||||
An **object ID** is essentially a unique ID that can be used to refer to a
|
||||
remote object. If you're familiar with futures, our object IDs are conceptually
|
||||
An **object ref** is essentially a unique ID that can be used to refer to a
|
||||
remote object. If you're familiar with futures, our object refs are conceptually
|
||||
similar.
|
||||
|
||||
Object IDs can be created in multiple ways.
|
||||
Object refs can be created in multiple ways.
|
||||
|
||||
1. They are returned by remote function calls.
|
||||
2. They are returned by ``ray.put``.
|
||||
@@ -204,7 +204,7 @@ Object IDs can be created in multiple ways.
|
||||
.. code-block:: python
|
||||
|
||||
y = 1
|
||||
object_id = ray.put(y)
|
||||
object_ref = ray.put(y)
|
||||
|
||||
.. autofunction:: ray.put
|
||||
:noindex:
|
||||
@@ -219,7 +219,7 @@ Object IDs can be created in multiple ways.
|
||||
Fetching Results
|
||||
----------------
|
||||
|
||||
The command ``ray.get(x_id, timeout=None)`` takes an object ID and creates a Python object
|
||||
The command ``ray.get(x_id, timeout=None)`` takes an object ref and creates a Python object
|
||||
from the corresponding remote object. First, if the current node's object store
|
||||
does not contain the object, the object is downloaded. Then, if the object is a `numpy array <https://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html>`__
|
||||
or a collection of numpy arrays, the ``get`` call is zero-copy and returns arrays backed by shared object store memory.
|
||||
@@ -228,8 +228,8 @@ Otherwise, we deserialize the object data into a Python object.
|
||||
.. code-block:: python
|
||||
|
||||
y = 1
|
||||
obj_id = ray.put(y)
|
||||
assert ray.get(obj_id) == 1
|
||||
obj_ref = ray.put(y)
|
||||
assert ray.get(obj_ref) == 1
|
||||
|
||||
You can also set a timeout to return early from a ``get`` that's blocking for too long.
|
||||
|
||||
@@ -241,9 +241,9 @@ You can also set a timeout to return early from a ``get`` that's blocking for to
|
||||
def long_running_function()
|
||||
time.sleep(8)
|
||||
|
||||
obj_id = long_running_function.remote()
|
||||
obj_ref = long_running_function.remote()
|
||||
try:
|
||||
ray.get(obj_id, timeout=4)
|
||||
ray.get(obj_ref, timeout=4)
|
||||
except RayTimeoutError:
|
||||
print("`get` timed out.")
|
||||
|
||||
@@ -257,7 +257,7 @@ works as follows.
|
||||
|
||||
.. code:: python
|
||||
|
||||
ready_ids, remaining_ids = ray.wait(object_ids, num_returns=1, timeout=None)
|
||||
ready_ids, remaining_ids = ray.wait(object_refs, num_returns=1, timeout=None)
|
||||
|
||||
.. autofunction:: ray.wait
|
||||
:noindex:
|
||||
@@ -275,7 +275,7 @@ actors.
|
||||
.. note::
|
||||
|
||||
Objects created with ``ray.put`` are pinned in memory while a Python reference
|
||||
to the object ID returned by the put exists. This only applies to the specific
|
||||
to the object ref returned by the put exists. This only applies to the specific
|
||||
ID returned by put, not IDs in general or copies of that IDs.
|
||||
|
||||
Remote Classes (Actors)
|
||||
@@ -319,13 +319,13 @@ You can specify resource requirements in Actors too (see the `Actors section
|
||||
pass
|
||||
|
||||
We can interact with the actor by calling its methods with the ``.remote``
|
||||
operator. We can then call ``ray.get`` on the object ID to retrieve the actual
|
||||
operator. We can then call ``ray.get`` on the object ref to retrieve the actual
|
||||
value.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
obj_id = a1.increment.remote()
|
||||
ray.get(obj_id) == 1
|
||||
obj_ref = a1.increment.remote()
|
||||
ray.get(obj_ref) == 1
|
||||
|
||||
|
||||
Methods called on different actors can execute in parallel, and methods called on the same actor are executed serially in the order that they are called. Methods on the same actor will share state with one another, as shown below.
|
||||
|
||||
@@ -65,6 +65,7 @@ from ray._raylet import (
|
||||
WorkerID,
|
||||
FunctionID,
|
||||
ObjectID,
|
||||
ObjectRef,
|
||||
TaskID,
|
||||
UniqueID,
|
||||
Language,
|
||||
@@ -166,6 +167,7 @@ __all__ += [
|
||||
"WorkerID",
|
||||
"FunctionID",
|
||||
"ObjectID",
|
||||
"ObjectRef",
|
||||
"TaskID",
|
||||
"UniqueID",
|
||||
]
|
||||
|
||||
@@ -65,10 +65,10 @@ cdef class BaseID:
|
||||
# here `cdef size_t` is required.
|
||||
cdef size_t hash(self)
|
||||
|
||||
cdef class ObjectID(BaseID):
|
||||
cdef class ObjectRef(BaseID):
|
||||
cdef:
|
||||
CObjectID data
|
||||
# Flag indicating whether or not this object ID was added to the set
|
||||
# Flag indicating whether or not this object ref was added to the set
|
||||
# of active IDs in the core worker so we know whether we should clean
|
||||
# it up.
|
||||
c_bool in_core_worker
|
||||
@@ -91,7 +91,7 @@ cdef class CoreWorker:
|
||||
c_bool is_local_mode
|
||||
|
||||
cdef _create_put_buffer(self, shared_ptr[CBuffer] &metadata,
|
||||
size_t data_size, ObjectID object_id,
|
||||
size_t data_size, ObjectRef object_ref,
|
||||
c_vector[CObjectID] contained_ids,
|
||||
CObjectID *c_object_id, shared_ptr[CBuffer] *data)
|
||||
cdef store_task_outputs(
|
||||
|
||||
+75
-71
@@ -103,6 +103,7 @@ import msgpack
|
||||
|
||||
cimport cpython
|
||||
|
||||
include "includes/object_ref.pxi"
|
||||
include "includes/unique_ids.pxi"
|
||||
include "includes/ray_config.pxi"
|
||||
include "includes/function_descriptor.pxi"
|
||||
@@ -162,31 +163,31 @@ cdef RayObjectsToDataMetadataPairs(
|
||||
return data_metadata_pairs
|
||||
|
||||
|
||||
cdef VectorToObjectIDs(const c_vector[CObjectID] &object_ids):
|
||||
cdef VectorToObjectRefs(const c_vector[CObjectID] &object_refs):
|
||||
result = []
|
||||
for i in range(object_ids.size()):
|
||||
result.append(ObjectID(object_ids[i].Binary()))
|
||||
for i in range(object_refs.size()):
|
||||
result.append(ObjectRef(object_refs[i].Binary()))
|
||||
return result
|
||||
|
||||
|
||||
cdef c_vector[CObjectID] ObjectIDsToVector(object_ids):
|
||||
"""A helper function that converts a Python list of object IDs to a vector.
|
||||
cdef c_vector[CObjectID] ObjectRefsToVector(object_refs):
|
||||
"""A helper function that converts a Python list of object refs to a vector.
|
||||
|
||||
Args:
|
||||
object_ids (list): The Python list of object IDs.
|
||||
object_refs (list): The Python list of object refs.
|
||||
|
||||
Returns:
|
||||
The output vector.
|
||||
"""
|
||||
cdef:
|
||||
c_vector[CObjectID] result
|
||||
for object_id in object_ids:
|
||||
result.push_back((<ObjectID>object_id).native())
|
||||
for object_ref in object_refs:
|
||||
result.push_back((<ObjectRef>object_ref).native())
|
||||
return result
|
||||
|
||||
|
||||
def compute_task_id(ObjectID object_id):
|
||||
return TaskID(object_id.native().TaskId().Binary())
|
||||
def compute_task_id(ObjectRef object_ref):
|
||||
return TaskID(object_ref.native().TaskId().Binary())
|
||||
|
||||
|
||||
cdef increase_recursion_limit():
|
||||
@@ -273,8 +274,8 @@ cdef prepare_args(
|
||||
worker = ray.worker.global_worker
|
||||
put_threshold = RayConfig.instance().max_direct_call_object_size()
|
||||
for arg in args:
|
||||
if isinstance(arg, ObjectID):
|
||||
c_arg = (<ObjectID>arg).native()
|
||||
if isinstance(arg, ObjectRef):
|
||||
c_arg = (<ObjectRef>arg).native()
|
||||
args_vector.push_back(
|
||||
unique_ptr[CTaskArg](new CTaskArgByReference(
|
||||
c_arg,
|
||||
@@ -292,9 +293,9 @@ cdef prepare_args(
|
||||
metadata, language))
|
||||
size = serialized_arg.total_bytes
|
||||
|
||||
# TODO(edoakes): any objects containing ObjectIDs are spilled to
|
||||
# TODO(edoakes): any objects containing ObjectRefs are spilled to
|
||||
# plasma here. This is inefficient for small objects, but inlined
|
||||
# arguments aren't associated ObjectIDs right now so this is a
|
||||
# arguments aren't associated ObjectRefs right now so this is a
|
||||
# simple fix for reference counting purposes.
|
||||
if <int64_t>size <= put_threshold:
|
||||
arg_data = dynamic_pointer_cast[CBuffer, LocalMemoryBuffer](
|
||||
@@ -302,8 +303,8 @@ cdef prepare_args(
|
||||
if size > 0:
|
||||
(<SerializedObject>serialized_arg).write_to(
|
||||
Buffer.make(arg_data))
|
||||
for object_id in serialized_arg.contained_object_ids:
|
||||
inlined_ids.push_back((<ObjectID>object_id).native())
|
||||
for object_ref in serialized_arg.contained_object_refs:
|
||||
inlined_ids.push_back((<ObjectRef>object_ref).native())
|
||||
args_vector.push_back(
|
||||
unique_ptr[CTaskArg](new CTaskArgByValue(
|
||||
make_shared[CRayObject](
|
||||
@@ -436,7 +437,7 @@ cdef execute_task(
|
||||
args, kwargs = [], {}
|
||||
else:
|
||||
metadata_pairs = RayObjectsToDataMetadataPairs(c_args)
|
||||
object_ids = VectorToObjectIDs(c_arg_reference_ids)
|
||||
object_refs = VectorToObjectRefs(c_arg_reference_ids)
|
||||
|
||||
if core_worker.current_actor_is_asyncio():
|
||||
# We deserialize objects in event loop thread to
|
||||
@@ -444,12 +445,12 @@ cdef execute_task(
|
||||
async def deserialize_args():
|
||||
return (ray.worker.global_worker
|
||||
.deserialize_objects(
|
||||
metadata_pairs, object_ids))
|
||||
metadata_pairs, object_refs))
|
||||
args = core_worker.run_async_func_in_event_loop(
|
||||
deserialize_args)
|
||||
else:
|
||||
args = ray.worker.global_worker.deserialize_objects(
|
||||
metadata_pairs, object_ids)
|
||||
metadata_pairs, object_refs)
|
||||
|
||||
for arg in args:
|
||||
if isinstance(arg, RayError):
|
||||
@@ -721,12 +722,12 @@ cdef class CoreWorker:
|
||||
def get_plasma_event_handler(self):
|
||||
return self.plasma_event_handler
|
||||
|
||||
def get_objects(self, object_ids, TaskID current_task_id,
|
||||
def get_objects(self, object_refs, TaskID current_task_id,
|
||||
int64_t timeout_ms=-1):
|
||||
cdef:
|
||||
c_vector[shared_ptr[CRayObject]] results
|
||||
CTaskID c_task_id = current_task_id.native()
|
||||
c_vector[CObjectID] c_object_ids = ObjectIDsToVector(object_ids)
|
||||
c_vector[CObjectID] c_object_ids = ObjectRefsToVector(object_refs)
|
||||
|
||||
with nogil:
|
||||
check_status(CCoreWorkerProcess.GetCoreWorker().Get(
|
||||
@@ -734,10 +735,10 @@ cdef class CoreWorker:
|
||||
|
||||
return RayObjectsToDataMetadataPairs(results)
|
||||
|
||||
def object_exists(self, ObjectID object_id):
|
||||
def object_exists(self, ObjectRef object_ref):
|
||||
cdef:
|
||||
c_bool has_object
|
||||
CObjectID c_object_id = object_id.native()
|
||||
CObjectID c_object_id = object_ref.native()
|
||||
|
||||
with nogil:
|
||||
check_status(CCoreWorkerProcess.GetCoreWorker().Contains(
|
||||
@@ -746,29 +747,29 @@ cdef class CoreWorker:
|
||||
return has_object
|
||||
|
||||
cdef _create_put_buffer(self, shared_ptr[CBuffer] &metadata,
|
||||
size_t data_size, ObjectID object_id,
|
||||
size_t data_size, ObjectRef object_ref,
|
||||
c_vector[CObjectID] contained_ids,
|
||||
CObjectID *c_object_id, shared_ptr[CBuffer] *data):
|
||||
if object_id is None:
|
||||
if object_ref is None:
|
||||
with nogil:
|
||||
check_status(CCoreWorkerProcess.GetCoreWorker().Create(
|
||||
metadata, data_size, contained_ids,
|
||||
c_object_id, data))
|
||||
else:
|
||||
c_object_id[0] = object_id.native()
|
||||
c_object_id[0] = object_ref.native()
|
||||
with nogil:
|
||||
check_status(CCoreWorkerProcess.GetCoreWorker().Create(
|
||||
metadata, data_size,
|
||||
c_object_id[0], data))
|
||||
|
||||
# If data is nullptr, that means the ObjectID already existed,
|
||||
# If data is nullptr, that means the ObjectRef already existed,
|
||||
# which we ignore.
|
||||
# TODO(edoakes): this is hacky, we should return the error instead
|
||||
# and deal with it here.
|
||||
return data.get() == NULL
|
||||
|
||||
def put_serialized_object(self, serialized_object,
|
||||
ObjectID object_id=None,
|
||||
ObjectRef object_ref=None,
|
||||
c_bool pin_object=True):
|
||||
cdef:
|
||||
CObjectID c_object_id
|
||||
@@ -784,8 +785,8 @@ cdef class CoreWorker:
|
||||
RayConfig.instance().put_small_object_in_memory_store())
|
||||
total_bytes = serialized_object.total_bytes
|
||||
object_already_exists = self._create_put_buffer(
|
||||
metadata, total_bytes, object_id,
|
||||
ObjectIDsToVector(serialized_object.contained_object_ids),
|
||||
metadata, total_bytes, object_ref,
|
||||
ObjectRefsToVector(serialized_object.contained_object_refs),
|
||||
&c_object_id, &data)
|
||||
|
||||
if not object_already_exists:
|
||||
@@ -800,42 +801,42 @@ cdef class CoreWorker:
|
||||
c_object_id_vector, c_object_id))
|
||||
else:
|
||||
with nogil:
|
||||
# Using custom object IDs is not supported because we can't
|
||||
# track their lifecycle, so we don't pin the object in this
|
||||
# case.
|
||||
# Using custom object refs is not supported because we
|
||||
# can't track their lifecycle, so we don't pin the object
|
||||
# in this case.
|
||||
check_status(CCoreWorkerProcess.GetCoreWorker().Seal(
|
||||
c_object_id,
|
||||
pin_object and object_id is None))
|
||||
pin_object and object_ref is None))
|
||||
|
||||
return c_object_id.Binary()
|
||||
|
||||
def wait(self, object_ids, int num_returns, int64_t timeout_ms,
|
||||
def wait(self, object_refs, int num_returns, int64_t timeout_ms,
|
||||
TaskID current_task_id):
|
||||
cdef:
|
||||
c_vector[CObjectID] wait_ids
|
||||
c_vector[c_bool] results
|
||||
CTaskID c_task_id = current_task_id.native()
|
||||
|
||||
wait_ids = ObjectIDsToVector(object_ids)
|
||||
wait_ids = ObjectRefsToVector(object_refs)
|
||||
with nogil:
|
||||
check_status(CCoreWorkerProcess.GetCoreWorker().Wait(
|
||||
wait_ids, num_returns, timeout_ms, &results))
|
||||
|
||||
assert len(results) == len(object_ids)
|
||||
assert len(results) == len(object_refs)
|
||||
|
||||
ready, not_ready = [], []
|
||||
for i, object_id in enumerate(object_ids):
|
||||
for i, object_ref in enumerate(object_refs):
|
||||
if results[i]:
|
||||
ready.append(object_id)
|
||||
ready.append(object_ref)
|
||||
else:
|
||||
not_ready.append(object_id)
|
||||
not_ready.append(object_ref)
|
||||
|
||||
return ready, not_ready
|
||||
|
||||
def free_objects(self, object_ids, c_bool local_only,
|
||||
def free_objects(self, object_refs, c_bool local_only,
|
||||
c_bool delete_creating_tasks):
|
||||
cdef:
|
||||
c_vector[CObjectID] free_ids = ObjectIDsToVector(object_ids)
|
||||
c_vector[CObjectID] free_ids = ObjectRefsToVector(object_refs)
|
||||
|
||||
with nogil:
|
||||
check_status(CCoreWorkerProcess.GetCoreWorker().Delete(
|
||||
@@ -894,7 +895,7 @@ cdef class CoreWorker:
|
||||
ray_function, args_vector, task_options, &return_ids,
|
||||
max_retries)
|
||||
|
||||
return VectorToObjectIDs(return_ids)
|
||||
return VectorToObjectRefs(return_ids)
|
||||
|
||||
def create_actor(self,
|
||||
Language language,
|
||||
@@ -966,7 +967,7 @@ cdef class CoreWorker:
|
||||
ray_function,
|
||||
args_vector, task_options, &return_ids)
|
||||
|
||||
return VectorToObjectIDs(return_ids)
|
||||
return VectorToObjectRefs(return_ids)
|
||||
|
||||
def kill_actor(self, ActorID actor_id, c_bool no_restart):
|
||||
cdef:
|
||||
@@ -976,9 +977,9 @@ cdef class CoreWorker:
|
||||
check_status(CCoreWorkerProcess.GetCoreWorker().KillActor(
|
||||
c_actor_id, True, no_restart))
|
||||
|
||||
def cancel_task(self, ObjectID object_id, c_bool force_kill):
|
||||
def cancel_task(self, ObjectRef object_ref, c_bool force_kill):
|
||||
cdef:
|
||||
CObjectID c_object_id = object_id.native()
|
||||
CObjectID c_object_id = object_ref.native()
|
||||
CRayStatus status = CRayStatus.OK()
|
||||
|
||||
status = CCoreWorkerProcess.GetCoreWorker().CancelTask(
|
||||
@@ -1061,11 +1062,11 @@ cdef class CoreWorker:
|
||||
worker.current_session_and_job)
|
||||
|
||||
def deserialize_and_register_actor_handle(self, const c_string &bytes,
|
||||
ObjectID
|
||||
outer_object_id):
|
||||
ObjectRef
|
||||
outer_object_ref):
|
||||
cdef:
|
||||
CObjectID c_outer_object_id = (outer_object_id.native() if
|
||||
outer_object_id else
|
||||
CObjectID c_outer_object_id = (outer_object_ref.native() if
|
||||
outer_object_ref else
|
||||
CObjectID.Nil())
|
||||
c_actor_id = (CCoreWorkerProcess
|
||||
.GetCoreWorker()
|
||||
@@ -1093,35 +1094,37 @@ cdef class CoreWorker:
|
||||
CObjectID c_actor_handle_id
|
||||
check_status(CCoreWorkerProcess.GetCoreWorker().SerializeActorHandle(
|
||||
actor_id.native(), &output, &c_actor_handle_id))
|
||||
return output, ObjectID(c_actor_handle_id.Binary())
|
||||
return output, ObjectRef(c_actor_handle_id.Binary())
|
||||
|
||||
def add_object_id_reference(self, ObjectID object_id):
|
||||
def add_object_ref_reference(self, ObjectRef object_ref):
|
||||
# Note: faster to not release GIL for short-running op.
|
||||
CCoreWorkerProcess.GetCoreWorker().AddLocalReference(
|
||||
object_id.native())
|
||||
object_ref.native())
|
||||
|
||||
def remove_object_id_reference(self, ObjectID object_id):
|
||||
def remove_object_ref_reference(self, ObjectRef object_ref):
|
||||
# Note: faster to not release GIL for short-running op.
|
||||
CCoreWorkerProcess.GetCoreWorker().RemoveLocalReference(
|
||||
object_id.native())
|
||||
object_ref.native())
|
||||
|
||||
def serialize_and_promote_object_id(self, ObjectID object_id):
|
||||
def serialize_and_promote_object_ref(self, ObjectRef object_ref):
|
||||
cdef:
|
||||
CObjectID c_object_id = object_id.native()
|
||||
CObjectID c_object_id = object_ref.native()
|
||||
CAddress c_owner_address = CAddress()
|
||||
CCoreWorkerProcess.GetCoreWorker().PromoteObjectToPlasma(c_object_id)
|
||||
CCoreWorkerProcess.GetCoreWorker().GetOwnershipInfo(
|
||||
c_object_id, &c_owner_address)
|
||||
return (object_id,
|
||||
return (object_ref,
|
||||
c_owner_address.SerializeAsString())
|
||||
|
||||
def deserialize_and_register_object_id(
|
||||
self, const c_string &object_id_binary, ObjectID outer_object_id,
|
||||
const c_string &serialized_owner_address):
|
||||
def deserialize_and_register_object_ref(
|
||||
self, const c_string &object_ref_binary,
|
||||
ObjectRef outer_object_ref,
|
||||
const c_string &serialized_owner_address,
|
||||
):
|
||||
cdef:
|
||||
CObjectID c_object_id = CObjectID.FromBinary(object_id_binary)
|
||||
CObjectID c_outer_object_id = (outer_object_id.native() if
|
||||
outer_object_id else
|
||||
CObjectID c_object_id = CObjectID.FromBinary(object_ref_binary)
|
||||
CObjectID c_outer_object_id = (outer_object_ref.native() if
|
||||
outer_object_ref else
|
||||
CObjectID.Nil())
|
||||
CAddress c_owner_address = CAddress()
|
||||
|
||||
@@ -1158,7 +1161,8 @@ cdef class CoreWorker:
|
||||
string_to_buffer(serialized_object.metadata))
|
||||
serialized_objects.append(serialized_object)
|
||||
contained_ids.push_back(
|
||||
ObjectIDsToVector(serialized_object.contained_object_ids))
|
||||
ObjectRefsToVector(serialized_object.contained_object_refs)
|
||||
)
|
||||
|
||||
with nogil:
|
||||
check_status(CCoreWorkerProcess.GetCoreWorker()
|
||||
@@ -1239,18 +1243,18 @@ cdef class CoreWorker:
|
||||
|
||||
ref_counts = {}
|
||||
while it != c_ref_counts.end():
|
||||
object_id = dereference(it).first.Hex()
|
||||
ref_counts[object_id] = {
|
||||
object_ref = dereference(it).first.Hex()
|
||||
ref_counts[object_ref] = {
|
||||
"local": dereference(it).second.first,
|
||||
"submitted": dereference(it).second.second}
|
||||
postincrement(it)
|
||||
|
||||
return ref_counts
|
||||
|
||||
def get_async(self, ObjectID object_id, future):
|
||||
def get_async(self, ObjectRef object_ref, future):
|
||||
cpython.Py_INCREF(future)
|
||||
CCoreWorkerProcess.GetCoreWorker().GetAsync(
|
||||
object_id.native(),
|
||||
object_ref.native(),
|
||||
async_set_result,
|
||||
<void*>future)
|
||||
|
||||
@@ -1287,7 +1291,7 @@ cdef class CoreWorker:
|
||||
CClientID.FromBinary(client_id.binary()))
|
||||
|
||||
cdef void async_set_result(shared_ptr[CRayObject] obj,
|
||||
CObjectID object_id,
|
||||
CObjectID object_ref,
|
||||
void *future) with gil:
|
||||
cdef:
|
||||
c_vector[shared_ptr[CRayObject]] objects_to_deserialize
|
||||
@@ -1299,7 +1303,7 @@ cdef void async_set_result(shared_ptr[CRayObject] obj,
|
||||
objects_to_deserialize.push_back(obj)
|
||||
data_metadata_pairs = RayObjectsToDataMetadataPairs(
|
||||
objects_to_deserialize)
|
||||
ids_to_deserialize = [ObjectID(object_id.Binary())]
|
||||
ids_to_deserialize = [ObjectRef(object_ref.Binary())]
|
||||
result = ray.worker.global_worker.deserialize_objects(
|
||||
data_metadata_pairs, ids_to_deserialize)[0]
|
||||
|
||||
|
||||
+15
-15
@@ -31,7 +31,7 @@ def method(*args, **kwargs):
|
||||
_, _ = f.bar.remote()
|
||||
|
||||
Args:
|
||||
num_return_vals: The number of object IDs that should be returned by
|
||||
num_return_vals: The number of object refs that should be returned by
|
||||
invocations of this actor method.
|
||||
"""
|
||||
assert len(args) == 0
|
||||
@@ -64,7 +64,7 @@ class ActorMethod:
|
||||
invoking the method. The decorator must return a function that
|
||||
takes in two arguments ("args" and "kwargs"). In most cases, it
|
||||
should call the function that was passed into the decorator and
|
||||
return the resulting ObjectIDs. For an example, see
|
||||
return the resulting ObjectRefs. For an example, see
|
||||
"test_decorated_method" in "python/ray/tests/test_actor.py".
|
||||
"""
|
||||
|
||||
@@ -81,7 +81,7 @@ class ActorMethod:
|
||||
# opposed to the function execution). The decorator must return a
|
||||
# function that takes in two arguments ("args" and "kwargs"). In most
|
||||
# cases, it should call the function that was passed into the decorator
|
||||
# and return the resulting ObjectIDs.
|
||||
# and return the resulting ObjectRefs.
|
||||
self._decorator = decorator
|
||||
|
||||
# Acquire a hard ref to the actor, this is useful mainly when passing
|
||||
@@ -685,7 +685,7 @@ class ActorHandle:
|
||||
num_return_vals (int): The number of return values for the method.
|
||||
|
||||
Returns:
|
||||
object_ids: A list of object IDs returned by the remote actor
|
||||
object_refs: A list of object refs returned by the remote actor
|
||||
method.
|
||||
"""
|
||||
worker = ray.worker.global_worker
|
||||
@@ -713,16 +713,16 @@ class ActorHandle:
|
||||
"Cross language remote actor method " \
|
||||
"cannot be executed locally."
|
||||
|
||||
object_ids = worker.core_worker.submit_actor_task(
|
||||
object_refs = worker.core_worker.submit_actor_task(
|
||||
self._ray_actor_language, self._ray_actor_id, function_descriptor,
|
||||
list_args, num_return_vals, self._ray_actor_method_cpus)
|
||||
|
||||
if len(object_ids) == 1:
|
||||
object_ids = object_ids[0]
|
||||
elif len(object_ids) == 0:
|
||||
object_ids = None
|
||||
if len(object_refs) == 1:
|
||||
object_refs = object_refs[0]
|
||||
elif len(object_refs) == 0:
|
||||
object_refs = None
|
||||
|
||||
return object_ids
|
||||
return object_refs
|
||||
|
||||
def __getattr__(self, item):
|
||||
if not self._ray_is_cross_language:
|
||||
@@ -795,14 +795,14 @@ class ActorHandle:
|
||||
return state
|
||||
|
||||
@classmethod
|
||||
def _deserialization_helper(cls, state, outer_object_id=None):
|
||||
def _deserialization_helper(cls, state, outer_object_ref=None):
|
||||
"""This is defined in order to make pickling work.
|
||||
|
||||
Args:
|
||||
state: The serialized state of the actor handle.
|
||||
outer_object_id: The ObjectID that the serialized actor handle was
|
||||
contained in, if any. This is used for counting references to
|
||||
the actor handle.
|
||||
outer_object_ref: The ObjectRef that the serialized actor handle
|
||||
was contained in, if any. This is used for counting references
|
||||
to the actor handle.
|
||||
|
||||
"""
|
||||
worker = ray.worker.global_worker
|
||||
@@ -811,7 +811,7 @@ class ActorHandle:
|
||||
if hasattr(worker, "core_worker"):
|
||||
# Non-local mode
|
||||
return worker.core_worker.deserialize_and_register_actor_handle(
|
||||
state, outer_object_id)
|
||||
state, outer_object_ref)
|
||||
else:
|
||||
# Local mode
|
||||
return cls(
|
||||
|
||||
@@ -33,13 +33,13 @@ def sync_to_async(func):
|
||||
return wrapper
|
||||
|
||||
|
||||
def get_async(object_id):
|
||||
def get_async(object_ref):
|
||||
"""C++ Asyncio version of ray.get"""
|
||||
loop = asyncio.get_event_loop()
|
||||
core_worker = ray.worker.global_worker.core_worker
|
||||
|
||||
future = loop.create_future()
|
||||
core_worker.get_async(object_id, future)
|
||||
# A hack to keep a reference to the object ID for ref counting.
|
||||
future.object_id = object_id
|
||||
core_worker.get_async(object_ref, future)
|
||||
# A hack to keep a reference to the object ref for ref counting.
|
||||
future.object_ref = object_ref
|
||||
return future
|
||||
|
||||
@@ -166,7 +166,7 @@ export type RayletActorInfo =
|
||||
nodeId: string;
|
||||
numExecutedTasks: number;
|
||||
numLocalObjects: number;
|
||||
numObjectIdsInScope: number;
|
||||
numObjectRefsInScope: number;
|
||||
pid: number;
|
||||
port: number;
|
||||
state:
|
||||
@@ -356,7 +356,7 @@ export type MemoryTableEntry = {
|
||||
node_ip_address: string;
|
||||
pid: number;
|
||||
type: string;
|
||||
object_id: string;
|
||||
object_ref: string;
|
||||
object_size: number;
|
||||
reference_type: string;
|
||||
call_site: string;
|
||||
|
||||
@@ -160,10 +160,10 @@ class Actor extends React.Component<Props & WithStyles<typeof styles>, State> {
|
||||
"The number of tasks this actor has executed throughout its lifetimes.",
|
||||
},
|
||||
{
|
||||
label: "Number of ObjectIDs in scope",
|
||||
value: actor.numObjectIdsInScope.toLocaleString(),
|
||||
label: "Number of ObjectRefs in scope",
|
||||
value: actor.numObjectRefsInScope.toLocaleString(),
|
||||
tooltip:
|
||||
"The number of ObjectIDs that this actor is keeping in scope via its internal state. " +
|
||||
"The number of ObjectRefs that this actor is keeping in scope via its internal state. " +
|
||||
"This does not imply that the objects are in active use or colocated on the node with the actor " +
|
||||
`currently. This can be useful for debugging memory leaks. See the docs at ${memoryDebuggingDocLink} ` +
|
||||
"for more information.",
|
||||
|
||||
@@ -75,7 +75,7 @@ const memoryHeaderInfo: HeaderInfo<MemoryTableEntry>[] = [
|
||||
{ id: "node_ip_address", label: "IP Address", numeric: true },
|
||||
{ id: "pid", label: "pid", numeric: true },
|
||||
{ id: "type", label: "Type", numeric: false },
|
||||
{ id: "object_id", label: "Object ID", numeric: false },
|
||||
{ id: "object_ref", label: "Object Ref", numeric: false },
|
||||
{ id: "object_size", label: "Object Size (B)", numeric: true },
|
||||
{ id: "reference_type", label: "Reference Type", numeric: false },
|
||||
{ id: "call_site", label: "Call Site", numeric: false },
|
||||
|
||||
@@ -48,7 +48,7 @@ const MemoryRowGroup: React.FC<MemoryRowGroupProps> = ({
|
||||
"node_ip_address",
|
||||
"pid",
|
||||
"type",
|
||||
"object_id",
|
||||
"object_ref",
|
||||
"object_size",
|
||||
"reference_type",
|
||||
"call_site",
|
||||
|
||||
@@ -18,7 +18,7 @@ export const MemoryTableRow = (props: Props) => {
|
||||
memoryTableEntry.node_ip_address,
|
||||
memoryTableEntry.pid,
|
||||
memoryTableEntry.type,
|
||||
memoryTableEntry.object_id,
|
||||
memoryTableEntry.object_ref,
|
||||
object_size,
|
||||
memoryTableEntry.reference_type,
|
||||
memoryTableEntry.call_site,
|
||||
|
||||
@@ -8,7 +8,7 @@ import ray
|
||||
|
||||
from ray._raylet import (TaskID, ActorID, JobID)
|
||||
|
||||
# These values are used to calculate if objectIDs are actor handles.
|
||||
# These values are used to calculate if objectRefs are actor handles.
|
||||
TASKID_BYTES_SIZE = TaskID.size()
|
||||
ACTORID_BYTES_SIZE = ActorID.size()
|
||||
JOBID_BYTES_SIZE = JobID.size()
|
||||
@@ -17,21 +17,21 @@ TASKID_RANDOM_BITS_SIZE = (TASKID_BYTES_SIZE - ACTORID_BYTES_SIZE) * 2
|
||||
ACTORID_RANDOM_BITS_SIZE = (ACTORID_BYTES_SIZE - JOBID_BYTES_SIZE) * 2
|
||||
|
||||
|
||||
def decode_object_id_if_needed(object_id: str) -> bytes:
|
||||
"""Decode objectID bytes string.
|
||||
def decode_object_ref_if_needed(object_ref: str) -> bytes:
|
||||
"""Decode objectRef bytes string.
|
||||
|
||||
gRPC reply contains an objectID that is encodded by Base64.
|
||||
This function is used to decode the objectID.
|
||||
Note that there are times that objectID is already decoded as
|
||||
gRPC reply contains an objectRef that is encodded by Base64.
|
||||
This function is used to decode the objectRef.
|
||||
Note that there are times that objectRef is already decoded as
|
||||
a hex string. In this case, just convert it to a binary number.
|
||||
"""
|
||||
if object_id.endswith("="):
|
||||
# If the object id ends with =, that means it is base64 encoded.
|
||||
# Object ids will always have = as a padding
|
||||
# when it is base64 encoded because objectID is always 20B.
|
||||
return base64.standard_b64decode(object_id)
|
||||
if object_ref.endswith("="):
|
||||
# If the object ref ends with =, that means it is base64 encoded.
|
||||
# Object refs will always have = as a padding
|
||||
# when it is base64 encoded because objectRef is always 20B.
|
||||
return base64.standard_b64decode(object_ref)
|
||||
else:
|
||||
return ray.utils.hex_to_binary(object_id)
|
||||
return ray.utils.hex_to_binary(object_ref)
|
||||
|
||||
|
||||
class SortingType(Enum):
|
||||
@@ -65,8 +65,8 @@ class MemoryTableEntry:
|
||||
# object info
|
||||
self.object_size = int(object_ref.get("objectSize", -1))
|
||||
self.call_site = object_ref.get("callSite", "<Unknown>")
|
||||
self.object_id = ray.ObjectID(
|
||||
decode_object_id_if_needed(object_ref["objectId"]))
|
||||
self.object_ref = ray.ObjectRef(
|
||||
decode_object_ref_if_needed(object_ref["objectId"]))
|
||||
|
||||
# reference info
|
||||
self.local_ref_count = int(object_ref.get("localRefCount", 0))
|
||||
@@ -74,19 +74,19 @@ class MemoryTableEntry:
|
||||
self.submitted_task_ref_count = int(
|
||||
object_ref.get("submittedTaskRefCount", 0))
|
||||
self.contained_in_owned = [
|
||||
ray.ObjectID(decode_object_id_if_needed(object_id))
|
||||
for object_id in object_ref.get("containedInOwned", [])
|
||||
ray.ObjectRef(decode_object_ref_if_needed(object_ref))
|
||||
for object_ref in object_ref.get("containedInOwned", [])
|
||||
]
|
||||
self.reference_type = self._get_reference_type()
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
# If the entry doesn't have a reference type or some invalid state,
|
||||
# (e.g., no object ID presented), it is considered invalid.
|
||||
# (e.g., no object ref presented), it is considered invalid.
|
||||
if (not self.pinned_in_memory and self.local_ref_count == 0
|
||||
and self.submitted_task_ref_count == 0
|
||||
and len(self.contained_in_owned) == 0):
|
||||
return False
|
||||
elif self.object_id.is_nil():
|
||||
elif self.object_ref.is_nil():
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@@ -99,7 +99,7 @@ class MemoryTableEntry:
|
||||
"group by type {} is invalid.".format(group_by_type))
|
||||
|
||||
def _get_reference_type(self) -> str:
|
||||
if self._is_object_id_actor_handle():
|
||||
if self._is_object_ref_actor_handle():
|
||||
return ReferenceType.ACTOR_HANDLE
|
||||
if self.pinned_in_memory:
|
||||
return ReferenceType.PINNED_IN_MEMORY
|
||||
@@ -112,18 +112,18 @@ class MemoryTableEntry:
|
||||
else:
|
||||
return ReferenceType.UNKNOWN_STATUS
|
||||
|
||||
def _is_object_id_actor_handle(self) -> bool:
|
||||
object_id_hex = self.object_id.hex()
|
||||
def _is_object_ref_actor_handle(self) -> bool:
|
||||
object_ref_hex = self.object_ref.hex()
|
||||
|
||||
# random (8B) | ActorID(6B) | flag (2B) | index (6B)
|
||||
# ActorID(6B) == ActorRandomByte(4B) + JobID(2B)
|
||||
# If random bytes are all 'f', but ActorRandomBytes
|
||||
# are not all 'f', that means it is an actor creation
|
||||
# task, which is an actor handle.
|
||||
random_bits = object_id_hex[:TASKID_RANDOM_BITS_SIZE]
|
||||
actor_random_bits = object_id_hex[TASKID_RANDOM_BITS_SIZE:
|
||||
TASKID_RANDOM_BITS_SIZE +
|
||||
ACTORID_RANDOM_BITS_SIZE]
|
||||
random_bits = object_ref_hex[:TASKID_RANDOM_BITS_SIZE]
|
||||
actor_random_bits = object_ref_hex[TASKID_RANDOM_BITS_SIZE:
|
||||
TASKID_RANDOM_BITS_SIZE +
|
||||
ACTORID_RANDOM_BITS_SIZE]
|
||||
if (random_bits == "f" * 16 and not actor_random_bits == "f" * 8):
|
||||
return True
|
||||
else:
|
||||
@@ -131,7 +131,7 @@ class MemoryTableEntry:
|
||||
|
||||
def __dict__(self):
|
||||
return {
|
||||
"object_id": self.object_id.hex(),
|
||||
"object_ref": self.object_ref.hex(),
|
||||
"pid": self.pid,
|
||||
"node_ip_address": self.node_address,
|
||||
"object_size": self.object_size,
|
||||
@@ -141,7 +141,7 @@ class MemoryTableEntry:
|
||||
"pinned_in_memory": self.pinned_in_memory,
|
||||
"submitted_task_ref_count": self.submitted_task_ref_count,
|
||||
"contained_in_owned": [
|
||||
object_id.hex() for object_id in self.contained_in_owned
|
||||
object_ref.hex() for object_ref in self.contained_in_owned
|
||||
],
|
||||
"type": "Driver" if self.is_driver else "Worker"
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class NodeStats(threading.Thread):
|
||||
"jobId": "",
|
||||
"numExecutedTasks": 0,
|
||||
"numLocalObjects": 0,
|
||||
"numObjectIdsInScope": 0,
|
||||
"numObjectRefsInScope": 0,
|
||||
"port": 0,
|
||||
"state": 0,
|
||||
"taskQueueLength": 0,
|
||||
|
||||
@@ -170,11 +170,11 @@ class UnreconstructableError(RayError):
|
||||
reconstruct the object.
|
||||
|
||||
Attributes:
|
||||
object_id: ID of the object.
|
||||
object_ref: ID of the object.
|
||||
"""
|
||||
|
||||
def __init__(self, object_id):
|
||||
self.object_id = object_id
|
||||
def __init__(self, object_ref):
|
||||
self.object_ref = object_ref
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
@@ -183,7 +183,7 @@ class UnreconstructableError(RayError):
|
||||
"memory available with ray.init(object_store_memory=<bytes>) "
|
||||
"or setting object store limits with "
|
||||
"ray.remote(object_store_memory=<bytes>). See also: {}".format(
|
||||
self.object_id.hex(),
|
||||
self.object_ref.hex(),
|
||||
"https://docs.ray.io/en/latest/memory-management.html"))
|
||||
|
||||
|
||||
|
||||
@@ -2,58 +2,58 @@ import ray
|
||||
import numpy as np
|
||||
|
||||
|
||||
def get(object_ids):
|
||||
def get(object_refs):
|
||||
"""Get a single or a collection of remote objects from the object store.
|
||||
|
||||
This method is identical to `ray.get` except it adds support for tuples,
|
||||
ndarrays and dictionaries.
|
||||
|
||||
Args:
|
||||
object_ids: Object ID of the object to get, a list, tuple, ndarray of
|
||||
object IDs to get or a dict of {key: object ID}.
|
||||
object_refs: Object ref of the object to get, a list, tuple, ndarray of
|
||||
object refs to get or a dict of {key: object ref}.
|
||||
|
||||
Returns:
|
||||
A Python object, a list of Python objects or a dict of {key: object}.
|
||||
"""
|
||||
if isinstance(object_ids, (tuple, np.ndarray)):
|
||||
return ray.get(list(object_ids))
|
||||
elif isinstance(object_ids, dict):
|
||||
if isinstance(object_refs, (tuple, np.ndarray)):
|
||||
return ray.get(list(object_refs))
|
||||
elif isinstance(object_refs, dict):
|
||||
keys_to_get = [
|
||||
k for k, v in object_ids.items() if isinstance(v, ray.ObjectID)
|
||||
k for k, v in object_refs.items() if isinstance(v, ray.ObjectRef)
|
||||
]
|
||||
ids_to_get = [
|
||||
v for k, v in object_ids.items() if isinstance(v, ray.ObjectID)
|
||||
v for k, v in object_refs.items() if isinstance(v, ray.ObjectRef)
|
||||
]
|
||||
values = ray.get(ids_to_get)
|
||||
|
||||
result = object_ids.copy()
|
||||
result = object_refs.copy()
|
||||
for key, value in zip(keys_to_get, values):
|
||||
result[key] = value
|
||||
return result
|
||||
else:
|
||||
return ray.get(object_ids)
|
||||
return ray.get(object_refs)
|
||||
|
||||
|
||||
def wait(object_ids, num_returns=1, timeout=None):
|
||||
def wait(object_refs, num_returns=1, timeout=None):
|
||||
"""Return a list of IDs that are ready and a list of IDs that are not.
|
||||
|
||||
This method is identical to `ray.wait` except it adds support for tuples
|
||||
and ndarrays.
|
||||
|
||||
Args:
|
||||
object_ids (List[ObjectID], Tuple(ObjectID), np.array(ObjectID)):
|
||||
List like of object IDs for objects that may or may not be ready.
|
||||
object_refs (List[ObjectRef], Tuple(ObjectRef), np.array(ObjectRef)):
|
||||
List like of object refs for objects that may or may not be ready.
|
||||
Note that these IDs must be unique.
|
||||
num_returns (int): The number of object IDs that should be returned.
|
||||
num_returns (int): The number of object refs that should be returned.
|
||||
timeout (float): The maximum amount of time in seconds to wait before
|
||||
returning.
|
||||
|
||||
Returns:
|
||||
A list of object IDs that are ready and a list of the remaining object
|
||||
A list of object refs that are ready and a list of the remaining object
|
||||
IDs.
|
||||
"""
|
||||
if isinstance(object_ids, (tuple, np.ndarray)):
|
||||
if isinstance(object_refs, (tuple, np.ndarray)):
|
||||
return ray.wait(
|
||||
list(object_ids), num_returns=num_returns, timeout=timeout)
|
||||
list(object_refs), num_returns=num_returns, timeout=timeout)
|
||||
|
||||
return ray.wait(object_ids, num_returns=num_returns, timeout=timeout)
|
||||
return ray.wait(object_refs, num_returns=num_returns, timeout=timeout)
|
||||
|
||||
@@ -6,21 +6,22 @@ BLOCK_SIZE = 10
|
||||
|
||||
|
||||
class DistArray:
|
||||
def __init__(self, shape, objectids=None):
|
||||
def __init__(self, shape, object_refs=None):
|
||||
self.shape = shape
|
||||
self.ndim = len(shape)
|
||||
self.num_blocks = [
|
||||
int(np.ceil(1.0 * a / BLOCK_SIZE)) for a in self.shape
|
||||
]
|
||||
if objectids is not None:
|
||||
self.objectids = objectids
|
||||
if object_refs is not None:
|
||||
self.object_refs = object_refs
|
||||
else:
|
||||
self.objectids = np.empty(self.num_blocks, dtype=object)
|
||||
if self.num_blocks != list(self.objectids.shape):
|
||||
raise Exception("The fields `num_blocks` and `objectids` are "
|
||||
"inconsistent, `num_blocks` is {} and `objectids` "
|
||||
"has shape {}".format(self.num_blocks,
|
||||
list(self.objectids.shape)))
|
||||
self.object_refs = np.empty(self.num_blocks, dtype=object)
|
||||
if self.num_blocks != list(self.object_refs.shape):
|
||||
raise Exception(
|
||||
"The fields `num_blocks` and `object_refs` are "
|
||||
"inconsistent, `num_blocks` is {} and `object_refs` "
|
||||
"has shape {}".format(self.num_blocks,
|
||||
list(self.object_refs.shape)))
|
||||
|
||||
@staticmethod
|
||||
def compute_block_lower(index, shape):
|
||||
@@ -52,14 +53,14 @@ class DistArray:
|
||||
return [int(np.ceil(1.0 * a / BLOCK_SIZE)) for a in shape]
|
||||
|
||||
def assemble(self):
|
||||
"""Assemble an array from a distributed array of object IDs."""
|
||||
first_block = ray.get(self.objectids[(0, ) * self.ndim])
|
||||
"""Assemble an array from a distributed array of object refs."""
|
||||
first_block = ray.get(self.object_refs[(0, ) * self.ndim])
|
||||
dtype = first_block.dtype
|
||||
result = np.zeros(self.shape, dtype=dtype)
|
||||
for index in np.ndindex(*self.num_blocks):
|
||||
lower = DistArray.compute_block_lower(index, self.shape)
|
||||
upper = DistArray.compute_block_upper(index, self.shape)
|
||||
value = ray.get(self.objectids[index])
|
||||
value = ray.get(self.object_refs[index])
|
||||
result[tuple(slice(l, u) for (l, u) in zip(lower, upper))] = value
|
||||
return result
|
||||
|
||||
@@ -83,7 +84,7 @@ def numpy_to_dist(a):
|
||||
lower = DistArray.compute_block_lower(index, a.shape)
|
||||
upper = DistArray.compute_block_upper(index, a.shape)
|
||||
idx = tuple(slice(l, u) for (l, u) in zip(lower, upper))
|
||||
result.objectids[index] = ray.put(a[idx])
|
||||
result.object_refs[index] = ray.put(a[idx])
|
||||
return result
|
||||
|
||||
|
||||
@@ -91,7 +92,7 @@ def numpy_to_dist(a):
|
||||
def zeros(shape, dtype_name="float"):
|
||||
result = DistArray(shape)
|
||||
for index in np.ndindex(*result.num_blocks):
|
||||
result.objectids[index] = ra.zeros.remote(
|
||||
result.object_refs[index] = ra.zeros.remote(
|
||||
DistArray.compute_block_shape(index, shape), dtype_name=dtype_name)
|
||||
return result
|
||||
|
||||
@@ -100,7 +101,7 @@ def zeros(shape, dtype_name="float"):
|
||||
def ones(shape, dtype_name="float"):
|
||||
result = DistArray(shape)
|
||||
for index in np.ndindex(*result.num_blocks):
|
||||
result.objectids[index] = ra.ones.remote(
|
||||
result.object_refs[index] = ra.ones.remote(
|
||||
DistArray.compute_block_shape(index, shape), dtype_name=dtype_name)
|
||||
return result
|
||||
|
||||
@@ -111,7 +112,7 @@ def copy(a):
|
||||
for index in np.ndindex(*result.num_blocks):
|
||||
# We don't need to actually copy the objects because remote objects are
|
||||
# immutable.
|
||||
result.objectids[index] = a.objectids[index]
|
||||
result.object_refs[index] = a.object_refs[index]
|
||||
return result
|
||||
|
||||
|
||||
@@ -123,10 +124,10 @@ def eye(dim1, dim2=-1, dtype_name="float"):
|
||||
for (i, j) in np.ndindex(*result.num_blocks):
|
||||
block_shape = DistArray.compute_block_shape([i, j], shape)
|
||||
if i == j:
|
||||
result.objectids[i, j] = ra.eye.remote(
|
||||
result.object_refs[i, j] = ra.eye.remote(
|
||||
block_shape[0], block_shape[1], dtype_name=dtype_name)
|
||||
else:
|
||||
result.objectids[i, j] = ra.zeros.remote(
|
||||
result.object_refs[i, j] = ra.zeros.remote(
|
||||
block_shape, dtype_name=dtype_name)
|
||||
return result
|
||||
|
||||
@@ -139,11 +140,12 @@ def triu(a):
|
||||
result = DistArray(a.shape)
|
||||
for (i, j) in np.ndindex(*result.num_blocks):
|
||||
if i < j:
|
||||
result.objectids[i, j] = ra.copy.remote(a.objectids[i, j])
|
||||
result.object_refs[i, j] = ra.copy.remote(a.object_refs[i, j])
|
||||
elif i == j:
|
||||
result.objectids[i, j] = ra.triu.remote(a.objectids[i, j])
|
||||
result.object_refs[i, j] = ra.triu.remote(a.object_refs[i, j])
|
||||
else:
|
||||
result.objectids[i, j] = ra.zeros_like.remote(a.objectids[i, j])
|
||||
result.object_refs[i, j] = ra.zeros_like.remote(
|
||||
a.object_refs[i, j])
|
||||
return result
|
||||
|
||||
|
||||
@@ -155,11 +157,12 @@ def tril(a):
|
||||
result = DistArray(a.shape)
|
||||
for (i, j) in np.ndindex(*result.num_blocks):
|
||||
if i > j:
|
||||
result.objectids[i, j] = ra.copy.remote(a.objectids[i, j])
|
||||
result.object_refs[i, j] = ra.copy.remote(a.object_refs[i, j])
|
||||
elif i == j:
|
||||
result.objectids[i, j] = ra.tril.remote(a.objectids[i, j])
|
||||
result.object_refs[i, j] = ra.tril.remote(a.object_refs[i, j])
|
||||
else:
|
||||
result.objectids[i, j] = ra.zeros_like.remote(a.objectids[i, j])
|
||||
result.object_refs[i, j] = ra.zeros_like.remote(
|
||||
a.object_refs[i, j])
|
||||
return result
|
||||
|
||||
|
||||
@@ -191,8 +194,8 @@ def dot(a, b):
|
||||
shape = [a.shape[0], b.shape[1]]
|
||||
result = DistArray(shape)
|
||||
for (i, j) in np.ndindex(*result.num_blocks):
|
||||
args = list(a.objectids[i, :]) + list(b.objectids[:, j])
|
||||
result.objectids[i, j] = blockwise_dot.remote(*args)
|
||||
args = list(a.object_refs[i, :]) + list(b.object_refs[:, j])
|
||||
result.object_refs[i, j] = blockwise_dot.remote(*args)
|
||||
return result
|
||||
|
||||
|
||||
@@ -203,9 +206,9 @@ def subblocks(a, *ranges):
|
||||
the `a`. The result and `a` will have the same number of dimensions. For
|
||||
example,
|
||||
subblocks(a, [0, 1], [2, 4])
|
||||
will produce a DistArray whose objectids are
|
||||
[[a.objectids[0, 2], a.objectids[0, 4]],
|
||||
[a.objectids[1, 2], a.objectids[1, 4]]]
|
||||
will produce a DistArray whose object_refs are
|
||||
[[a.object_refs[0, 2], a.object_refs[0, 4]],
|
||||
[a.object_refs[1, 2], a.object_refs[1, 4]]]
|
||||
We allow the user to pass in an empty list [] to indicate the full range.
|
||||
"""
|
||||
ranges = list(ranges)
|
||||
@@ -236,7 +239,7 @@ def subblocks(a, *ranges):
|
||||
for i in range(a.ndim)]
|
||||
result = DistArray(shape)
|
||||
for index in np.ndindex(*result.num_blocks):
|
||||
result.objectids[index] = a.objectids[tuple(
|
||||
result.object_refs[index] = a.object_refs[tuple(
|
||||
ranges[i][index[i]] for i in range(a.ndim))]
|
||||
return result
|
||||
|
||||
@@ -250,7 +253,7 @@ def transpose(a):
|
||||
result = DistArray([a.shape[1], a.shape[0]])
|
||||
for i in range(result.num_blocks[0]):
|
||||
for j in range(result.num_blocks[1]):
|
||||
result.objectids[i, j] = ra.transpose.remote(a.objectids[j, i])
|
||||
result.object_refs[i, j] = ra.transpose.remote(a.object_refs[j, i])
|
||||
return result
|
||||
|
||||
|
||||
@@ -263,8 +266,8 @@ def add(x1, x2):
|
||||
x1.shape, x2.shape))
|
||||
result = DistArray(x1.shape)
|
||||
for index in np.ndindex(*result.num_blocks):
|
||||
result.objectids[index] = ra.add.remote(x1.objectids[index],
|
||||
x2.objectids[index])
|
||||
result.object_refs[index] = ra.add.remote(x1.object_refs[index],
|
||||
x2.object_refs[index])
|
||||
return result
|
||||
|
||||
|
||||
@@ -277,6 +280,6 @@ def subtract(x1, x2):
|
||||
.format(x1.shape, x2.shape))
|
||||
result = DistArray(x1.shape)
|
||||
for index in np.ndindex(*result.num_blocks):
|
||||
result.objectids[index] = ra.subtract.remote(x1.objectids[index],
|
||||
x2.objectids[index])
|
||||
result.object_refs[index] = ra.subtract.remote(x1.object_refs[index],
|
||||
x2.object_refs[index])
|
||||
return result
|
||||
|
||||
@@ -35,7 +35,7 @@ def tsqr(a):
|
||||
q_tree = np.empty((num_blocks, K), dtype=object)
|
||||
current_rs = []
|
||||
for i in range(num_blocks):
|
||||
block = a.objectids[i, 0]
|
||||
block = a.object_refs[i, 0]
|
||||
q, r = ra.linalg.qr.remote(block)
|
||||
q_tree[i, 0] = q
|
||||
current_rs.append(r)
|
||||
@@ -57,8 +57,8 @@ def tsqr(a):
|
||||
else:
|
||||
q_shape = [a.shape[0], a.shape[0]]
|
||||
q_num_blocks = core.DistArray.compute_num_blocks(q_shape)
|
||||
q_objectids = np.empty(q_num_blocks, dtype=object)
|
||||
q_result = core.DistArray(q_shape, q_objectids)
|
||||
q_object_refs = np.empty(q_num_blocks, dtype=object)
|
||||
q_result = core.DistArray(q_shape, q_object_refs)
|
||||
|
||||
# reconstruct output
|
||||
for i in range(num_blocks):
|
||||
@@ -75,7 +75,7 @@ def tsqr(a):
|
||||
q_block_current = ra.dot.remote(
|
||||
q_block_current,
|
||||
ra.subarray.remote(q_tree[ith_index, j], lower, upper))
|
||||
q_result.objectids[i] = q_block_current
|
||||
q_result.object_refs[i] = q_block_current
|
||||
r = current_rs[0]
|
||||
return q_result, ray.get(r)
|
||||
|
||||
@@ -142,7 +142,7 @@ def tsqr_hr(a):
|
||||
q, r_temp = tsqr.remote(a)
|
||||
y, u, s = modified_lu.remote(q)
|
||||
y_blocked = ray.get(y)
|
||||
t, y_top = tsqr_hr_helper1.remote(u, s, y_blocked.objectids[0, 0],
|
||||
t, y_top = tsqr_hr_helper1.remote(u, s, y_blocked.object_refs[0, 0],
|
||||
a.shape[1])
|
||||
r = tsqr_hr_helper2.remote(s, r_temp)
|
||||
return ray.get(y), ray.get(t), ray.get(y_top), ray.get(r)
|
||||
@@ -167,9 +167,9 @@ def qr(a):
|
||||
k = min(m, n)
|
||||
|
||||
# we will store our scratch work in a_work
|
||||
a_work = core.DistArray(a.shape, np.copy(a.objectids))
|
||||
a_work = core.DistArray(a.shape, np.copy(a.object_refs))
|
||||
|
||||
result_dtype = np.linalg.qr(ray.get(a.objectids[0, 0]))[0].dtype.name
|
||||
result_dtype = np.linalg.qr(ray.get(a.object_refs[0, 0]))[0].dtype.name
|
||||
# TODO(rkn): It would be preferable not to get this right after creating
|
||||
# it.
|
||||
r_res = ray.get(core.zeros.remote([k, n], result_dtype))
|
||||
@@ -188,28 +188,29 @@ def qr(a):
|
||||
y_val = ray.get(y)
|
||||
|
||||
for j in range(i, a.num_blocks[0]):
|
||||
y_res.objectids[j, i] = y_val.objectids[j - i, 0]
|
||||
y_res.object_refs[j, i] = y_val.object_refs[j - i, 0]
|
||||
if a.shape[0] > a.shape[1]:
|
||||
# in this case, R needs to be square
|
||||
R_shape = ray.get(ra.shape.remote(R))
|
||||
eye_temp = ra.eye.remote(
|
||||
R_shape[1], R_shape[0], dtype_name=result_dtype)
|
||||
r_res.objectids[i, i] = ra.dot.remote(eye_temp, R)
|
||||
r_res.object_refs[i, i] = ra.dot.remote(eye_temp, R)
|
||||
else:
|
||||
r_res.objectids[i, i] = R
|
||||
r_res.object_refs[i, i] = R
|
||||
Ts.append(core.numpy_to_dist.remote(t))
|
||||
|
||||
for c in range(i + 1, a.num_blocks[1]):
|
||||
W_rcs = []
|
||||
for r in range(i, a.num_blocks[0]):
|
||||
y_ri = y_val.objectids[r - i, 0]
|
||||
W_rcs.append(qr_helper2.remote(y_ri, a_work.objectids[r, c]))
|
||||
y_ri = y_val.object_refs[r - i, 0]
|
||||
W_rcs.append(qr_helper2.remote(y_ri, a_work.object_refs[r, c]))
|
||||
W_c = ra.sum_list.remote(*W_rcs)
|
||||
for r in range(i, a.num_blocks[0]):
|
||||
y_ri = y_val.objectids[r - i, 0]
|
||||
A_rc = qr_helper1.remote(a_work.objectids[r, c], y_ri, t, W_c)
|
||||
a_work.objectids[r, c] = A_rc
|
||||
r_res.objectids[i, c] = a_work.objectids[i, c]
|
||||
y_ri = y_val.object_refs[r - i, 0]
|
||||
A_rc = qr_helper1.remote(a_work.object_refs[r, c], y_ri, t,
|
||||
W_c)
|
||||
a_work.object_refs[r, c] = A_rc
|
||||
r_res.object_refs[i, c] = a_work.object_refs[i, c]
|
||||
|
||||
# construct q_res from Ys and Ts
|
||||
q = core.eye.remote(m, k, dtype_name=result_dtype)
|
||||
|
||||
@@ -8,9 +8,9 @@ from .core import DistArray
|
||||
@ray.remote
|
||||
def normal(shape):
|
||||
num_blocks = DistArray.compute_num_blocks(shape)
|
||||
objectids = np.empty(num_blocks, dtype=object)
|
||||
object_refs = np.empty(num_blocks, dtype=object)
|
||||
for index in np.ndindex(*num_blocks):
|
||||
objectids[index] = ra.random.normal.remote(
|
||||
object_refs[index] = ra.random.normal.remote(
|
||||
DistArray.compute_block_shape(index, shape))
|
||||
result = DistArray(shape, objectids)
|
||||
result = DistArray(shape, object_refs)
|
||||
return result
|
||||
|
||||
@@ -253,7 +253,7 @@ cdef class PythonFunctionDescriptor(FunctionDescriptor):
|
||||
"""Get the function id calculated from this descriptor.
|
||||
|
||||
Returns:
|
||||
The value of ray.ObjectID that represents the function id.
|
||||
The value of ray.ObjectRef that represents the function id.
|
||||
"""
|
||||
if not self._function_id:
|
||||
self._function_id = self._get_function_id()
|
||||
@@ -266,7 +266,7 @@ cdef class PythonFunctionDescriptor(FunctionDescriptor):
|
||||
descriptor.
|
||||
|
||||
Returns:
|
||||
ray.ObjectID to represent the function descriptor.
|
||||
ray.ObjectRef to represent the function descriptor.
|
||||
"""
|
||||
function_id_hash = hashlib.sha1()
|
||||
# Include the function module and name in the hash.
|
||||
|
||||
@@ -12,8 +12,8 @@ from ray.includes.unique_ids cimport (
|
||||
cdef extern from "ray/gcs/gcs_client/global_state_accessor.h" nogil:
|
||||
cdef cppclass CGlobalStateAccessor "ray::gcs::GlobalStateAccessor":
|
||||
CGlobalStateAccessor(const c_string &redis_address,
|
||||
const c_string &redis_password,
|
||||
c_bool is_test)
|
||||
const c_string &redis_password,
|
||||
c_bool is_test)
|
||||
c_bool Connect()
|
||||
void Disconnect()
|
||||
c_vector[c_string] GetAllJobInfo()
|
||||
|
||||
@@ -16,12 +16,17 @@ cdef class GlobalStateAccessor:
|
||||
cdef:
|
||||
unique_ptr[CGlobalStateAccessor] inner
|
||||
|
||||
def __init__(self, redis_address, redis_password, c_bool is_test_client=False):
|
||||
def __init__(self, redis_address, redis_password,
|
||||
c_bool is_test_client=False):
|
||||
if not redis_password:
|
||||
redis_password = ""
|
||||
self.inner.reset(
|
||||
new CGlobalStateAccessor(redis_address.encode("ascii"),
|
||||
redis_password.encode("ascii"), is_test_client))
|
||||
new CGlobalStateAccessor(
|
||||
redis_address.encode("ascii"),
|
||||
redis_password.encode("ascii"),
|
||||
is_test_client,
|
||||
),
|
||||
)
|
||||
|
||||
def connect(self):
|
||||
return self.inner.get().Connect()
|
||||
@@ -41,8 +46,9 @@ cdef class GlobalStateAccessor:
|
||||
def get_object_table(self):
|
||||
return self.inner.get().GetAllObjectInfo()
|
||||
|
||||
def get_object_info(self, object_id):
|
||||
object_info = self.inner.get().GetObjectInfo(CObjectID.FromBinary(object_id.binary()))
|
||||
def get_object_info(self, object_ref):
|
||||
object_info = self.inner.get().GetObjectInfo(
|
||||
CObjectID.FromBinary(object_ref.binary()))
|
||||
if object_info:
|
||||
return c_string(object_info.get().data(), object_info.get().size())
|
||||
return None
|
||||
@@ -51,19 +57,22 @@ cdef class GlobalStateAccessor:
|
||||
return self.inner.get().GetAllActorInfo()
|
||||
|
||||
def get_actor_info(self, actor_id):
|
||||
actor_info = self.inner.get().GetActorInfo(CActorID.FromBinary(actor_id.binary()))
|
||||
actor_info = self.inner.get().GetActorInfo(
|
||||
CActorID.FromBinary(actor_id.binary()))
|
||||
if actor_info:
|
||||
return c_string(actor_info.get().data(), actor_info.get().size())
|
||||
return None
|
||||
|
||||
def get_node_resource_info(self, node_id):
|
||||
return self.inner.get().GetNodeResourceInfo(CClientID.FromBinary(node_id.binary()))
|
||||
return self.inner.get().GetNodeResourceInfo(
|
||||
CClientID.FromBinary(node_id.binary()))
|
||||
|
||||
def get_worker_table(self):
|
||||
return self.inner.get().GetAllWorkerInfo()
|
||||
|
||||
def get_worker_info(self, worker_id):
|
||||
worker_info = self.inner.get().GetWorkerInfo(CWorkerID.FromBinary(worker_id.binary()))
|
||||
worker_info = self.inner.get().GetWorkerInfo(
|
||||
CWorkerID.FromBinary(worker_id.binary()))
|
||||
if worker_info:
|
||||
return c_string(worker_info.get().data(), worker_info.get().size())
|
||||
return None
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
from ray.includes.unique_ids cimport CObjectID
|
||||
|
||||
import ray
|
||||
|
||||
cdef class ObjectRef(BaseID):
|
||||
|
||||
def __init__(self, id):
|
||||
check_id(id)
|
||||
self.data = CObjectID.FromBinary(<c_string>id)
|
||||
self.in_core_worker = False
|
||||
|
||||
worker = ray.worker.global_worker
|
||||
# TODO(edoakes): We should be able to remove the in_core_worker flag.
|
||||
# But there are still some dummy object refs being created outside the
|
||||
# context of a core worker.
|
||||
if hasattr(worker, "core_worker"):
|
||||
worker.core_worker.add_object_ref_reference(self)
|
||||
self.in_core_worker = True
|
||||
|
||||
def __dealloc__(self):
|
||||
if self.in_core_worker:
|
||||
try:
|
||||
worker = ray.worker.global_worker
|
||||
worker.core_worker.remove_object_ref_reference(self)
|
||||
except Exception as e:
|
||||
# There is a strange error in rllib that causes the above to
|
||||
# fail. Somehow the global 'ray' variable corresponding to the
|
||||
# imported package is None when this gets called. Unfortunately
|
||||
# this is hard to debug because __dealloc__ is called during
|
||||
# garbage collection so we can't get a good stack trace. In any
|
||||
# case, there's not much we can do besides ignore it
|
||||
# (re-importing ray won't help).
|
||||
pass
|
||||
|
||||
cdef CObjectID native(self):
|
||||
return <CObjectID>self.data
|
||||
|
||||
def size(self):
|
||||
return CObjectID.Size()
|
||||
|
||||
def binary(self):
|
||||
return self.data.Binary()
|
||||
|
||||
def hex(self):
|
||||
return decode(self.data.Hex())
|
||||
|
||||
def is_nil(self):
|
||||
return self.data.IsNil()
|
||||
|
||||
def task_id(self):
|
||||
return TaskID(self.data.TaskId().Binary())
|
||||
|
||||
cdef size_t hash(self):
|
||||
return self.data.Hash()
|
||||
|
||||
@classmethod
|
||||
def nil(cls):
|
||||
return cls(CObjectID.Nil().Binary())
|
||||
|
||||
@classmethod
|
||||
def from_random(cls):
|
||||
return cls(CObjectID.FromRandom().Binary())
|
||||
|
||||
def __await__(self):
|
||||
# Delayed import because this can only be imported in py3.
|
||||
from ray.async_compat import get_async
|
||||
return get_async(self).__await__()
|
||||
|
||||
def as_future(self):
|
||||
# Delayed import because this can only be imported in py3.
|
||||
from ray.async_compat import get_async
|
||||
return get_async(self)
|
||||
@@ -177,7 +177,8 @@ cdef class MessagePackSerializer(object):
|
||||
raise Exception('Unrecognized ext type id: {}'.format(code))
|
||||
try:
|
||||
gc.disable() # Performance optimization for msgpack.
|
||||
return msgpack.loads(s, ext_hook=_ext_hook, raw=False, strict_map_key=False)
|
||||
return msgpack.loads(s, ext_hook=_ext_hook, raw=False,
|
||||
strict_map_key=False)
|
||||
finally:
|
||||
gc.enable()
|
||||
|
||||
@@ -371,11 +372,11 @@ cdef class Pickle5Writer:
|
||||
cdef class SerializedObject(object):
|
||||
cdef:
|
||||
object _metadata
|
||||
object _contained_object_ids
|
||||
object _contained_object_refs
|
||||
|
||||
def __init__(self, metadata, contained_object_ids=None):
|
||||
def __init__(self, metadata, contained_object_refs=None):
|
||||
self._metadata = metadata
|
||||
self._contained_object_ids = contained_object_ids or []
|
||||
self._contained_object_refs = contained_object_refs or []
|
||||
|
||||
@property
|
||||
def total_bytes(self):
|
||||
@@ -387,8 +388,8 @@ cdef class SerializedObject(object):
|
||||
return self._metadata
|
||||
|
||||
@property
|
||||
def contained_object_ids(self):
|
||||
return self._contained_object_ids
|
||||
def contained_object_refs(self):
|
||||
return self._contained_object_refs
|
||||
|
||||
@cython.boundscheck(False)
|
||||
@cython.wraparound(False)
|
||||
@@ -404,9 +405,9 @@ cdef class Pickle5SerializedObject(SerializedObject):
|
||||
object _total_bytes
|
||||
|
||||
def __init__(self, metadata, inband, Pickle5Writer writer,
|
||||
contained_object_ids):
|
||||
contained_object_refs):
|
||||
super(Pickle5SerializedObject, self).__init__(metadata,
|
||||
contained_object_ids)
|
||||
contained_object_refs)
|
||||
self.inband = inband
|
||||
self.writer = writer
|
||||
# cached total bytes
|
||||
@@ -438,13 +439,17 @@ cdef class MessagePackSerializedObject(SerializedObject):
|
||||
def __init__(self, metadata, msgpack_data,
|
||||
SerializedObject nest_serialized_object=None):
|
||||
if nest_serialized_object:
|
||||
contained_object_ids = nest_serialized_object.contained_object_ids
|
||||
contained_object_refs = (
|
||||
nest_serialized_object.contained_object_refs
|
||||
)
|
||||
total_bytes = nest_serialized_object.total_bytes
|
||||
else:
|
||||
contained_object_ids = []
|
||||
contained_object_refs = []
|
||||
total_bytes = 0
|
||||
super(MessagePackSerializedObject, self).__init__(metadata,
|
||||
contained_object_ids)
|
||||
super(MessagePackSerializedObject, self).__init__(
|
||||
metadata,
|
||||
contained_object_refs,
|
||||
)
|
||||
self.nest_serialized_object = nest_serialized_object
|
||||
self.msgpack_header = msgpack_header = msgpack.dumps(len(msgpack_data))
|
||||
self.msgpack_data = msgpack_data
|
||||
|
||||
@@ -126,75 +126,6 @@ cdef class UniqueID(BaseID):
|
||||
return self.data.Hash()
|
||||
|
||||
|
||||
cdef class ObjectID(BaseID):
|
||||
|
||||
def __init__(self, id):
|
||||
check_id(id)
|
||||
self.data = CObjectID.FromBinary(<c_string>id)
|
||||
self.in_core_worker = False
|
||||
|
||||
worker = ray.worker.global_worker
|
||||
# TODO(edoakes): We should be able to remove the in_core_worker flag.
|
||||
# But there are still some dummy object IDs being created outside the
|
||||
# context of a core worker.
|
||||
if hasattr(worker, "core_worker"):
|
||||
worker.core_worker.add_object_id_reference(self)
|
||||
self.in_core_worker = True
|
||||
|
||||
def __dealloc__(self):
|
||||
if self.in_core_worker:
|
||||
try:
|
||||
worker = ray.worker.global_worker
|
||||
worker.core_worker.remove_object_id_reference(self)
|
||||
except Exception as e:
|
||||
# There is a strange error in rllib that causes the above to
|
||||
# fail. Somehow the global 'ray' variable corresponding to the
|
||||
# imported package is None when this gets called. Unfortunately
|
||||
# this is hard to debug because __dealloc__ is called during
|
||||
# garbage collection so we can't get a good stack trace. In any
|
||||
# case, there's not much we can do besides ignore it
|
||||
# (re-importing ray won't help).
|
||||
pass
|
||||
|
||||
cdef CObjectID native(self):
|
||||
return <CObjectID>self.data
|
||||
|
||||
def size(self):
|
||||
return CObjectID.Size()
|
||||
|
||||
def binary(self):
|
||||
return self.data.Binary()
|
||||
|
||||
def hex(self):
|
||||
return decode(self.data.Hex())
|
||||
|
||||
def is_nil(self):
|
||||
return self.data.IsNil()
|
||||
|
||||
def task_id(self):
|
||||
return TaskID(self.data.TaskId().Binary())
|
||||
|
||||
cdef size_t hash(self):
|
||||
return self.data.Hash()
|
||||
|
||||
@classmethod
|
||||
def nil(cls):
|
||||
return cls(CObjectID.Nil().Binary())
|
||||
|
||||
@classmethod
|
||||
def from_random(cls):
|
||||
return cls(CObjectID.FromRandom().Binary())
|
||||
|
||||
def __await__(self):
|
||||
# Delayed import because this can only be imported in py3.
|
||||
from ray.async_compat import get_async
|
||||
return get_async(self).__await__()
|
||||
|
||||
def as_future(self):
|
||||
# Delayed import because this can only be imported in py3.
|
||||
from ray.async_compat import get_async
|
||||
return get_async(self)
|
||||
|
||||
cdef class TaskID(BaseID):
|
||||
cdef CTaskID data
|
||||
|
||||
@@ -397,6 +328,9 @@ cdef class ActorClassID(UniqueID):
|
||||
cdef CActorClassID native(self):
|
||||
return <CActorClassID>self.data
|
||||
|
||||
# This type alias is for backward compatibility.
|
||||
ObjectID = ObjectRef
|
||||
|
||||
_ID_TYPES = [
|
||||
ActorCheckpointID,
|
||||
ActorClassID,
|
||||
|
||||
@@ -29,7 +29,7 @@ def memory_summary():
|
||||
return reply.memory_summary
|
||||
|
||||
|
||||
def free(object_ids, local_only=False, delete_creating_tasks=False):
|
||||
def free(object_refs, local_only=False, delete_creating_tasks=False):
|
||||
"""Free a list of IDs from object stores.
|
||||
|
||||
This function is a low-level API which should be used in restricted
|
||||
@@ -48,7 +48,7 @@ def free(object_ids, local_only=False, delete_creating_tasks=False):
|
||||
>>> free([x_id]) # unpin & delete x globally
|
||||
|
||||
Args:
|
||||
object_ids (List[ObjectID]): List of object IDs to delete.
|
||||
object_refs (List[ObjectRef]): List of object refs to delete.
|
||||
local_only (bool): Whether only deleting the list of objects in local
|
||||
object store or all object stores.
|
||||
delete_creating_tasks (bool): Whether also delete the object creating
|
||||
@@ -56,23 +56,24 @@ def free(object_ids, local_only=False, delete_creating_tasks=False):
|
||||
"""
|
||||
worker = ray.worker.global_worker
|
||||
|
||||
if isinstance(object_ids, ray.ObjectID):
|
||||
object_ids = [object_ids]
|
||||
if isinstance(object_refs, ray.ObjectRef):
|
||||
object_refs = [object_refs]
|
||||
|
||||
if not isinstance(object_ids, list):
|
||||
raise TypeError("free() expects a list of ObjectID, got {}".format(
|
||||
type(object_ids)))
|
||||
if not isinstance(object_refs, list):
|
||||
raise TypeError("free() expects a list of ObjectRef, got {}".format(
|
||||
type(object_refs)))
|
||||
|
||||
# Make sure that the values are object IDs.
|
||||
for object_id in object_ids:
|
||||
if not isinstance(object_id, ray.ObjectID):
|
||||
raise TypeError("Attempting to call `free` on the value {}, "
|
||||
"which is not an ray.ObjectID.".format(object_id))
|
||||
# Make sure that the values are object refs.
|
||||
for object_ref in object_refs:
|
||||
if not isinstance(object_ref, ray.ObjectRef):
|
||||
raise TypeError(
|
||||
"Attempting to call `free` on the value {}, "
|
||||
"which is not an ray.ObjectRef.".format(object_ref))
|
||||
|
||||
worker.check_connected()
|
||||
with profiling.profile("ray.free"):
|
||||
if len(object_ids) == 0:
|
||||
if len(object_refs) == 0:
|
||||
return
|
||||
|
||||
worker.core_worker.free_objects(object_ids, local_only,
|
||||
worker.core_worker.free_objects(object_refs, local_only,
|
||||
delete_creating_tasks)
|
||||
|
||||
+3
-3
@@ -283,9 +283,9 @@ class Node:
|
||||
return self._ray_params.load_code_from_local
|
||||
|
||||
@property
|
||||
def object_id_seed(self):
|
||||
"""Get the seed for deterministic generation of object IDs"""
|
||||
return self._ray_params.object_id_seed
|
||||
def object_ref_seed(self):
|
||||
"""Get the seed for deterministic generation of object refs"""
|
||||
return self._ray_params.object_ref_seed
|
||||
|
||||
@property
|
||||
def plasma_store_socket_name(self):
|
||||
|
||||
@@ -40,9 +40,9 @@ class RayParams:
|
||||
on. If not set or set to 0, random ports will be chosen.
|
||||
max_worker_port (int): The highest port number that workers will bind
|
||||
on. If set, min_worker_port must also be set.
|
||||
object_id_seed (int): Used to seed the deterministic generation of
|
||||
object IDs. The same value can be used across multiple runs of the
|
||||
same job in order to generate the object IDs in a consistent
|
||||
object_ref_seed (int): Used to seed the deterministic generation of
|
||||
object refs. The same value can be used across multiple runs of the
|
||||
same job in order to generate the object refs in a consistent
|
||||
manner. However, the same ID should not be used for different jobs.
|
||||
redirect_worker_output: True if the stdout and stderr of worker
|
||||
processes should be redirected to files.
|
||||
@@ -107,7 +107,7 @@ class RayParams:
|
||||
raylet_ip_address=None,
|
||||
min_worker_port=None,
|
||||
max_worker_port=None,
|
||||
object_id_seed=None,
|
||||
object_ref_seed=None,
|
||||
driver_mode=None,
|
||||
redirect_worker_output=None,
|
||||
redirect_output=None,
|
||||
@@ -131,7 +131,7 @@ class RayParams:
|
||||
java_worker_options=None,
|
||||
load_code_from_local=False,
|
||||
_internal_config=None):
|
||||
self.object_id_seed = object_id_seed
|
||||
self.object_ref_seed = object_ref_seed
|
||||
self.redis_address = redis_address
|
||||
self.num_cpus = num_cpus
|
||||
self.num_gpus = num_gpus
|
||||
|
||||
@@ -18,23 +18,23 @@ def main():
|
||||
cluster.add_node(
|
||||
object_store_memory=20 * 1024 * 1024 * 1024, num_gpus=1, num_cpus=16)
|
||||
|
||||
object_id_list = []
|
||||
object_ref_list = []
|
||||
for i in range(0, 10):
|
||||
object_id = ray.put(np.random.rand(1024 * 128, 1024))
|
||||
object_id_list.append(object_id)
|
||||
object_ref = ray.put(np.random.rand(1024 * 128, 1024))
|
||||
object_ref_list.append(object_ref)
|
||||
|
||||
@ray.remote(num_gpus=1)
|
||||
def f(object_id_list):
|
||||
def f(object_ref_list):
|
||||
diffs = []
|
||||
for object_id in object_id_list:
|
||||
for object_ref in object_ref_list:
|
||||
before = time.time()
|
||||
ray.get(object_id)
|
||||
ray.get(object_ref)
|
||||
after = time.time()
|
||||
diffs.append(after - before)
|
||||
time.sleep(1)
|
||||
return np.mean(diffs), np.std(diffs)
|
||||
|
||||
time_diff, time_diff_std = ray.get(f.remote(object_id_list))
|
||||
time_diff, time_diff_std = ray.get(f.remote(object_ref_list))
|
||||
|
||||
print("latency to get an 1G object over network", round(time_diff, 2),
|
||||
"+-", round(time_diff_std, 2))
|
||||
|
||||
@@ -47,7 +47,7 @@ class RemoteFunction:
|
||||
invoking the function. The decorator must return a function that
|
||||
takes in two arguments ("args" and "kwargs"). In most cases, it
|
||||
should call the function that was passed into the decorator and
|
||||
return the resulting ObjectIDs. For an example, see
|
||||
return the resulting ObjectRefs. For an example, see
|
||||
"test_decorated_function" in "python/ray/tests/test_basic.py".
|
||||
_function_signature: The function signature.
|
||||
_last_export_session_and_job: A pair of the last exported session
|
||||
@@ -203,14 +203,14 @@ class RemoteFunction:
|
||||
assert not self._is_cross_language, \
|
||||
"Cross language remote function " \
|
||||
"cannot be executed locally."
|
||||
object_ids = worker.core_worker.submit_task(
|
||||
object_refs = worker.core_worker.submit_task(
|
||||
self._language, self._function_descriptor, list_args,
|
||||
num_return_vals, resources, max_retries)
|
||||
|
||||
if len(object_ids) == 1:
|
||||
return object_ids[0]
|
||||
elif len(object_ids) > 1:
|
||||
return object_ids
|
||||
if len(object_refs) == 1:
|
||||
return object_refs[0]
|
||||
elif len(object_refs) > 1:
|
||||
return object_refs
|
||||
|
||||
if self._decorator is not None:
|
||||
invocation = self._decorator(invocation)
|
||||
|
||||
+51
-50
@@ -88,7 +88,7 @@ def _try_to_compute_deterministic_class_id(cls, depth=5):
|
||||
class SerializationContext:
|
||||
"""Initialize the serialization library.
|
||||
|
||||
This defines a custom serializer for object IDs and also tells ray to
|
||||
This defines a custom serializer for object refs and also tells ray to
|
||||
serialize several exception classes that we define for error handling.
|
||||
"""
|
||||
|
||||
@@ -99,14 +99,14 @@ class SerializationContext:
|
||||
def actor_handle_serializer(obj):
|
||||
serialized, actor_handle_id = obj._serialization_helper()
|
||||
# Update ref counting for the actor handle
|
||||
self.add_contained_object_id(actor_handle_id)
|
||||
self.add_contained_object_ref(actor_handle_id)
|
||||
return serialized
|
||||
|
||||
def actor_handle_deserializer(serialized_obj):
|
||||
# If this actor handle was stored in another object, then tell the
|
||||
# core worker.
|
||||
context = ray.worker.global_worker.get_serialization_context()
|
||||
outer_id = context.get_outer_object_id()
|
||||
outer_id = context.get_outer_object_ref()
|
||||
return ray.actor.ActorHandle._deserialization_helper(
|
||||
serialized_obj, outer_id)
|
||||
|
||||
@@ -121,22 +121,22 @@ class SerializationContext:
|
||||
def id_deserializer(serialized_obj):
|
||||
return serialized_obj[0](*serialized_obj[1])
|
||||
|
||||
def object_id_serializer(obj):
|
||||
self.add_contained_object_id(obj)
|
||||
def object_ref_serializer(obj):
|
||||
self.add_contained_object_ref(obj)
|
||||
worker = ray.worker.global_worker
|
||||
worker.check_connected()
|
||||
obj, owner_address = (
|
||||
worker.core_worker.serialize_and_promote_object_id(obj))
|
||||
worker.core_worker.serialize_and_promote_object_ref(obj))
|
||||
obj = id_serializer(obj)
|
||||
return obj, owner_address
|
||||
|
||||
def object_id_deserializer(serialized_obj):
|
||||
obj_id, owner_address = serialized_obj
|
||||
def object_ref_deserializer(serialized_obj):
|
||||
obj_ref, owner_address = serialized_obj
|
||||
# NOTE(swang): Must deserialize the object first before asking
|
||||
# the core worker to resolve the value. This is to make sure
|
||||
# that the ref count for the ObjectID is greater than 0 by the
|
||||
# that the ref count for the ObjectRef is greater than 0 by the
|
||||
# time the core worker resolves the value of the object.
|
||||
deserialized_object_id = id_deserializer(obj_id)
|
||||
deserialized_object_ref = id_deserializer(obj_ref)
|
||||
# TODO(edoakes): we should be able to just capture a reference
|
||||
# to 'self' here instead, but this function is itself pickled
|
||||
# somewhere, which causes an error.
|
||||
@@ -146,19 +146,19 @@ class SerializationContext:
|
||||
worker.check_connected()
|
||||
# UniqueIDs are serialized as
|
||||
# (class name, (unique bytes,)).
|
||||
outer_id = context.get_outer_object_id()
|
||||
# outer_id is None in the case that this ObjectID was closed
|
||||
outer_id = context.get_outer_object_ref()
|
||||
# outer_id is None in the case that this ObjectRef was closed
|
||||
# over in a function or pickled directly using pickle.dumps().
|
||||
if outer_id is None:
|
||||
outer_id = ray.ObjectID.nil()
|
||||
worker.core_worker.deserialize_and_register_object_id(
|
||||
obj_id[1][0], outer_id, owner_address)
|
||||
return deserialized_object_id
|
||||
outer_id = ray.ObjectRef.nil()
|
||||
worker.core_worker.deserialize_and_register_object_ref(
|
||||
obj_ref[1][0], outer_id, owner_address)
|
||||
return deserialized_object_ref
|
||||
|
||||
for id_type in ray._raylet._ID_TYPES:
|
||||
if id_type == ray._raylet.ObjectID:
|
||||
if id_type == ray._raylet.ObjectRef:
|
||||
self._register_cloudpickle_serializer(
|
||||
id_type, object_id_serializer, object_id_deserializer)
|
||||
id_type, object_ref_serializer, object_ref_deserializer)
|
||||
else:
|
||||
self._register_cloudpickle_serializer(id_type, id_serializer,
|
||||
id_deserializer)
|
||||
@@ -180,36 +180,36 @@ class SerializationContext:
|
||||
def set_out_of_band_serialization(self):
|
||||
self._thread_local.in_band = False
|
||||
|
||||
def set_outer_object_id(self, outer_object_id):
|
||||
self._thread_local.outer_object_id = outer_object_id
|
||||
def set_outer_object_ref(self, outer_object_ref):
|
||||
self._thread_local.outer_object_ref = outer_object_ref
|
||||
|
||||
def get_outer_object_id(self):
|
||||
return getattr(self._thread_local, "outer_object_id", None)
|
||||
def get_outer_object_ref(self):
|
||||
return getattr(self._thread_local, "outer_object_ref", None)
|
||||
|
||||
def get_and_clear_contained_object_ids(self):
|
||||
if not hasattr(self._thread_local, "object_ids"):
|
||||
self._thread_local.object_ids = set()
|
||||
def get_and_clear_contained_object_refs(self):
|
||||
if not hasattr(self._thread_local, "object_refs"):
|
||||
self._thread_local.object_refs = set()
|
||||
return set()
|
||||
|
||||
object_ids = self._thread_local.object_ids
|
||||
self._thread_local.object_ids = set()
|
||||
return object_ids
|
||||
object_refs = self._thread_local.object_refs
|
||||
self._thread_local.object_refs = set()
|
||||
return object_refs
|
||||
|
||||
def add_contained_object_id(self, object_id):
|
||||
def add_contained_object_ref(self, object_ref):
|
||||
if self.is_in_band_serialization():
|
||||
# This object ID is being stored in an object. Add the ID to the
|
||||
# This object ref is being stored in an object. Add the ID to the
|
||||
# list of IDs contained in the object so that we keep the inner
|
||||
# object value alive as long as the outer object is in scope.
|
||||
if not hasattr(self._thread_local, "object_ids"):
|
||||
self._thread_local.object_ids = set()
|
||||
self._thread_local.object_ids.add(object_id)
|
||||
if not hasattr(self._thread_local, "object_refs"):
|
||||
self._thread_local.object_refs = set()
|
||||
self._thread_local.object_refs.add(object_ref)
|
||||
else:
|
||||
# If this serialization is out-of-band (e.g., from a call to
|
||||
# cloudpickle directly or captured in a remote function/actor),
|
||||
# then pin the object for the lifetime of this worker by adding
|
||||
# a local reference that won't ever be removed.
|
||||
ray.worker.global_worker.core_worker.add_object_id_reference(
|
||||
object_id)
|
||||
ray.worker.global_worker.core_worker.add_object_ref_reference(
|
||||
object_ref)
|
||||
|
||||
def _deserialize_pickle5_data(self, data):
|
||||
try:
|
||||
@@ -242,7 +242,7 @@ class SerializationContext:
|
||||
raise DeserializationError()
|
||||
return obj
|
||||
|
||||
def _deserialize_object(self, data, metadata, object_id):
|
||||
def _deserialize_object(self, data, metadata, object_ref):
|
||||
if metadata:
|
||||
if metadata in [
|
||||
ray_constants.OBJECT_METADATA_TYPE_CROSS_LANGUAGE,
|
||||
@@ -261,7 +261,7 @@ class SerializationContext:
|
||||
except Exception:
|
||||
raise Exception(
|
||||
"Can't deserialize object: {}, metadata: {}".format(
|
||||
object_id, metadata))
|
||||
object_ref, metadata))
|
||||
|
||||
# RayTaskError is serialized with pickle5 in the data field.
|
||||
# TODO (kfstorm): exception serialization should be language
|
||||
@@ -277,7 +277,8 @@ class SerializationContext:
|
||||
elif error_type == ErrorType.Value("TASK_CANCELLED"):
|
||||
return RayCancellationError()
|
||||
elif error_type == ErrorType.Value("OBJECT_UNRECONSTRUCTABLE"):
|
||||
return UnreconstructableError(ray.ObjectID(object_id.binary()))
|
||||
return UnreconstructableError(
|
||||
ray.ObjectRef(object_ref.binary()))
|
||||
else:
|
||||
assert error_type != ErrorType.Value("OBJECT_IN_PLASMA"), \
|
||||
"Tried to get object that has been promoted to plasma."
|
||||
@@ -293,22 +294,22 @@ class SerializationContext:
|
||||
|
||||
def deserialize_objects(self,
|
||||
data_metadata_pairs,
|
||||
object_ids,
|
||||
object_refs,
|
||||
error_timeout=10):
|
||||
assert len(data_metadata_pairs) == len(object_ids)
|
||||
assert len(data_metadata_pairs) == len(object_refs)
|
||||
|
||||
start_time = time.time()
|
||||
results = []
|
||||
warning_sent = False
|
||||
i = 0
|
||||
while i < len(object_ids):
|
||||
object_id = object_ids[i]
|
||||
while i < len(object_refs):
|
||||
object_ref = object_refs[i]
|
||||
data, metadata = data_metadata_pairs[i]
|
||||
assert self.get_outer_object_id() is None
|
||||
self.set_outer_object_id(object_id)
|
||||
assert self.get_outer_object_ref() is None
|
||||
self.set_outer_object_ref(object_ref)
|
||||
try:
|
||||
results.append(
|
||||
self._deserialize_object(data, metadata, object_id))
|
||||
self._deserialize_object(data, metadata, object_ref))
|
||||
i += 1
|
||||
except DeserializationError:
|
||||
# Wait a little bit for the import thread to import the class.
|
||||
@@ -330,27 +331,27 @@ class SerializationContext:
|
||||
job_id=self.worker.current_job_id)
|
||||
warning_sent = True
|
||||
finally:
|
||||
# Must clear ObjectID to not hold a reference.
|
||||
self.set_outer_object_id(None)
|
||||
# Must clear ObjectRef to not hold a reference.
|
||||
self.set_outer_object_ref(None)
|
||||
|
||||
return results
|
||||
|
||||
def _serialize_to_pickle5(self, metadata, value):
|
||||
writer = Pickle5Writer()
|
||||
# TODO(swang): Check that contained_object_ids is empty.
|
||||
# TODO(swang): Check that contained_object_refs is empty.
|
||||
try:
|
||||
self.set_in_band_serialization()
|
||||
inband = pickle.dumps(
|
||||
value, protocol=5, buffer_callback=writer.buffer_callback)
|
||||
except Exception as e:
|
||||
self.get_and_clear_contained_object_ids()
|
||||
self.get_and_clear_contained_object_refs()
|
||||
raise e
|
||||
finally:
|
||||
self.set_out_of_band_serialization()
|
||||
|
||||
return Pickle5SerializedObject(
|
||||
metadata, inband, writer,
|
||||
self.get_and_clear_contained_object_ids())
|
||||
self.get_and_clear_contained_object_refs())
|
||||
|
||||
def _serialize_to_msgpack(self, metadata, value):
|
||||
python_objects = []
|
||||
|
||||
@@ -20,7 +20,7 @@ class RayServeHandle:
|
||||
Traffic=...
|
||||
)
|
||||
>>> handle.remote(my_request_content)
|
||||
ObjectID(...)
|
||||
ObjectRef(...)
|
||||
>>> ray.get(handle.remote(...))
|
||||
# result
|
||||
>>> ray.get(handle.remote(let_it_crash_request))
|
||||
|
||||
@@ -198,7 +198,7 @@ class Router:
|
||||
self.endpoint_queues[endpoint].appendleft(query)
|
||||
self.flush_endpoint_queue(endpoint)
|
||||
|
||||
# Note: a future change can be to directly return the ObjectID from
|
||||
# Note: a future change can be to directly return the ObjectRef from
|
||||
# replica task submission
|
||||
try:
|
||||
result = await query.async_future
|
||||
|
||||
+21
-20
@@ -131,7 +131,7 @@ class GlobalState:
|
||||
"""Execute a Redis command on the appropriate Redis shard based on key.
|
||||
|
||||
Args:
|
||||
key: The object ID or the task ID that the query is about.
|
||||
key: The object ref or the task ID that the query is about.
|
||||
args: The command to run.
|
||||
|
||||
Returns:
|
||||
@@ -155,11 +155,11 @@ class GlobalState:
|
||||
result.extend(list(client.scan_iter(match=pattern)))
|
||||
return result
|
||||
|
||||
def object_table(self, object_id=None):
|
||||
"""Fetch and parse the object table info for one or more object IDs.
|
||||
def object_table(self, object_ref=None):
|
||||
"""Fetch and parse the object table info for one or more object refs.
|
||||
|
||||
Args:
|
||||
object_id: An object ID to fetch information about. If this is
|
||||
object_ref: An object ref to fetch information about. If this is
|
||||
None, then the entire object table is fetched.
|
||||
|
||||
Returns:
|
||||
@@ -167,9 +167,10 @@ class GlobalState:
|
||||
"""
|
||||
self._check_connected()
|
||||
|
||||
if object_id is not None:
|
||||
object_id = ray.ObjectID(hex_to_binary(object_id))
|
||||
object_info = self.global_state_accessor.get_object_info(object_id)
|
||||
if object_ref is not None:
|
||||
object_ref = ray.ObjectRef(hex_to_binary(object_ref))
|
||||
object_info = self.global_state_accessor.get_object_info(
|
||||
object_ref)
|
||||
if object_info is None:
|
||||
return {}
|
||||
else:
|
||||
@@ -182,7 +183,7 @@ class GlobalState:
|
||||
for i in range(len(object_table)):
|
||||
object_location_info = gcs_utils.ObjectLocationInfo.FromString(
|
||||
object_table[i])
|
||||
results[binary_to_hex(object_location_info.object_id)] = \
|
||||
results[binary_to_hex(object_location_info.object_ref)] = \
|
||||
self._gen_object_info(object_location_info)
|
||||
return results
|
||||
|
||||
@@ -196,8 +197,8 @@ class GlobalState:
|
||||
locations.append(ray.utils.binary_to_hex(location.manager))
|
||||
|
||||
object_info = {
|
||||
"ObjectID": ray.utils.binary_to_hex(
|
||||
object_location_info.object_id),
|
||||
"ObjectRef": ray.utils.binary_to_hex(
|
||||
object_location_info.object_ref),
|
||||
"Locations": locations,
|
||||
}
|
||||
return object_info
|
||||
@@ -538,21 +539,21 @@ class GlobalState:
|
||||
|
||||
for event in items:
|
||||
if event["event_type"] == "transfer_send":
|
||||
object_id, remote_node_id, _, _ = event["extra_data"]
|
||||
object_ref, remote_node_id, _, _ = event["extra_data"]
|
||||
|
||||
elif event["event_type"] == "transfer_receive":
|
||||
object_id, remote_node_id, _, _ = event["extra_data"]
|
||||
object_ref, remote_node_id, _, _ = event["extra_data"]
|
||||
|
||||
elif event["event_type"] == "receive_pull_request":
|
||||
object_id, remote_node_id = event["extra_data"]
|
||||
object_ref, remote_node_id = event["extra_data"]
|
||||
|
||||
else:
|
||||
assert False, "This should be unreachable."
|
||||
|
||||
# Choose a color by reading the first couple of hex digits of
|
||||
# the object ID as an integer and turning that into a color.
|
||||
object_id_int = int(object_id[:2], 16)
|
||||
color = self._chrome_tracing_colors[object_id_int % len(
|
||||
# the object ref as an integer and turning that into a color.
|
||||
object_ref_int = int(object_ref[:2], 16)
|
||||
color = self._chrome_tracing_colors[object_ref_int % len(
|
||||
self._chrome_tracing_colors)]
|
||||
|
||||
new_event = {
|
||||
@@ -921,17 +922,17 @@ def actors(actor_id=None):
|
||||
return state.actor_table(actor_id=actor_id)
|
||||
|
||||
|
||||
def objects(object_id=None):
|
||||
"""Fetch and parse the object table info for one or more object IDs.
|
||||
def objects(object_ref=None):
|
||||
"""Fetch and parse the object table info for one or more object refs.
|
||||
|
||||
Args:
|
||||
object_id: An object ID to fetch information about. If this is None,
|
||||
object_ref: An object ref to fetch information about. If this is None,
|
||||
then the entire object table is fetched.
|
||||
|
||||
Returns:
|
||||
Information from the object table.
|
||||
"""
|
||||
return state.object_table(object_id=object_id)
|
||||
return state.object_table(object_ref=object_ref)
|
||||
|
||||
|
||||
def timeline(filename=None):
|
||||
|
||||
@@ -72,8 +72,8 @@ def test_task_forward(benchmark, num_tasks):
|
||||
benchmark(benchmark_task_forward, f, num_tasks)
|
||||
|
||||
|
||||
def benchmark_transfer_object(actor, object_ids):
|
||||
ray.get(actor.f.remote(object_ids))
|
||||
def benchmark_transfer_object(actor, object_refs):
|
||||
ray.get(actor.f.remote(object_refs))
|
||||
|
||||
|
||||
@pytest.mark.benchmark
|
||||
@@ -87,14 +87,14 @@ def test_transfer_performance(benchmark, ray_start_cluster_head, object_number,
|
||||
|
||||
@ray.remote(resources={"my_resource": 1})
|
||||
class ObjectActor:
|
||||
def f(self, object_ids):
|
||||
ray.get(object_ids)
|
||||
def f(self, object_refs):
|
||||
ray.get(object_refs)
|
||||
|
||||
# setup remote actor
|
||||
actor = ObjectActor.remote()
|
||||
actor.f.remote([])
|
||||
|
||||
data = bytes(1) * data_size
|
||||
object_ids = [ray.put(data) for _ in range(object_number)]
|
||||
object_refs = [ray.put(data) for _ in range(object_number)]
|
||||
|
||||
benchmark(benchmark_transfer_object, actor, object_ids)
|
||||
benchmark(benchmark_transfer_object, actor, object_refs)
|
||||
|
||||
@@ -614,11 +614,11 @@ def test_remote_function_within_actor(ray_start_10_cpus):
|
||||
def __init__(self, x):
|
||||
self.x = x
|
||||
self.y = val2
|
||||
self.object_ids = [f.remote(i) for i in range(5)]
|
||||
self.object_refs = [f.remote(i) for i in range(5)]
|
||||
self.values2 = ray.get([f.remote(i) for i in range(5)])
|
||||
|
||||
def get_values(self):
|
||||
return self.x, self.y, self.object_ids, self.values2
|
||||
return self.x, self.y, self.object_refs, self.values2
|
||||
|
||||
def f(self):
|
||||
return [f.remote(i) for i in range(5)]
|
||||
@@ -626,8 +626,8 @@ def test_remote_function_within_actor(ray_start_10_cpus):
|
||||
def g(self):
|
||||
return ray.get([g.remote(i) for i in range(5)])
|
||||
|
||||
def h(self, object_ids):
|
||||
return ray.get(object_ids)
|
||||
def h(self, object_refs):
|
||||
return ray.get(object_refs)
|
||||
|
||||
actor = Actor.remote(1)
|
||||
values = ray.get(actor.get_values.remote())
|
||||
|
||||
@@ -473,7 +473,7 @@ def test_multiple_actor_restart(ray_start_cluster_head):
|
||||
# Wait for the actors to start up.
|
||||
time.sleep(1)
|
||||
|
||||
# This is a mapping from actor handles to object IDs returned by
|
||||
# This is a mapping from actor handles to object refs returned by
|
||||
# methods on that actor.
|
||||
result_ids = collections.defaultdict(lambda: [])
|
||||
|
||||
@@ -813,10 +813,10 @@ def test_decorated_method(ray_start_regular):
|
||||
|
||||
a = Actor.remote()
|
||||
|
||||
object_id, extra = a.decorated_method.remote(3, kwarg=3)
|
||||
assert isinstance(object_id, ray.ObjectID)
|
||||
object_ref, extra = a.decorated_method.remote(3, kwarg=3)
|
||||
assert isinstance(object_ref, ray.ObjectRef)
|
||||
assert extra == {"kwarg": 3}
|
||||
assert ray.get(object_id) == 7 # 2 * 3 + 1
|
||||
assert ray.get(object_ref) == 7 # 2 * 3 + 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -631,12 +631,12 @@ def test_creating_more_actors_than_resources(shutdown_only):
|
||||
results = []
|
||||
for _ in range(3):
|
||||
actor = ResourceActor2.remote()
|
||||
object_id = actor.method.remote()
|
||||
results.append(object_id)
|
||||
object_ref = actor.method.remote()
|
||||
results.append(object_ref)
|
||||
# Wait for the task to execute. We do this because otherwise it may
|
||||
# be possible for the __ray_terminate__ task to execute before the
|
||||
# method.
|
||||
ray.wait([object_id])
|
||||
ray.wait([object_ref])
|
||||
|
||||
ray.get(results)
|
||||
|
||||
|
||||
@@ -34,10 +34,10 @@ def test_internal_free(shutdown_only):
|
||||
sampler = Sampler.remote()
|
||||
|
||||
# Free does not delete from in-memory store.
|
||||
obj_id = sampler.sample.remote()
|
||||
ray.get(obj_id)
|
||||
ray.internal.free(obj_id)
|
||||
assert ray.get(obj_id) == [1, 2, 3, 4, 5]
|
||||
obj_ref = sampler.sample.remote()
|
||||
ray.get(obj_ref)
|
||||
ray.internal.free(obj_ref)
|
||||
assert ray.get(obj_ref) == [1, 2, 3, 4, 5]
|
||||
|
||||
# Free deletes big objects from plasma store.
|
||||
big_id = sampler.sample_big.remote()
|
||||
@@ -54,17 +54,17 @@ def test_wait_iterables(ray_start_regular):
|
||||
time.sleep(delay)
|
||||
return 1
|
||||
|
||||
objectids = (f.remote(1.0), f.remote(0.5), f.remote(0.5), f.remote(0.5))
|
||||
ready_ids, remaining_ids = ray.experimental.wait(objectids)
|
||||
object_refs = (f.remote(1.0), f.remote(0.5), f.remote(0.5), f.remote(0.5))
|
||||
ready_ids, remaining_ids = ray.experimental.wait(object_refs)
|
||||
assert len(ready_ids) == 1
|
||||
assert len(remaining_ids) == 3
|
||||
|
||||
objectids = np.array(
|
||||
object_refs = np.array(
|
||||
[f.remote(1.0),
|
||||
f.remote(0.5),
|
||||
f.remote(0.5),
|
||||
f.remote(0.5)])
|
||||
ready_ids, remaining_ids = ray.experimental.wait(objectids)
|
||||
ready_ids, remaining_ids = ray.experimental.wait(object_refs)
|
||||
assert len(ready_ids) == 1
|
||||
assert len(remaining_ids) == 3
|
||||
|
||||
@@ -81,20 +81,20 @@ def test_multiple_waits_and_gets(shutdown_only):
|
||||
|
||||
@ray.remote
|
||||
def g(l):
|
||||
# The argument l should be a list containing one object ID.
|
||||
# The argument l should be a list containing one object ref.
|
||||
ray.wait([l[0]])
|
||||
|
||||
@ray.remote
|
||||
def h(l):
|
||||
# The argument l should be a list containing one object ID.
|
||||
# The argument l should be a list containing one object ref.
|
||||
ray.get(l[0])
|
||||
|
||||
# Make sure that multiple wait requests involving the same object ID
|
||||
# Make sure that multiple wait requests involving the same object ref
|
||||
# all return.
|
||||
x = f.remote(1)
|
||||
ray.get([g.remote([x]), g.remote([x])])
|
||||
|
||||
# Make sure that multiple get requests involving the same object ID all
|
||||
# Make sure that multiple get requests involving the same object ref all
|
||||
# return.
|
||||
x = f.remote(1)
|
||||
ray.get([h.remote([x]), h.remote([x])])
|
||||
@@ -179,9 +179,9 @@ def test_profiling_api(ray_start_2_cpus):
|
||||
pass
|
||||
|
||||
ray.put(1)
|
||||
object_id = f.remote()
|
||||
ray.wait([object_id])
|
||||
ray.get(object_id)
|
||||
object_ref = f.remote()
|
||||
ray.wait([object_ref])
|
||||
ray.get(object_ref)
|
||||
|
||||
# Wait until all of the profiling information appears in the profile
|
||||
# table.
|
||||
@@ -259,14 +259,14 @@ def test_object_transfer_dump(ray_start_cluster):
|
||||
return
|
||||
|
||||
# These objects will live on different nodes.
|
||||
object_ids = [
|
||||
object_refs = [
|
||||
f._remote(args=[1], resources={str(i): 1}) for i in range(num_nodes)
|
||||
]
|
||||
|
||||
# Broadcast each object from each machine to each other machine.
|
||||
for object_id in object_ids:
|
||||
for object_ref in object_refs:
|
||||
ray.get([
|
||||
f._remote(args=[object_id], resources={str(i): 1})
|
||||
f._remote(args=[object_ref], resources={str(i): 1})
|
||||
for i in range(num_nodes)
|
||||
])
|
||||
|
||||
@@ -355,7 +355,7 @@ def test_identical_function_names(ray_start_regular):
|
||||
|
||||
def test_illegal_api_calls(ray_start_regular):
|
||||
|
||||
# Verify that we cannot call put on an ObjectID.
|
||||
# Verify that we cannot call put on an ObjectRef.
|
||||
x = ray.put(1)
|
||||
with pytest.raises(Exception):
|
||||
ray.put(x)
|
||||
|
||||
@@ -690,15 +690,15 @@ def test_blocking_tasks(ray_start_regular):
|
||||
def g(i):
|
||||
# Each instance of g submits and blocks on the result of another
|
||||
# remote task.
|
||||
object_ids = [f.remote(i, j) for j in range(2)]
|
||||
return ray.get(object_ids)
|
||||
object_refs = [f.remote(i, j) for j in range(2)]
|
||||
return ray.get(object_refs)
|
||||
|
||||
@ray.remote
|
||||
def h(i):
|
||||
# Each instance of g submits and blocks on the result of another
|
||||
# remote task using ray.wait.
|
||||
object_ids = [f.remote(i, j) for j in range(2)]
|
||||
return ray.wait(object_ids, num_returns=len(object_ids))
|
||||
object_refs = [f.remote(i, j) for j in range(2)]
|
||||
return ray.wait(object_refs, num_returns=len(object_refs))
|
||||
|
||||
ray.get([h.remote(i) for i in range(4)])
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ def test_global_state_api(shutdown_only):
|
||||
|
||||
# A driver/worker creates a temporary object during startup. Although the
|
||||
# temporary object is freed immediately, in a rare case, we can still find
|
||||
# the object ID in GCS because Raylet removes the object ID from GCS
|
||||
# the object ref in GCS because Raylet removes the object ref from GCS
|
||||
# asynchronously.
|
||||
# Because we can't control when workers create the temporary objects, so
|
||||
# We can't assert that `ray.objects()` returns an empty dict. Here we just
|
||||
@@ -281,22 +281,22 @@ def test_specific_job_id():
|
||||
ray.shutdown()
|
||||
|
||||
|
||||
def test_object_id_properties():
|
||||
def test_object_ref_properties():
|
||||
id_bytes = b"00112233445566778899"
|
||||
object_id = ray.ObjectID(id_bytes)
|
||||
assert object_id.binary() == id_bytes
|
||||
object_id = ray.ObjectID.nil()
|
||||
assert object_id.is_nil()
|
||||
object_ref = ray.ObjectRef(id_bytes)
|
||||
assert object_ref.binary() == id_bytes
|
||||
object_ref = ray.ObjectRef.nil()
|
||||
assert object_ref.is_nil()
|
||||
with pytest.raises(ValueError, match=r".*needs to have length 20.*"):
|
||||
ray.ObjectID(id_bytes + b"1234")
|
||||
ray.ObjectRef(id_bytes + b"1234")
|
||||
with pytest.raises(ValueError, match=r".*needs to have length 20.*"):
|
||||
ray.ObjectID(b"0123456789")
|
||||
object_id = ray.ObjectID.from_random()
|
||||
assert not object_id.is_nil()
|
||||
assert object_id.binary() != id_bytes
|
||||
id_dumps = pickle.dumps(object_id)
|
||||
ray.ObjectRef(b"0123456789")
|
||||
object_ref = ray.ObjectRef.from_random()
|
||||
assert not object_ref.is_nil()
|
||||
assert object_ref.binary() != id_bytes
|
||||
id_dumps = pickle.dumps(object_ref)
|
||||
id_from_dumps = pickle.loads(id_dumps)
|
||||
assert id_from_dumps == object_id
|
||||
assert id_from_dumps == object_ref
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -434,7 +434,7 @@ def test_pandas_parquet_serialization():
|
||||
|
||||
|
||||
def test_socket_dir_not_existing(shutdown_only):
|
||||
random_name = ray.ObjectID.from_random().hex()
|
||||
random_name = ray.ObjectRef.from_random().hex()
|
||||
temp_raylet_socket_dir = os.path.join(ray.utils.get_ray_temp_dir(),
|
||||
"tests", random_name)
|
||||
temp_raylet_socket_name = os.path.join(temp_raylet_socket_dir,
|
||||
@@ -487,20 +487,20 @@ def test_put_pins_object(ray_start_object_store_memory):
|
||||
obj = np.ones(200 * 1024, dtype=np.uint8)
|
||||
x_id = ray.put(obj)
|
||||
x_binary = x_id.binary()
|
||||
assert (ray.get(ray.ObjectID(x_binary)) == obj).all()
|
||||
assert (ray.get(ray.ObjectRef(x_binary)) == obj).all()
|
||||
|
||||
# x cannot be evicted since x_id pins it
|
||||
for _ in range(10):
|
||||
ray.put(np.zeros(10 * 1024 * 1024))
|
||||
assert (ray.get(x_id) == obj).all()
|
||||
assert (ray.get(ray.ObjectID(x_binary)) == obj).all()
|
||||
assert (ray.get(ray.ObjectRef(x_binary)) == obj).all()
|
||||
|
||||
# now it can be evicted since x_id pins it but x_binary does not
|
||||
del x_id
|
||||
for _ in range(10):
|
||||
ray.put(np.zeros(10 * 1024 * 1024))
|
||||
assert not ray.worker.global_worker.core_worker.object_exists(
|
||||
ray.ObjectID(x_binary))
|
||||
ray.ObjectRef(x_binary))
|
||||
|
||||
# weakref put
|
||||
y_id = ray.put(obj, weakref=True)
|
||||
@@ -530,7 +530,7 @@ def test_decorated_function(ray_start_regular):
|
||||
|
||||
|
||||
def test_get_postprocess(ray_start_regular):
|
||||
def get_postprocessor(object_ids, values):
|
||||
def get_postprocessor(object_refs, values):
|
||||
return [value for value in values if value > 0]
|
||||
|
||||
ray.worker.global_worker._post_get_hooks.append(get_postprocessor)
|
||||
@@ -657,10 +657,10 @@ def test_lease_request_leak(shutdown_only):
|
||||
# from the raylet.
|
||||
tasks = []
|
||||
for _ in range(10):
|
||||
oid = ray.put(1)
|
||||
obj_ref = ray.put(1)
|
||||
for _ in range(2):
|
||||
tasks.append(f.remote(oid))
|
||||
del oid
|
||||
tasks.append(f.remote(obj_ref))
|
||||
del obj_ref
|
||||
ray.get(tasks)
|
||||
|
||||
time.sleep(
|
||||
|
||||
@@ -19,13 +19,13 @@ def reload_modules():
|
||||
|
||||
def test_remote_array_methods(ray_start_2_cpus, reload_modules):
|
||||
# test eye
|
||||
object_id = ra.eye.remote(3)
|
||||
val = ray.get(object_id)
|
||||
object_ref = ra.eye.remote(3)
|
||||
val = ray.get(object_ref)
|
||||
assert_almost_equal(val, np.eye(3))
|
||||
|
||||
# test zeros
|
||||
object_id = ra.zeros.remote([3, 4, 5])
|
||||
val = ray.get(object_id)
|
||||
object_ref = ra.zeros.remote([3, 4, 5])
|
||||
val = ray.get(object_ref)
|
||||
assert_equal(val, np.zeros([3, 4, 5]))
|
||||
|
||||
# test qr - pass by value
|
||||
@@ -35,7 +35,7 @@ def test_remote_array_methods(ray_start_2_cpus, reload_modules):
|
||||
r_val = ray.get(r_id)
|
||||
assert_almost_equal(np.dot(q_val, r_val), a_val)
|
||||
|
||||
# test qr - pass by objectid
|
||||
# test qr - pass by object_ref
|
||||
a = ra.random.normal.remote([10, 13])
|
||||
q_id, r_id = ra.linalg.qr.remote(a)
|
||||
a_val = ray.get(a)
|
||||
|
||||
@@ -40,7 +40,7 @@ def test_simple(init):
|
||||
def test_gather(init):
|
||||
loop = asyncio.get_event_loop()
|
||||
tasks = gen_tasks()
|
||||
futures = [obj_id.as_future() for obj_id in tasks]
|
||||
futures = [obj_ref.as_future() for obj_ref in tasks]
|
||||
results = loop.run_until_complete(asyncio.gather(*futures))
|
||||
assert all(a[0] == b[0] for a, b in zip(results, ray.get(tasks)))
|
||||
|
||||
@@ -48,7 +48,7 @@ def test_gather(init):
|
||||
def test_wait(init):
|
||||
loop = asyncio.get_event_loop()
|
||||
tasks = gen_tasks()
|
||||
futures = [obj_id.as_future() for obj_id in tasks]
|
||||
futures = [obj_ref.as_future() for obj_ref in tasks]
|
||||
results, _ = loop.run_until_complete(asyncio.wait(futures))
|
||||
assert set(results) == set(futures)
|
||||
|
||||
@@ -56,7 +56,7 @@ def test_wait(init):
|
||||
def test_wait_timeout(init):
|
||||
loop = asyncio.get_event_loop()
|
||||
tasks = gen_tasks(10)
|
||||
futures = [obj_id.as_future() for obj_id in tasks]
|
||||
futures = [obj_ref.as_future() for obj_ref in tasks]
|
||||
fut = asyncio.wait(futures, timeout=5)
|
||||
results, _ = loop.run_until_complete(fut)
|
||||
assert list(results)[0] == futures[0]
|
||||
|
||||
@@ -441,7 +441,7 @@ def test_passing_arguments_by_value_out_of_the_box(ray_start_regular):
|
||||
"local_mode": False
|
||||
}],
|
||||
indirect=True)
|
||||
def test_putting_object_that_closes_over_object_id(ray_start_regular):
|
||||
def test_putting_object_that_closes_over_object_ref(ray_start_regular):
|
||||
# This test is here to prevent a regression of
|
||||
# https://github.com/ray-project/ray/issues/1317.
|
||||
|
||||
@@ -461,26 +461,26 @@ def test_put_get(shutdown_only):
|
||||
|
||||
for i in range(100):
|
||||
value_before = i * 10**6
|
||||
objectid = ray.put(value_before)
|
||||
value_after = ray.get(objectid)
|
||||
object_ref = ray.put(value_before)
|
||||
value_after = ray.get(object_ref)
|
||||
assert value_before == value_after
|
||||
|
||||
for i in range(100):
|
||||
value_before = i * 10**6 * 1.0
|
||||
objectid = ray.put(value_before)
|
||||
value_after = ray.get(objectid)
|
||||
object_ref = ray.put(value_before)
|
||||
value_after = ray.get(object_ref)
|
||||
assert value_before == value_after
|
||||
|
||||
for i in range(100):
|
||||
value_before = "h" * i
|
||||
objectid = ray.put(value_before)
|
||||
value_after = ray.get(objectid)
|
||||
object_ref = ray.put(value_before)
|
||||
value_after = ray.get(object_ref)
|
||||
assert value_before == value_after
|
||||
|
||||
for i in range(100):
|
||||
value_before = [1] * i
|
||||
objectid = ray.put(value_before)
|
||||
value_after = ray.get(objectid)
|
||||
object_ref = ray.put(value_before)
|
||||
value_after = ray.get(object_ref)
|
||||
assert value_before == value_after
|
||||
|
||||
|
||||
@@ -728,6 +728,21 @@ def test_args_stars_after(ray_start_regular):
|
||||
ray.get(remote_test_function.remote(local_method, actor_method))
|
||||
|
||||
|
||||
def test_object_id_backward_compatibility(ray_start_regular):
|
||||
# We've renamed Python's `ObjectID` to `ObjectRef`, and added a type
|
||||
# alias for backward compatibility.
|
||||
# This test is to make sure legacy code can still use `ObjectID`.
|
||||
# TODO(hchen): once we completely remove Python's `ObjectID`,
|
||||
# this test can be removed as well.
|
||||
|
||||
# Check that these 2 types are the same.
|
||||
assert ray.ObjectID == ray.ObjectRef
|
||||
object_ref = ray.put(1)
|
||||
# Check that users can use either type in `isinstance`
|
||||
assert isinstance(object_ref, ray.ObjectID)
|
||||
assert isinstance(object_ref, ray.ObjectRef)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import pytest
|
||||
sys.exit(pytest.main(["-v", __file__]))
|
||||
|
||||
@@ -196,13 +196,13 @@ def test_redefining_remote_functions(shutdown_only):
|
||||
}],
|
||||
indirect=True)
|
||||
def test_get_multiple(ray_start_regular):
|
||||
object_ids = [ray.put(i) for i in range(10)]
|
||||
assert ray.get(object_ids) == list(range(10))
|
||||
object_refs = [ray.put(i) for i in range(10)]
|
||||
assert ray.get(object_refs) == list(range(10))
|
||||
|
||||
# Get a random choice of object IDs with duplicates.
|
||||
# Get a random choice of object refs with duplicates.
|
||||
indices = list(np.random.choice(range(10), 5))
|
||||
indices += indices
|
||||
results = ray.get([object_ids[i] for i in indices])
|
||||
results = ray.get([object_refs[i] for i in indices])
|
||||
assert results == indices
|
||||
|
||||
|
||||
@@ -214,13 +214,13 @@ def test_get_multiple(ray_start_regular):
|
||||
}],
|
||||
indirect=True)
|
||||
def test_get_multiple_experimental(ray_start_regular):
|
||||
object_ids = [ray.put(i) for i in range(10)]
|
||||
object_refs = [ray.put(i) for i in range(10)]
|
||||
|
||||
object_ids_tuple = tuple(object_ids)
|
||||
assert ray.experimental.get(object_ids_tuple) == list(range(10))
|
||||
object_refs_tuple = tuple(object_refs)
|
||||
assert ray.experimental.get(object_refs_tuple) == list(range(10))
|
||||
|
||||
object_ids_nparray = np.array(object_ids)
|
||||
assert ray.experimental.get(object_ids_nparray) == list(range(10))
|
||||
object_refs_nparray = np.array(object_refs)
|
||||
assert ray.experimental.get(object_refs_nparray) == list(range(10))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -412,10 +412,10 @@ def test_skip_plasma(ray_start_regular):
|
||||
return x * 2
|
||||
|
||||
a = Actor.remote()
|
||||
obj_id = a.f.remote(1)
|
||||
obj_ref = a.f.remote(1)
|
||||
# it is not stored in plasma
|
||||
assert not ray.worker.global_worker.core_worker.object_exists(obj_id)
|
||||
assert ray.get(obj_id) == 2
|
||||
assert not ray.worker.global_worker.core_worker.object_exists(obj_ref)
|
||||
assert ray.get(obj_ref) == 2
|
||||
|
||||
|
||||
def test_actor_call_order(shutdown_only):
|
||||
@@ -452,12 +452,12 @@ def test_actor_large_objects(ray_start_regular):
|
||||
return np.zeros(10000000)
|
||||
|
||||
a = Actor.remote()
|
||||
obj_id = a.f.remote()
|
||||
assert not ray.worker.global_worker.core_worker.object_exists(obj_id)
|
||||
done, _ = ray.wait([obj_id])
|
||||
obj_ref = a.f.remote()
|
||||
assert not ray.worker.global_worker.core_worker.object_exists(obj_ref)
|
||||
done, _ = ray.wait([obj_ref])
|
||||
assert len(done) == 1
|
||||
assert ray.worker.global_worker.core_worker.object_exists(obj_id)
|
||||
assert isinstance(ray.get(obj_id), np.ndarray)
|
||||
assert ray.worker.global_worker.core_worker.object_exists(obj_ref)
|
||||
assert isinstance(ray.get(obj_ref), np.ndarray)
|
||||
|
||||
|
||||
def test_actor_pass_by_ref(ray_start_regular):
|
||||
@@ -580,20 +580,21 @@ def test_wait(ray_start_regular):
|
||||
time.sleep(delay)
|
||||
return
|
||||
|
||||
object_ids = [f.remote(0), f.remote(0), f.remote(0), f.remote(0)]
|
||||
ready_ids, remaining_ids = ray.wait(object_ids)
|
||||
object_refs = [f.remote(0), f.remote(0), f.remote(0), f.remote(0)]
|
||||
ready_ids, remaining_ids = ray.wait(object_refs)
|
||||
assert len(ready_ids) == 1
|
||||
assert len(remaining_ids) == 3
|
||||
ready_ids, remaining_ids = ray.wait(object_ids, num_returns=4)
|
||||
assert set(ready_ids) == set(object_ids)
|
||||
ready_ids, remaining_ids = ray.wait(object_refs, num_returns=4)
|
||||
assert set(ready_ids) == set(object_refs)
|
||||
assert remaining_ids == []
|
||||
|
||||
object_ids = [f.remote(0), f.remote(5)]
|
||||
ready_ids, remaining_ids = ray.wait(object_ids, timeout=0.5, num_returns=2)
|
||||
object_refs = [f.remote(0), f.remote(5)]
|
||||
ready_ids, remaining_ids = ray.wait(
|
||||
object_refs, timeout=0.5, num_returns=2)
|
||||
assert len(ready_ids) == 1
|
||||
assert len(remaining_ids) == 1
|
||||
|
||||
# Verify that calling wait with duplicate object IDs throws an
|
||||
# Verify that calling wait with duplicate object refs throws an
|
||||
# exception.
|
||||
x = ray.put(1)
|
||||
with pytest.raises(Exception):
|
||||
@@ -605,8 +606,8 @@ def test_wait(ray_start_regular):
|
||||
assert remaining_ids == []
|
||||
|
||||
# Test semantics of num_returns with no timeout.
|
||||
oids = [ray.put(i) for i in range(10)]
|
||||
(found, rest) = ray.wait(oids, num_returns=2)
|
||||
obj_refs = [ray.put(i) for i in range(10)]
|
||||
(found, rest) = ray.wait(obj_refs, num_returns=2)
|
||||
assert len(found) == 2
|
||||
assert len(rest) == 8
|
||||
|
||||
@@ -665,14 +666,14 @@ def test_internal_config_when_connecting(ray_start_cluster):
|
||||
|
||||
# Check that the config was picked up (object pinning is disabled).
|
||||
ray.init(address=cluster.address)
|
||||
oid = ray.put(np.zeros(40 * 1024 * 1024, dtype=np.uint8))
|
||||
obj_ref = ray.put(np.zeros(40 * 1024 * 1024, dtype=np.uint8))
|
||||
|
||||
for _ in range(5):
|
||||
ray.put(np.zeros(40 * 1024 * 1024, dtype=np.uint8))
|
||||
|
||||
# This would not raise an exception if object pinning was enabled.
|
||||
with pytest.raises(ray.exceptions.UnreconstructableError):
|
||||
ray.get(oid)
|
||||
ray.get(obj_ref)
|
||||
|
||||
|
||||
def test_get_correct_node_ip():
|
||||
|
||||
@@ -223,9 +223,9 @@ def test_fast(shutdown_only, use_force):
|
||||
if random.random() > 0.95:
|
||||
ray.cancel(ids[idx], use_force)
|
||||
signaler.send.remote()
|
||||
for obj_id in ids:
|
||||
for obj_ref in ids:
|
||||
try:
|
||||
ray.get(obj_id)
|
||||
ray.get(obj_ref)
|
||||
except Exception as e:
|
||||
assert isinstance(e, valid_exceptions(use_force))
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ def test_dying_driver_get(ray_start_regular):
|
||||
driver = """
|
||||
import ray
|
||||
ray.init("{}")
|
||||
ray.get(ray.ObjectID(ray.utils.hex_to_binary("{}")))
|
||||
ray.get(ray.ObjectRef(ray.utils.hex_to_binary("{}")))
|
||||
""".format(address_info["redis_address"], x_id.hex())
|
||||
|
||||
p = run_string_as_driver_nonblocking(driver)
|
||||
@@ -128,8 +128,8 @@ def test_dying_worker_wait(ray_start_2_cpus):
|
||||
worker_pid = ray.get(get_pid.remote())
|
||||
|
||||
@ray.remote
|
||||
def block_in_wait(object_id_in_list):
|
||||
ray.wait(object_id_in_list)
|
||||
def block_in_wait(object_ref_in_list):
|
||||
ray.wait(object_ref_in_list)
|
||||
|
||||
# Have the worker wait in a wait call.
|
||||
block_in_wait.remote([x_id])
|
||||
@@ -166,7 +166,7 @@ def test_dying_driver_wait(ray_start_regular):
|
||||
driver = """
|
||||
import ray
|
||||
ray.init("{}")
|
||||
ray.wait([ray.ObjectID(ray.utils.hex_to_binary("{}"))])
|
||||
ray.wait([ray.ObjectRef(ray.utils.hex_to_binary("{}"))])
|
||||
""".format(address_info["redis_address"], x_id.hex())
|
||||
|
||||
p = run_string_as_driver_nonblocking(driver)
|
||||
|
||||
@@ -58,8 +58,8 @@ def test_worker_failed(ray_start_workers_separate_multinode):
|
||||
|
||||
# Submit more tasks than there are workers so that all workers and
|
||||
# cores are utilized.
|
||||
object_ids = [f.remote(i) for i in range(num_initial_workers * num_nodes)]
|
||||
object_ids += [f.remote(object_id) for object_id in object_ids]
|
||||
object_refs = [f.remote(i) for i in range(num_initial_workers * num_nodes)]
|
||||
object_refs += [f.remote(object_ref) for object_ref in object_refs]
|
||||
# Allow the tasks some time to begin executing.
|
||||
time.sleep(0.1)
|
||||
# Kill the workers as the tasks execute.
|
||||
@@ -68,9 +68,9 @@ def test_worker_failed(ray_start_workers_separate_multinode):
|
||||
time.sleep(0.1)
|
||||
# Make sure that we either get the object or we get an appropriate
|
||||
# exception.
|
||||
for object_id in object_ids:
|
||||
for object_ref in object_refs:
|
||||
try:
|
||||
ray.get(object_id)
|
||||
ray.get(object_ref)
|
||||
except (ray.exceptions.RayTaskError, ray.exceptions.RayWorkerError):
|
||||
pass
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ def test_dynamic_res_infeasible_rescheduling(ray_start_regular):
|
||||
return 1
|
||||
|
||||
remote_task = ray.remote(resources={res_name: res_capacity})(f)
|
||||
oid = remote_task.remote() # This is infeasible
|
||||
obj_ref = remote_task.remote() # This is infeasible
|
||||
ray.get(set_res.remote(res_name, res_capacity)) # Now should be feasible
|
||||
|
||||
def check_resources():
|
||||
@@ -75,7 +75,7 @@ def test_dynamic_res_infeasible_rescheduling(ray_start_regular):
|
||||
|
||||
wait_for_condition(check_resources)
|
||||
|
||||
successful, unsuccessful = ray.wait([oid], timeout=1)
|
||||
successful, unsuccessful = ray.wait([obj_ref], timeout=1)
|
||||
assert successful # The task completed
|
||||
|
||||
|
||||
|
||||
@@ -819,15 +819,15 @@ def test_raylet_crash_when_get(ray_start_regular):
|
||||
time.sleep(2)
|
||||
ray.worker._global_node.kill_raylet()
|
||||
|
||||
object_id = ray.put(np.zeros(200 * 1024, dtype=np.uint8))
|
||||
ray.internal.free(object_id)
|
||||
while ray.worker.global_worker.core_worker.object_exists(object_id):
|
||||
object_ref = ray.put(np.zeros(200 * 1024, dtype=np.uint8))
|
||||
ray.internal.free(object_ref)
|
||||
while ray.worker.global_worker.core_worker.object_exists(object_ref):
|
||||
time.sleep(1)
|
||||
|
||||
thread = threading.Thread(target=sleep_to_kill_raylet)
|
||||
thread.start()
|
||||
with pytest.raises(ray.exceptions.UnreconstructableError):
|
||||
ray.get(object_id)
|
||||
ray.get(object_ref)
|
||||
thread.join()
|
||||
|
||||
|
||||
@@ -938,11 +938,11 @@ def test_fill_object_store_lru_fallback(shutdown_only):
|
||||
end = time.time()
|
||||
assert end - start < 3
|
||||
|
||||
oids = []
|
||||
obj_refs = []
|
||||
for _ in range(3):
|
||||
oid = expensive_task.remote()
|
||||
ray.get(oid)
|
||||
oids.append(oid)
|
||||
obj_ref = expensive_task.remote()
|
||||
ray.get(obj_ref)
|
||||
obj_refs.append(obj_ref)
|
||||
|
||||
@ray.remote
|
||||
class LargeMemoryActor:
|
||||
@@ -954,16 +954,16 @@ def test_fill_object_store_lru_fallback(shutdown_only):
|
||||
|
||||
actor = LargeMemoryActor.remote()
|
||||
for _ in range(3):
|
||||
oid = actor.some_expensive_task.remote()
|
||||
ray.get(oid)
|
||||
oids.append(oid)
|
||||
obj_ref = actor.some_expensive_task.remote()
|
||||
ray.get(obj_ref)
|
||||
obj_refs.append(obj_ref)
|
||||
# Make sure actor does not die
|
||||
ray.get(actor.test.remote())
|
||||
|
||||
for _ in range(3):
|
||||
oid = ray.put(np.zeros(10**8 // 2, dtype=np.uint8))
|
||||
ray.get(oid)
|
||||
oids.append(oid)
|
||||
obj_ref = ray.put(np.zeros(10**8 // 2, dtype=np.uint8))
|
||||
ray.get(obj_ref)
|
||||
obj_refs.append(obj_ref)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -1022,13 +1022,13 @@ def test_serialized_id(ray_start_cluster):
|
||||
return x
|
||||
|
||||
@ray.remote
|
||||
def get(obj_ids, test_dependent_task):
|
||||
print("get", obj_ids)
|
||||
obj_id = obj_ids[0]
|
||||
def get(obj_refs, test_dependent_task):
|
||||
print("get", obj_refs)
|
||||
obj_ref = obj_refs[0]
|
||||
if test_dependent_task:
|
||||
assert ray.get(dependent_task.remote(obj_id)) == 1
|
||||
assert ray.get(dependent_task.remote(obj_ref)) == 1
|
||||
else:
|
||||
assert ray.get(obj_id) == 1
|
||||
assert ray.get(obj_ref) == 1
|
||||
|
||||
obj = small_object.remote()
|
||||
ray.get(get.remote([obj], False))
|
||||
|
||||
@@ -97,7 +97,7 @@ def test_global_gc_when_full(shutdown_only):
|
||||
|
||||
# GC should be triggered for all workers, including the local driver,
|
||||
# when the driver tries to ray.put a value that doesn't fit in the
|
||||
# object store. This should cause the captured ObjectIDs' numpy arrays
|
||||
# object store. This should cause the captured ObjectRefs' numpy arrays
|
||||
# to be evicted.
|
||||
ray.put(np.zeros(80 * 1024 * 1024, dtype=np.uint8))
|
||||
|
||||
@@ -116,7 +116,7 @@ def test_global_gc_when_full(shutdown_only):
|
||||
|
||||
# GC should be triggered for all workers, including the local driver,
|
||||
# when a remote task tries to put a return value that doesn't fit in
|
||||
# the object store. This should cause the captured ObjectIDs' numpy
|
||||
# the object store. This should cause the captured ObjectRefs' numpy
|
||||
# arrays to be evicted.
|
||||
ray.get(actors[0].return_large_array.remote())
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from ray.core.generated import node_manager_pb2
|
||||
from ray.core.generated import node_manager_pb2_grpc
|
||||
from ray.core.generated import reporter_pb2
|
||||
from ray.core.generated import reporter_pb2_grpc
|
||||
from ray.dashboard.memory import (ReferenceType, decode_object_id_if_needed,
|
||||
from ray.dashboard.memory import (ReferenceType, decode_object_ref_if_needed,
|
||||
MemoryTableEntry, MemoryTable, SortingType)
|
||||
from ray.test_utils import (RayTestTimeoutException,
|
||||
wait_until_succeeded_without_exception,
|
||||
@@ -210,7 +210,7 @@ def test_raylet_info_endpoint(shutdown_only):
|
||||
try:
|
||||
assert len(actor_info) == 1
|
||||
_, parent_actor_info = actor_info.popitem()
|
||||
assert parent_actor_info["numObjectIdsInScope"] == 13
|
||||
assert parent_actor_info["numObjectRefsInScope"] == 13
|
||||
assert parent_actor_info["numLocalObjects"] == 10
|
||||
children = parent_actor_info["children"]
|
||||
assert len(children) == 2
|
||||
@@ -486,7 +486,7 @@ def test_memory_dashboard(shutdown_only):
|
||||
stop_memory_table()
|
||||
return True
|
||||
|
||||
def test_serialized_object_id_reference():
|
||||
def test_serialized_object_ref_reference():
|
||||
@ray.remote
|
||||
def f(arg):
|
||||
time.sleep(1)
|
||||
@@ -508,7 +508,7 @@ def test_memory_dashboard(shutdown_only):
|
||||
stop_memory_table()
|
||||
return True
|
||||
|
||||
def test_captured_object_id_reference():
|
||||
def test_captured_object_ref_reference():
|
||||
a = ray.put(None)
|
||||
b = ray.put([a]) # Noqa F841
|
||||
del a
|
||||
@@ -562,12 +562,12 @@ def test_memory_dashboard(shutdown_only):
|
||||
True)
|
||||
|
||||
assert (wait_for_condition(
|
||||
test_serialized_object_id_reference,
|
||||
test_serialized_object_ref_reference,
|
||||
timeout=30000,
|
||||
retry_interval_ms=1000) is True)
|
||||
|
||||
assert (wait_for_condition(
|
||||
test_captured_object_id_reference,
|
||||
test_captured_object_ref_reference,
|
||||
timeout=30000,
|
||||
retry_interval_ms=1000) is True)
|
||||
|
||||
@@ -583,7 +583,7 @@ IS_DRIVER = True
|
||||
PID = 1
|
||||
OBJECT_ID = "7wpsIhgZiBz/////AQAAyAEAAAA="
|
||||
ACTOR_ID = "fffffffffffffffff66d17ba010000c801000000"
|
||||
DECODED_ID = decode_object_id_if_needed(OBJECT_ID)
|
||||
DECODED_ID = decode_object_ref_if_needed(OBJECT_ID)
|
||||
OBJECT_SIZE = 100
|
||||
|
||||
|
||||
@@ -721,8 +721,8 @@ def test_invalid_memory_entry():
|
||||
def test_valid_reference_memory_entry():
|
||||
memory_entry = build_local_reference_entry()
|
||||
assert memory_entry.reference_type == ReferenceType.LOCAL_REFERENCE
|
||||
assert memory_entry.object_id == ray.ObjectID(
|
||||
decode_object_id_if_needed(OBJECT_ID))
|
||||
assert memory_entry.object_ref == ray.ObjectRef(
|
||||
decode_object_ref_if_needed(OBJECT_ID))
|
||||
assert memory_entry.is_valid() is True
|
||||
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ def test_put_api(ray_start_regular):
|
||||
for obj in test_values:
|
||||
assert ray.get(ray.put(obj)) == obj
|
||||
|
||||
# Test putting object IDs.
|
||||
# Test putting object refs.
|
||||
x_id = ray.put(0)
|
||||
for obj in [[x_id], (x_id, ), {x_id: x_id}]:
|
||||
assert ray.get(ray.put(obj)) == obj
|
||||
|
||||
@@ -176,7 +176,7 @@ import time
|
||||
import ray
|
||||
import numpy as np
|
||||
ray.init(address="{}")
|
||||
object_ids = [ray.put(np.zeros(200 * 1024, dtype=np.uint8))
|
||||
object_refs = [ray.put(np.zeros(200 * 1024, dtype=np.uint8))
|
||||
for i in range(1000)]
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < 30:
|
||||
@@ -582,7 +582,7 @@ ray.init(address="{}")
|
||||
@ray.remote
|
||||
def g(x):
|
||||
return
|
||||
g.remote(ray.ObjectID(ray.utils.hex_to_binary("{}")))
|
||||
g.remote(ray.ObjectRef(ray.utils.hex_to_binary("{}")))
|
||||
time.sleep(1)
|
||||
print("success")
|
||||
"""
|
||||
@@ -590,7 +590,7 @@ print("success")
|
||||
# Create some drivers and let them exit and make sure everything is
|
||||
# still alive.
|
||||
for _ in range(3):
|
||||
nonexistent_id = ray.ObjectID.from_random()
|
||||
nonexistent_id = ray.ObjectRef.from_random()
|
||||
driver_script = driver_script_template.format(address,
|
||||
nonexistent_id.hex())
|
||||
out = run_string_as_driver(driver_script)
|
||||
@@ -606,7 +606,7 @@ import ray
|
||||
ray.init(address="{}")
|
||||
@ray.remote
|
||||
def g():
|
||||
ray.wait(ray.ObjectID(ray.utils.hex_to_binary("{}")))
|
||||
ray.wait(ray.ObjectRef(ray.utils.hex_to_binary("{}")))
|
||||
g.remote()
|
||||
time.sleep(1)
|
||||
print("success")
|
||||
@@ -615,7 +615,7 @@ print("success")
|
||||
# Create some drivers and let them exit and make sure everything is
|
||||
# still alive.
|
||||
for _ in range(3):
|
||||
nonexistent_id = ray.ObjectID.from_random()
|
||||
nonexistent_id = ray.ObjectRef.from_random()
|
||||
driver_script = driver_script_template.format(address,
|
||||
nonexistent_id.hex())
|
||||
out = run_string_as_driver(driver_script)
|
||||
|
||||
@@ -58,8 +58,8 @@ def test_worker_failed(ray_start_workers_separate_multinode):
|
||||
|
||||
# Submit more tasks than there are workers so that all workers and
|
||||
# cores are utilized.
|
||||
object_ids = [f.remote(i) for i in range(num_initial_workers * num_nodes)]
|
||||
object_ids += [f.remote(object_id) for object_id in object_ids]
|
||||
object_refs = [f.remote(i) for i in range(num_initial_workers * num_nodes)]
|
||||
object_refs += [f.remote(object_ref) for object_ref in object_refs]
|
||||
# Allow the tasks some time to begin executing.
|
||||
time.sleep(0.1)
|
||||
# Kill the workers as the tasks execute.
|
||||
@@ -68,9 +68,9 @@ def test_worker_failed(ray_start_workers_separate_multinode):
|
||||
time.sleep(0.1)
|
||||
# Make sure that we either get the object or we get an appropriate
|
||||
# exception.
|
||||
for object_id in object_ids:
|
||||
for object_ref in object_refs:
|
||||
try:
|
||||
ray.get(object_id)
|
||||
ray.get(object_ref)
|
||||
except (ray.exceptions.RayTaskError, ray.exceptions.RayWorkerError):
|
||||
pass
|
||||
|
||||
|
||||
@@ -232,7 +232,7 @@ def test_apply_async(pool):
|
||||
with pytest.raises(Exception):
|
||||
pool.apply_async(f, (1, 2), {"kwarg1": 3}).get()
|
||||
|
||||
# Won't return until the input ObjectID is fulfilled.
|
||||
# Won't return until the input ObjectRef is fulfilled.
|
||||
def ten_over(args):
|
||||
signal, val = args
|
||||
ray.get(signal.wait.remote())
|
||||
@@ -245,7 +245,7 @@ def test_apply_async(pool):
|
||||
with pytest.raises(TimeoutError):
|
||||
result.get(timeout=0.01)
|
||||
|
||||
# Fulfill the ObjectID.
|
||||
# Fulfill the ObjectRef.
|
||||
ray.get(signal.send.remote())
|
||||
result.wait(timeout=10)
|
||||
assert result.ready()
|
||||
@@ -257,7 +257,7 @@ def test_apply_async(pool):
|
||||
with pytest.raises(ValueError, match="not ready"):
|
||||
result.successful()
|
||||
|
||||
# Fulfill the ObjectID with 0, causing the task to fail (divide by zero).
|
||||
# Fulfill the ObjectRef with 0, causing the task to fail (divide by zero).
|
||||
ray.get(signal.send.remote())
|
||||
result.wait(timeout=10)
|
||||
assert result.ready()
|
||||
|
||||
@@ -50,12 +50,12 @@ def test_object_broadcast(ray_start_cluster_with_resource):
|
||||
def create_object():
|
||||
return np.zeros(1024 * 1024, dtype=np.uint8)
|
||||
|
||||
object_ids = []
|
||||
object_refs = []
|
||||
|
||||
for _ in range(3):
|
||||
# Broadcast an object to all machines.
|
||||
x_id = ray.put(x)
|
||||
object_ids.append(x_id)
|
||||
object_refs.append(x_id)
|
||||
ray.get([
|
||||
f._remote(args=[x_id], resources={str(i % num_nodes): 1})
|
||||
for i in range(10 * num_nodes)
|
||||
@@ -64,7 +64,7 @@ def test_object_broadcast(ray_start_cluster_with_resource):
|
||||
for _ in range(3):
|
||||
# Broadcast an object to all machines.
|
||||
x_id = create_object.remote()
|
||||
object_ids.append(x_id)
|
||||
object_refs.append(x_id)
|
||||
ray.get([
|
||||
f._remote(args=[x_id], resources={str(i % num_nodes): 1})
|
||||
for i in range(10 * num_nodes)
|
||||
@@ -75,7 +75,7 @@ def test_object_broadcast(ray_start_cluster_with_resource):
|
||||
transfer_events = ray.object_transfer_timeline()
|
||||
|
||||
# Make sure that each object was transferred a reasonable number of times.
|
||||
for x_id in object_ids:
|
||||
for x_id in object_refs:
|
||||
relevant_events = [
|
||||
event for event in transfer_events
|
||||
if event["cat"] == "transfer_send"
|
||||
@@ -141,12 +141,12 @@ def test_actor_broadcast(ray_start_cluster_with_resource):
|
||||
# Wait for the actors to start up.
|
||||
ray.get([a.ready.remote() for a in actors])
|
||||
|
||||
object_ids = []
|
||||
object_refs = []
|
||||
|
||||
# Broadcast a large object to all actors.
|
||||
for _ in range(5):
|
||||
x_id = ray.put(np.zeros(1024 * 1024, dtype=np.uint8))
|
||||
object_ids.append(x_id)
|
||||
object_refs.append(x_id)
|
||||
# Pass the object into a method for every actor.
|
||||
ray.get([a.set_weights.remote(x_id) for a in actors])
|
||||
|
||||
@@ -155,7 +155,7 @@ def test_actor_broadcast(ray_start_cluster_with_resource):
|
||||
transfer_events = ray.object_transfer_timeline()
|
||||
|
||||
# Make sure that each object was transferred a reasonable number of times.
|
||||
for x_id in object_ids:
|
||||
for x_id in object_refs:
|
||||
relevant_events = [
|
||||
event for event in transfer_events
|
||||
if event["cat"] == "transfer_send"
|
||||
|
||||
@@ -28,8 +28,8 @@ class TestRedisPassword:
|
||||
redis_ip, redis_port = address.split(":")
|
||||
|
||||
# Check that we can run a task
|
||||
object_id = f.remote()
|
||||
ray.get(object_id)
|
||||
object_ref = f.remote()
|
||||
ray.get(object_ref)
|
||||
|
||||
# Check that Redis connections require a password
|
||||
redis_client = redis.StrictRedis(
|
||||
@@ -55,8 +55,8 @@ class TestRedisPassword:
|
||||
initialize_head=True, connect=True, head_node_args=node_args)
|
||||
cluster.add_node(**node_args)
|
||||
|
||||
object_id = f.remote()
|
||||
ray.get(object_id)
|
||||
object_ref = f.remote()
|
||||
ray.get(object_ref)
|
||||
|
||||
def test_redis_port(self, shutdown_only):
|
||||
@ray.remote
|
||||
|
||||
@@ -29,28 +29,28 @@ def one_worker_100MiB(request):
|
||||
ray.shutdown()
|
||||
|
||||
|
||||
def _fill_object_store_and_get(oid, succeed=True, object_MiB=40,
|
||||
def _fill_object_store_and_get(obj, succeed=True, object_MiB=40,
|
||||
num_objects=5):
|
||||
for _ in range(num_objects):
|
||||
ray.put(np.zeros(object_MiB * 1024 * 1024, dtype=np.uint8))
|
||||
|
||||
if type(oid) is bytes:
|
||||
oid = ray.ObjectID(oid)
|
||||
if type(obj) is bytes:
|
||||
obj = ray.ObjectRef(obj)
|
||||
|
||||
if succeed:
|
||||
wait_for_condition(
|
||||
lambda: ray.worker.global_worker.core_worker.object_exists(oid))
|
||||
lambda: ray.worker.global_worker.core_worker.object_exists(obj))
|
||||
else:
|
||||
wait_for_condition(
|
||||
lambda: not ray.worker.global_worker.core_worker.object_exists(oid)
|
||||
lambda: not ray.worker.global_worker.core_worker.object_exists(obj)
|
||||
)
|
||||
|
||||
|
||||
def _check_refcounts(expected):
|
||||
actual = ray.worker.global_worker.core_worker.get_all_reference_counts()
|
||||
assert len(expected) == len(actual)
|
||||
for object_id, (local, submitted) in expected.items():
|
||||
hex_id = object_id.hex().encode("ascii")
|
||||
for object_ref, (local, submitted) in expected.items():
|
||||
hex_id = object_ref.hex().encode("ascii")
|
||||
assert hex_id in actual
|
||||
assert local == actual[hex_id]["local"]
|
||||
assert submitted == actual[hex_id]["submitted"]
|
||||
@@ -70,13 +70,13 @@ def check_refcounts(expected, timeout=10):
|
||||
|
||||
|
||||
def test_local_refcounts(ray_start_regular):
|
||||
oid1 = ray.put(None)
|
||||
check_refcounts({oid1: (1, 0)})
|
||||
oid1_copy = copy.copy(oid1)
|
||||
check_refcounts({oid1: (2, 0)})
|
||||
del oid1
|
||||
check_refcounts({oid1_copy: (1, 0)})
|
||||
del oid1_copy
|
||||
obj_ref1 = ray.put(None)
|
||||
check_refcounts({obj_ref1: (1, 0)})
|
||||
obj_ref1_copy = copy.copy(obj_ref1)
|
||||
check_refcounts({obj_ref1: (2, 0)})
|
||||
del obj_ref1
|
||||
check_refcounts({obj_ref1_copy: (1, 0)})
|
||||
del obj_ref1_copy
|
||||
check_refcounts({})
|
||||
|
||||
|
||||
@@ -233,13 +233,13 @@ def test_pending_task_dependency_pinning(one_worker_100MiB):
|
||||
# store.
|
||||
np_array = np.zeros(40 * 1024 * 1024, dtype=np.uint8)
|
||||
signal = SignalActor.remote()
|
||||
oid = pending.remote(np_array, signal.wait.remote())
|
||||
obj_ref = pending.remote(np_array, signal.wait.remote())
|
||||
|
||||
for _ in range(2):
|
||||
ray.put(np.zeros(40 * 1024 * 1024, dtype=np.uint8))
|
||||
|
||||
ray.get(signal.send.remote())
|
||||
ray.get(oid)
|
||||
ray.get(obj_ref)
|
||||
|
||||
|
||||
def test_feature_flag(shutdown_only):
|
||||
@@ -273,20 +273,20 @@ def test_feature_flag(shutdown_only):
|
||||
_fill_object_store_and_get(actor.get_large_object.remote(), succeed=False)
|
||||
|
||||
|
||||
def test_out_of_band_serialized_object_id(one_worker_100MiB):
|
||||
def test_out_of_band_serialized_object_ref(one_worker_100MiB):
|
||||
assert len(
|
||||
ray.worker.global_worker.core_worker.get_all_reference_counts()) == 0
|
||||
oid = ray.put("hello")
|
||||
_check_refcounts({oid: (1, 0)})
|
||||
oid_str = ray.cloudpickle.dumps(oid)
|
||||
_check_refcounts({oid: (2, 0)})
|
||||
del oid
|
||||
obj_ref = ray.put("hello")
|
||||
_check_refcounts({obj_ref: (1, 0)})
|
||||
obj_ref_str = ray.cloudpickle.dumps(obj_ref)
|
||||
_check_refcounts({obj_ref: (2, 0)})
|
||||
del obj_ref
|
||||
assert len(
|
||||
ray.worker.global_worker.core_worker.get_all_reference_counts()) == 1
|
||||
assert ray.get(ray.cloudpickle.loads(oid_str)) == "hello"
|
||||
assert ray.get(ray.cloudpickle.loads(obj_ref_str)) == "hello"
|
||||
|
||||
|
||||
def test_captured_object_id(one_worker_100MiB):
|
||||
def test_captured_object_ref(one_worker_100MiB):
|
||||
captured_id = ray.put(np.zeros(10 * 1024 * 1024, dtype=np.uint8))
|
||||
|
||||
@ray.remote
|
||||
@@ -295,16 +295,16 @@ def test_captured_object_id(one_worker_100MiB):
|
||||
ray.get(captured_id) # noqa: F821
|
||||
|
||||
signal = SignalActor.remote()
|
||||
oid = f.remote(signal)
|
||||
obj_ref = f.remote(signal)
|
||||
|
||||
# Delete local references.
|
||||
del f
|
||||
del captured_id
|
||||
|
||||
# Test that the captured object ID is pinned despite having no local
|
||||
# Test that the captured object ref is pinned despite having no local
|
||||
# references.
|
||||
ray.get(signal.send.remote())
|
||||
_fill_object_store_and_get(oid)
|
||||
_fill_object_store_and_get(obj_ref)
|
||||
|
||||
captured_id = ray.put(np.zeros(10 * 1024 * 1024, dtype=np.uint8))
|
||||
|
||||
@@ -316,16 +316,16 @@ def test_captured_object_id(one_worker_100MiB):
|
||||
|
||||
signal = SignalActor.remote()
|
||||
actor = Actor.remote()
|
||||
oid = actor.get.remote(signal)
|
||||
obj_ref = actor.get.remote(signal)
|
||||
|
||||
# Delete local references.
|
||||
del Actor
|
||||
del captured_id
|
||||
|
||||
# Test that the captured object ID is pinned despite having no local
|
||||
# Test that the captured object ref is pinned despite having no local
|
||||
# references.
|
||||
ray.get(signal.send.remote())
|
||||
_fill_object_store_and_get(oid)
|
||||
_fill_object_store_and_get(obj_ref)
|
||||
|
||||
|
||||
# Remote function takes serialized reference and doesn't hold onto it after
|
||||
@@ -343,7 +343,7 @@ def test_basic_serialized_reference(one_worker_100MiB, use_ray_put, failure):
|
||||
array_oid = put_object(
|
||||
np.zeros(40 * 1024 * 1024, dtype=np.uint8), use_ray_put)
|
||||
signal = SignalActor.remote()
|
||||
oid = pending.remote([array_oid], signal.wait.remote())
|
||||
obj_ref = pending.remote([array_oid], signal.wait.remote())
|
||||
|
||||
# Remove the local reference.
|
||||
array_oid_bytes = array_oid.binary()
|
||||
@@ -355,7 +355,7 @@ def test_basic_serialized_reference(one_worker_100MiB, use_ray_put, failure):
|
||||
# Fulfill the dependency, causing the task to finish.
|
||||
ray.get(signal.send.remote())
|
||||
try:
|
||||
ray.get(oid)
|
||||
ray.get(obj_ref)
|
||||
assert not failure
|
||||
except ray.exceptions.RayWorkerError:
|
||||
assert failure
|
||||
@@ -415,7 +415,7 @@ def test_recursive_serialized_reference(one_worker_100MiB, use_ray_put,
|
||||
|
||||
# Test that a passed reference held by an actor after the method finishes
|
||||
# is kept until the reference is removed from the actor. Also tests giving
|
||||
# the actor a duplicate reference to the same object ID.
|
||||
# the actor a duplicate reference to the same object ref.
|
||||
@pytest.mark.parametrize("use_ray_put,failure", [(False, False), (False, True),
|
||||
(True, False), (True, True)])
|
||||
def test_actor_holding_serialized_reference(one_worker_100MiB, use_ray_put,
|
||||
@@ -471,7 +471,7 @@ def test_actor_holding_serialized_reference(one_worker_100MiB, use_ray_put,
|
||||
|
||||
# Test that a passed reference held by an actor after a task finishes
|
||||
# is kept until the reference is removed from the worker. Also tests giving
|
||||
# the worker a duplicate reference to the same object ID.
|
||||
# the worker a duplicate reference to the same object ref.
|
||||
@pytest.mark.parametrize("use_ray_put,failure", [(False, False), (False, True),
|
||||
(True, False), (True, True)])
|
||||
def test_worker_holding_serialized_reference(one_worker_100MiB, use_ray_put,
|
||||
@@ -512,7 +512,7 @@ def test_worker_holding_serialized_reference(one_worker_100MiB, use_ray_put,
|
||||
_fill_object_store_and_get(array_oid_bytes, succeed=False)
|
||||
|
||||
|
||||
# Test that an object containing object IDs within it pins the inner IDs.
|
||||
# Test that an object containing object refs within it pins the inner IDs.
|
||||
def test_basic_nested_ids(one_worker_100MiB):
|
||||
inner_oid = ray.put(np.zeros(40 * 1024 * 1024, dtype=np.uint8))
|
||||
outer_oid = ray.put([inner_oid])
|
||||
|
||||
@@ -32,24 +32,24 @@ def one_worker_100MiB(request):
|
||||
ray.shutdown()
|
||||
|
||||
|
||||
def _fill_object_store_and_get(oid, succeed=True, object_MiB=40,
|
||||
def _fill_object_store_and_get(obj, succeed=True, object_MiB=40,
|
||||
num_objects=5):
|
||||
for _ in range(num_objects):
|
||||
ray.put(np.zeros(object_MiB * 1024 * 1024, dtype=np.uint8))
|
||||
|
||||
if type(oid) is bytes:
|
||||
oid = ray.ObjectID(oid)
|
||||
if type(obj) is bytes:
|
||||
obj = ray.ObjectRef(obj)
|
||||
|
||||
if succeed:
|
||||
wait_for_condition(
|
||||
lambda: ray.worker.global_worker.core_worker.object_exists(oid))
|
||||
lambda: ray.worker.global_worker.core_worker.object_exists(obj))
|
||||
else:
|
||||
wait_for_condition(
|
||||
lambda: not ray.worker.global_worker.core_worker.object_exists(oid)
|
||||
lambda: not ray.worker.global_worker.core_worker.object_exists(obj)
|
||||
)
|
||||
|
||||
|
||||
# Test that an object containing object IDs within it pins the inner IDs
|
||||
# Test that an object containing object refs within it pins the inner IDs
|
||||
# recursively and for submitted tasks.
|
||||
@pytest.mark.parametrize("use_ray_put,failure", [(False, False), (False, True),
|
||||
(True, False), (True, True)])
|
||||
@@ -99,11 +99,11 @@ def test_recursively_nest_ids(one_worker_100MiB, use_ray_put, failure):
|
||||
_fill_object_store_and_get(array_oid_bytes, succeed=False)
|
||||
|
||||
|
||||
# Test that serialized objectIDs returned from remote tasks are pinned until
|
||||
# Test that serialized ObjectRefs returned from remote tasks are pinned until
|
||||
# they go out of scope on the caller side.
|
||||
@pytest.mark.parametrize("use_ray_put,failure", [(False, False), (False, True),
|
||||
(True, False), (True, True)])
|
||||
def test_return_object_id(one_worker_100MiB, use_ray_put, failure):
|
||||
def test_return_object_ref(one_worker_100MiB, use_ray_put, failure):
|
||||
@ray.remote
|
||||
def return_an_id():
|
||||
return [
|
||||
@@ -139,11 +139,11 @@ def test_return_object_id(one_worker_100MiB, use_ray_put, failure):
|
||||
_fill_object_store_and_get(inner_oid_binary, succeed=False)
|
||||
|
||||
|
||||
# Test that serialized objectIDs returned from remote tasks are pinned if
|
||||
# Test that serialized ObjectRefs returned from remote tasks are pinned if
|
||||
# passed into another remote task by the caller.
|
||||
@pytest.mark.parametrize("use_ray_put,failure", [(False, False), (False, True),
|
||||
(True, False), (True, True)])
|
||||
def test_pass_returned_object_id(one_worker_100MiB, use_ray_put, failure):
|
||||
def test_pass_returned_object_ref(one_worker_100MiB, use_ray_put, failure):
|
||||
@ray.remote
|
||||
def return_an_id():
|
||||
return [
|
||||
@@ -179,7 +179,7 @@ def test_pass_returned_object_id(one_worker_100MiB, use_ray_put, failure):
|
||||
|
||||
def ref_not_exists():
|
||||
worker = ray.worker.global_worker
|
||||
inner_oid = ray.ObjectID(inner_oid_binary)
|
||||
inner_oid = ray.ObjectRef(inner_oid_binary)
|
||||
return not worker.core_worker.object_exists(inner_oid)
|
||||
|
||||
assert wait_for_condition(ref_not_exists)
|
||||
@@ -191,8 +191,8 @@ def test_pass_returned_object_id(one_worker_100MiB, use_ray_put, failure):
|
||||
# it finishes.
|
||||
@pytest.mark.parametrize("use_ray_put,failure", [(False, False), (False, True),
|
||||
(True, False), (True, True)])
|
||||
def test_recursively_pass_returned_object_id(one_worker_100MiB, use_ray_put,
|
||||
failure):
|
||||
def test_recursively_pass_returned_object_ref(one_worker_100MiB, use_ray_put,
|
||||
failure):
|
||||
@ray.remote
|
||||
def return_an_id():
|
||||
return put_object(
|
||||
@@ -246,14 +246,14 @@ def test_recursively_pass_returned_object_id(one_worker_100MiB, use_ray_put,
|
||||
|
||||
|
||||
# Call a recursive chain of tasks. The final task in the chain returns an
|
||||
# ObjectID returned by a task that it submitted. Every other task in the chain
|
||||
# returns the same ObjectID by calling ray.get() on its submitted task and
|
||||
# ObjectRef returned by a task that it submitted. Every other task in the chain
|
||||
# returns the same ObjectRef by calling ray.get() on its submitted task and
|
||||
# returning the result. The reference should still exist while the driver has a
|
||||
# reference to the final task's ObjectID.
|
||||
# reference to the final task's ObjectRef.
|
||||
@pytest.mark.parametrize("use_ray_put,failure", [(False, False), (False, True),
|
||||
(True, False), (True, True)])
|
||||
def test_recursively_return_borrowed_object_id(one_worker_100MiB, use_ray_put,
|
||||
failure):
|
||||
def test_recursively_return_borrowed_object_ref(one_worker_100MiB, use_ray_put,
|
||||
failure):
|
||||
@ray.remote
|
||||
def recursive(num_tasks_left):
|
||||
if num_tasks_left == 0:
|
||||
|
||||
@@ -355,8 +355,8 @@ def test_driver_put_errors(ray_start_object_store_memory):
|
||||
# def g(i):
|
||||
# # Each instance of g submits and blocks on the result of another remote
|
||||
# # task.
|
||||
# object_ids = [f.remote(i, j) for j in range(10)]
|
||||
# return ray.get(object_ids)
|
||||
# object_refs = [f.remote(i, j) for j in range(10)]
|
||||
# return ray.get(object_refs)
|
||||
#
|
||||
# ray.init(num_workers=1)
|
||||
# ray.get([g.remote(i) for i in range(1000)])
|
||||
|
||||
@@ -102,7 +102,7 @@ class RayTrialExecutor(TrialExecutor):
|
||||
self._trial_queued = False
|
||||
self._running = {}
|
||||
# Since trial resume after paused should not run
|
||||
# trial.train.remote(), thus no more new remote object id generated.
|
||||
# trial.train.remote(), thus no more new remote object ref generated.
|
||||
# We use self._paused to store paused trials here.
|
||||
self._paused = {}
|
||||
|
||||
|
||||
@@ -97,9 +97,9 @@ class UtilMonitor(Thread):
|
||||
def pin_in_object_store(obj):
|
||||
"""Deprecated, use ray.put(value, weakref=False) instead."""
|
||||
|
||||
obj_id = ray.put(obj, weakref=False)
|
||||
_pinned_objects.append(obj_id)
|
||||
return obj_id
|
||||
obj_ref = ray.put(obj, weakref=False)
|
||||
_pinned_objects.append(obj_ref)
|
||||
return obj_ref
|
||||
|
||||
|
||||
def get_pinned_object(pinned_id):
|
||||
|
||||
@@ -42,8 +42,8 @@ class ActorPool:
|
||||
|
||||
Arguments:
|
||||
fn (func): Function that takes (actor, value) as argument and
|
||||
returns an ObjectID computing the result over the value. The
|
||||
actor will be considered busy until the ObjectID completes.
|
||||
returns an ObjectRef computing the result over the value. The
|
||||
actor will be considered busy until the ObjectRef completes.
|
||||
values (list): List of values that fn(actor, value) should be
|
||||
applied to.
|
||||
|
||||
@@ -69,8 +69,8 @@ class ActorPool:
|
||||
|
||||
Arguments:
|
||||
fn (func): Function that takes (actor, value) as argument and
|
||||
returns an ObjectID computing the result over the value. The
|
||||
actor will be considered busy until the ObjectID completes.
|
||||
returns an ObjectRef computing the result over the value. The
|
||||
actor will be considered busy until the ObjectRef completes.
|
||||
values (list): List of values that fn(actor, value) should be
|
||||
applied to.
|
||||
|
||||
@@ -96,8 +96,8 @@ class ActorPool:
|
||||
|
||||
Arguments:
|
||||
fn (func): Function that takes (actor, value) as argument and
|
||||
returns an ObjectID computing the result over the value. The
|
||||
actor will be considered busy until the ObjectID completes.
|
||||
returns an ObjectRef computing the result over the value. The
|
||||
actor will be considered busy until the ObjectRef completes.
|
||||
value (object): Value to compute a result for.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -402,10 +402,10 @@ class ParallelIterator(Generic[T]):
|
||||
else:
|
||||
ready, _ = ray.wait(
|
||||
pending, num_returns=len(pending), timeout=timeout)
|
||||
for obj_id in ready:
|
||||
actor = futures.pop(obj_id)
|
||||
for obj_ref in ready:
|
||||
actor = futures.pop(obj_ref)
|
||||
try:
|
||||
batch = ray.get(obj_id)
|
||||
batch = ray.get(obj_ref)
|
||||
futures[actor.par_iter_slice_batch.remote(
|
||||
step=num_partitions,
|
||||
start=partition_index,
|
||||
@@ -545,11 +545,11 @@ class ParallelIterator(Generic[T]):
|
||||
else:
|
||||
ready, _ = ray.wait(
|
||||
pending, num_returns=len(pending), timeout=timeout)
|
||||
for obj_id in ready:
|
||||
actor = futures.pop(obj_id)
|
||||
for obj_ref in ready:
|
||||
actor = futures.pop(obj_ref)
|
||||
try:
|
||||
local_iter.shared_metrics.get().current_actor = actor
|
||||
batch = ray.get(obj_id)
|
||||
batch = ray.get(obj_ref)
|
||||
futures[actor.par_iter_next_batch.remote(
|
||||
batch_ms)] = actor
|
||||
for item in batch:
|
||||
|
||||
@@ -27,45 +27,45 @@ class PoolTaskError(Exception):
|
||||
|
||||
class ResultThread(threading.Thread):
|
||||
def __init__(self,
|
||||
object_ids,
|
||||
object_refs,
|
||||
callback=None,
|
||||
error_callback=None,
|
||||
total_object_ids=None):
|
||||
total_object_refs=None):
|
||||
threading.Thread.__init__(self, daemon=True)
|
||||
self._got_error = False
|
||||
self._object_ids = []
|
||||
self._object_refs = []
|
||||
self._num_ready = 0
|
||||
self._results = []
|
||||
self._ready_index_queue = queue.Queue()
|
||||
self._callback = callback
|
||||
self._error_callback = error_callback
|
||||
self._total_object_ids = total_object_ids or len(object_ids)
|
||||
self._total_object_refs = total_object_refs or len(object_refs)
|
||||
self._indices = {}
|
||||
# Thread-safe queue used to add ObjectIDs to fetch after creating
|
||||
# Thread-safe queue used to add ObjectRefs to fetch after creating
|
||||
# this thread (used to lazily submit for imap and imap_unordered).
|
||||
self._new_object_ids = queue.Queue()
|
||||
for object_id in object_ids:
|
||||
self._add_object_id(object_id)
|
||||
self._new_object_refs = queue.Queue()
|
||||
for object_ref in object_refs:
|
||||
self._add_object_ref(object_ref)
|
||||
|
||||
def _add_object_id(self, object_id):
|
||||
self._indices[object_id] = len(self._object_ids)
|
||||
self._object_ids.append(object_id)
|
||||
def _add_object_ref(self, object_ref):
|
||||
self._indices[object_ref] = len(self._object_refs)
|
||||
self._object_refs.append(object_ref)
|
||||
self._results.append(None)
|
||||
|
||||
def add_object_id(self, object_id):
|
||||
self._new_object_ids.put(object_id)
|
||||
def add_object_ref(self, object_ref):
|
||||
self._new_object_refs.put(object_ref)
|
||||
|
||||
def run(self):
|
||||
unready = copy.copy(self._object_ids)
|
||||
while self._num_ready < self._total_object_ids:
|
||||
unready = copy.copy(self._object_refs)
|
||||
while self._num_ready < self._total_object_refs:
|
||||
# Get as many new IDs from the queue as possible without blocking,
|
||||
# unless we have no IDs to wait on, in which case we block.
|
||||
while True:
|
||||
try:
|
||||
block = len(unready) == 0
|
||||
new_object_id = self._new_object_ids.get(block=block)
|
||||
self._add_object_id(new_object_id)
|
||||
unready.append(new_object_id)
|
||||
new_object_ref = self._new_object_refs.get(block=block)
|
||||
self._add_object_ref(new_object_ref)
|
||||
unready.append(new_object_ref)
|
||||
except queue.Empty:
|
||||
# queue.Empty means no result was retrieved if block=False.
|
||||
break
|
||||
@@ -114,12 +114,12 @@ class AsyncResult:
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
chunk_object_ids,
|
||||
chunk_object_refs,
|
||||
callback=None,
|
||||
error_callback=None,
|
||||
single_result=False):
|
||||
self._single_result = single_result
|
||||
self._result_thread = ResultThread(chunk_object_ids, callback,
|
||||
self._result_thread = ResultThread(chunk_object_refs, callback,
|
||||
error_callback)
|
||||
self._result_thread.start()
|
||||
|
||||
@@ -189,7 +189,7 @@ class IMapIterator:
|
||||
self._chunksize = chunksize or pool._calculate_chunksize(iterable)
|
||||
self._total_chunks = div_round_up(len(iterable), chunksize)
|
||||
self._result_thread = ResultThread(
|
||||
[], total_object_ids=self._total_chunks)
|
||||
[], total_object_refs=self._total_chunks)
|
||||
self._result_thread.start()
|
||||
|
||||
for _ in range(len(self._pool._actor_pool)):
|
||||
@@ -204,7 +204,7 @@ class IMapIterator:
|
||||
new_chunk_id = self._pool._submit_chunk(self._func, self._iterator,
|
||||
self._chunksize, actor_index)
|
||||
self._submitted_chunks.append(False)
|
||||
self._result_thread.add_object_id(new_chunk_id)
|
||||
self._result_thread.add_object_ref(new_chunk_id)
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
@@ -411,14 +411,14 @@ class Pool:
|
||||
# Batch should be a list of tuples: (args, kwargs).
|
||||
def _run_batch(self, actor_index, func, batch):
|
||||
actor, count = self._actor_pool[actor_index]
|
||||
object_id = actor.run_batch.remote(func, batch)
|
||||
object_ref = actor.run_batch.remote(func, batch)
|
||||
count += 1
|
||||
assert self._maxtasksperchild == -1 or count <= self._maxtasksperchild
|
||||
if count == self._maxtasksperchild:
|
||||
self._stop_actor(actor)
|
||||
actor, count = self._new_actor_entry()
|
||||
self._actor_pool[actor_index] = (actor, count)
|
||||
return object_id
|
||||
return object_ref
|
||||
|
||||
def apply(self, func, args=None, kwargs=None):
|
||||
"""Run the given function on a random actor process and return the
|
||||
@@ -459,10 +459,10 @@ class Pool:
|
||||
"""
|
||||
|
||||
self._check_running()
|
||||
object_id = self._run_batch(self._random_actor_index(), func,
|
||||
[(args, kwargs)])
|
||||
object_ref = self._run_batch(self._random_actor_index(), func,
|
||||
[(args, kwargs)])
|
||||
return AsyncResult(
|
||||
[object_id], callback, error_callback, single_result=True)
|
||||
[object_ref], callback, error_callback, single_result=True)
|
||||
|
||||
def _calculate_chunksize(self, iterable):
|
||||
chunksize, extra = divmod(len(iterable), len(self._actor_pool) * 4)
|
||||
@@ -500,10 +500,10 @@ class Pool:
|
||||
chunksize = self._calculate_chunksize(iterable)
|
||||
|
||||
iterator = iter(iterable)
|
||||
chunk_object_ids = []
|
||||
while len(chunk_object_ids) * chunksize < len(iterable):
|
||||
actor_index = len(chunk_object_ids) % len(self._actor_pool)
|
||||
chunk_object_ids.append(
|
||||
chunk_object_refs = []
|
||||
while len(chunk_object_refs) * chunksize < len(iterable):
|
||||
actor_index = len(chunk_object_refs) % len(self._actor_pool)
|
||||
chunk_object_refs.append(
|
||||
self._submit_chunk(
|
||||
func,
|
||||
iterator,
|
||||
@@ -511,7 +511,7 @@ class Pool:
|
||||
actor_index,
|
||||
unpack_args=unpack_args))
|
||||
|
||||
return chunk_object_ids
|
||||
return chunk_object_refs
|
||||
|
||||
def _map_async(self,
|
||||
func,
|
||||
@@ -521,9 +521,9 @@ class Pool:
|
||||
callback=None,
|
||||
error_callback=None):
|
||||
self._check_running()
|
||||
object_ids = self._chunk_and_run(
|
||||
object_refs = self._chunk_and_run(
|
||||
func, iterable, chunksize=chunksize, unpack_args=unpack_args)
|
||||
return AsyncResult(object_ids, callback, error_callback)
|
||||
return AsyncResult(object_refs, callback, error_callback)
|
||||
|
||||
def map(self, func, iterable, chunksize=None):
|
||||
"""Run the given function on each element in the iterable round-robin
|
||||
|
||||
@@ -201,7 +201,7 @@ def check_for_failure(remote_values):
|
||||
"""Checks remote values for any that returned and failed.
|
||||
|
||||
Args:
|
||||
remote_values (list): List of object IDs representing functions
|
||||
remote_values (list): List of object refs representing functions
|
||||
that may fail in the middle of execution. For example, running
|
||||
a SGD training loop in multiple parallel actor calls.
|
||||
|
||||
|
||||
+2
-2
@@ -233,8 +233,8 @@ def ensure_str(s, encoding="utf-8", errors="strict"):
|
||||
return s.decode(encoding, errors)
|
||||
|
||||
|
||||
def binary_to_object_id(binary_object_id):
|
||||
return ray.ObjectID(binary_object_id)
|
||||
def binary_to_object_ref(binary_object_ref):
|
||||
return ray.ObjectRef(binary_object_ref)
|
||||
|
||||
|
||||
def binary_to_task_id(binary_task_id):
|
||||
|
||||
+91
-89
@@ -33,7 +33,7 @@ import ray.state
|
||||
from ray import (
|
||||
ActorID,
|
||||
JobID,
|
||||
ObjectID,
|
||||
ObjectRef,
|
||||
Language,
|
||||
)
|
||||
from ray import import_thread
|
||||
@@ -121,7 +121,7 @@ class Worker:
|
||||
# increment every time when `ray.shutdown` is called.
|
||||
self._session_index = 0
|
||||
# Functions to run to process the values returned by ray.get. Each
|
||||
# postprocessor must take two arguments ("object_ids", and "values").
|
||||
# postprocessor must take two arguments ("object_refs", and "values").
|
||||
self._post_get_hooks = []
|
||||
|
||||
@property
|
||||
@@ -224,10 +224,10 @@ class Worker:
|
||||
"""
|
||||
self.mode = mode
|
||||
|
||||
def put_object(self, value, object_id=None, pin_object=True):
|
||||
"""Put value in the local object store with object id `objectid`.
|
||||
def put_object(self, value, object_ref=None, pin_object=True):
|
||||
"""Put value in the local object store with object reference `object_ref`.
|
||||
|
||||
This assumes that the value for `objectid` has not yet been placed in
|
||||
This assumes that the value for `object_ref` has not yet been placed in
|
||||
the local object store. If the plasma store is full, the worker will
|
||||
automatically retry up to DEFAULT_PUT_OBJECT_RETRIES times. Each
|
||||
retry will delay for an exponentially doubling amount of time,
|
||||
@@ -236,70 +236,71 @@ class Worker:
|
||||
|
||||
Args:
|
||||
value: The value to put in the object store.
|
||||
object_id (object_id.ObjectID): The object ID of the value to be
|
||||
object_ref (ObjectRef): The object ref of the value to be
|
||||
put. If None, one will be generated.
|
||||
pin_object: If set, the object will be pinned at the raylet.
|
||||
|
||||
Returns:
|
||||
object_id.ObjectID: The object ID the object was put under.
|
||||
ObjectRef: The object ref the object was put under.
|
||||
|
||||
Raises:
|
||||
ray.exceptions.ObjectStoreFullError: This is raised if the attempt
|
||||
to store the object fails because the object store is full even
|
||||
after multiple retries.
|
||||
"""
|
||||
# Make sure that the value is not an object ID.
|
||||
if isinstance(value, ObjectID):
|
||||
# Make sure that the value is not an object ref.
|
||||
if isinstance(value, ObjectRef):
|
||||
raise TypeError(
|
||||
"Calling 'put' on an ray.ObjectID is not allowed "
|
||||
"(similarly, returning an ray.ObjectID from a remote "
|
||||
"Calling 'put' on an ray.ObjectRef is not allowed "
|
||||
"(similarly, returning an ray.ObjectRef from a remote "
|
||||
"function is not allowed). If you really want to "
|
||||
"do this, you can wrap the ray.ObjectID in a list and "
|
||||
"do this, you can wrap the ray.ObjectRef in a list and "
|
||||
"call 'put' on it (or return it).")
|
||||
|
||||
if self.mode == LOCAL_MODE:
|
||||
assert object_id is None, ("Local Mode does not support "
|
||||
"inserting with an objectID")
|
||||
assert object_ref is None, ("Local Mode does not support "
|
||||
"inserting with an ObjectRef")
|
||||
|
||||
serialized_value = self.get_serialization_context().serialize(value)
|
||||
# This *must* be the first place that we construct this python
|
||||
# ObjectID because an entry with 0 local references is created when
|
||||
# ObjectRef because an entry with 0 local references is created when
|
||||
# the object is Put() in the core worker, expecting that this python
|
||||
# reference will be created. If another reference is created and
|
||||
# removed before this one, it will corrupt the state in the
|
||||
# reference counter.
|
||||
return ray.ObjectID(
|
||||
return ray.ObjectRef(
|
||||
self.core_worker.put_serialized_object(
|
||||
serialized_value, object_id=object_id, pin_object=pin_object))
|
||||
serialized_value, object_ref=object_ref,
|
||||
pin_object=pin_object))
|
||||
|
||||
def deserialize_objects(self, data_metadata_pairs, object_ids):
|
||||
def deserialize_objects(self, data_metadata_pairs, object_refs):
|
||||
context = self.get_serialization_context()
|
||||
return context.deserialize_objects(data_metadata_pairs, object_ids)
|
||||
return context.deserialize_objects(data_metadata_pairs, object_refs)
|
||||
|
||||
def get_objects(self, object_ids, timeout=None):
|
||||
def get_objects(self, object_refs, timeout=None):
|
||||
"""Get the values in the object store associated with the IDs.
|
||||
|
||||
Return the values from the local object store for object_ids. This will
|
||||
block until all the values for object_ids have been written to the
|
||||
local object store.
|
||||
Return the values from the local object store for object_refs. This
|
||||
will block until all the values for object_refs have been written to
|
||||
the local object store.
|
||||
|
||||
Args:
|
||||
object_ids (List[object_id.ObjectID]): A list of the object IDs
|
||||
object_refs (List[object_ref.ObjectRef]): A list of the object refs
|
||||
whose values should be retrieved.
|
||||
timeout (float): timeout (float): The maximum amount of time in
|
||||
seconds to wait before returning.
|
||||
"""
|
||||
# Make sure that the values are object IDs.
|
||||
for object_id in object_ids:
|
||||
if not isinstance(object_id, ObjectID):
|
||||
# Make sure that the values are object refs.
|
||||
for object_ref in object_refs:
|
||||
if not isinstance(object_ref, ObjectRef):
|
||||
raise TypeError(
|
||||
"Attempting to call `get` on the value {}, "
|
||||
"which is not an ray.ObjectID.".format(object_id))
|
||||
"which is not an ray.ObjectRef.".format(object_ref))
|
||||
|
||||
timeout_ms = int(timeout * 1000) if timeout else -1
|
||||
data_metadata_pairs = self.core_worker.get_objects(
|
||||
object_ids, self.current_task_id, timeout_ms)
|
||||
return self.deserialize_objects(data_metadata_pairs, object_ids)
|
||||
object_refs, self.current_task_id, timeout_ms)
|
||||
return self.deserialize_objects(data_metadata_pairs, object_refs)
|
||||
|
||||
def run_function_on_all_workers(self, function,
|
||||
run_on_other_drivers=False):
|
||||
@@ -470,7 +471,7 @@ def init(address=None,
|
||||
redis_max_memory=None,
|
||||
log_to_driver=True,
|
||||
node_ip_address=ray_constants.NODE_DEFAULT_IP,
|
||||
object_id_seed=None,
|
||||
object_ref_seed=None,
|
||||
local_mode=False,
|
||||
redirect_worker_output=None,
|
||||
redirect_output=None,
|
||||
@@ -551,9 +552,9 @@ def init(address=None,
|
||||
log_to_driver (bool): If true, the output from all of the worker
|
||||
processes on all nodes will be directed to the driver.
|
||||
node_ip_address (str): The IP address of the node that we are on.
|
||||
object_id_seed (int): Used to seed the deterministic generation of
|
||||
object IDs. The same value can be used across multiple runs of the
|
||||
same driver in order to generate the object IDs in a consistent
|
||||
object_ref_seed (int): Used to seed the deterministic generation of
|
||||
object refs. The same value can be used across multiple runs of the
|
||||
same driver in order to generate the object refs in a consistent
|
||||
manner. However, the same ID should not be used for different
|
||||
drivers.
|
||||
local_mode (bool): If true, the code will be executed serially. This
|
||||
@@ -690,7 +691,7 @@ def init(address=None,
|
||||
redis_port=redis_port,
|
||||
node_ip_address=node_ip_address,
|
||||
raylet_ip_address=raylet_ip_address,
|
||||
object_id_seed=object_id_seed,
|
||||
object_ref_seed=object_ref_seed,
|
||||
driver_mode=driver_mode,
|
||||
redirect_worker_output=redirect_worker_output,
|
||||
redirect_output=redirect_output,
|
||||
@@ -780,7 +781,7 @@ def init(address=None,
|
||||
raylet_ip_address=raylet_ip_address,
|
||||
redis_address=redis_address,
|
||||
redis_password=redis_password,
|
||||
object_id_seed=object_id_seed,
|
||||
object_ref_seed=object_ref_seed,
|
||||
temp_dir=temp_dir,
|
||||
load_code_from_local=load_code_from_local,
|
||||
_internal_config=_internal_config)
|
||||
@@ -1463,22 +1464,22 @@ def show_in_webui(message, key="", dtype="text"):
|
||||
blocking_get_inside_async_warned = False
|
||||
|
||||
|
||||
def get(object_ids, timeout=None):
|
||||
def get(object_refs, timeout=None):
|
||||
"""Get a remote object or a list of remote objects from the object store.
|
||||
|
||||
This method blocks until the object corresponding to the object ID is
|
||||
This method blocks until the object corresponding to the object ref is
|
||||
available in the local object store. If this object is not in the local
|
||||
object store, it will be shipped from an object store that has it (once the
|
||||
object has been created). If object_ids is a list, then the objects
|
||||
object has been created). If object_refs is a list, then the objects
|
||||
corresponding to each object in the list will be returned.
|
||||
|
||||
This method will issue a warning if it's running inside async context,
|
||||
you can use ``await object_id`` instead of ``ray.get(object_id)``. For
|
||||
a list of object ids, you can use ``await asyncio.gather(*object_ids)``.
|
||||
you can use ``await object_ref`` instead of ``ray.get(object_ref)``. For
|
||||
a list of object refs, you can use ``await asyncio.gather(*object_refs)``.
|
||||
|
||||
Args:
|
||||
object_ids: Object ID of the object to get or a list of object IDs to
|
||||
get.
|
||||
object_refs: Object ref of the object to get or a list of object refs
|
||||
to get.
|
||||
timeout (Optional[float]): The maximum amount of time in seconds to
|
||||
wait before returning.
|
||||
|
||||
@@ -1501,22 +1502,22 @@ def get(object_ids, timeout=None):
|
||||
if not blocking_get_inside_async_warned:
|
||||
logger.debug("Using blocking ray.get inside async actor. "
|
||||
"This blocks the event loop. Please use `await` "
|
||||
"on object id with asyncio.gather if you want to "
|
||||
"on object ref with asyncio.gather if you want to "
|
||||
"yield execution to the event loop instead.")
|
||||
blocking_get_inside_async_warned = True
|
||||
|
||||
with profiling.profile("ray.get"):
|
||||
is_individual_id = isinstance(object_ids, ray.ObjectID)
|
||||
is_individual_id = isinstance(object_refs, ray.ObjectRef)
|
||||
if is_individual_id:
|
||||
object_ids = [object_ids]
|
||||
object_refs = [object_refs]
|
||||
|
||||
if not isinstance(object_ids, list):
|
||||
raise ValueError("'object_ids' must either be an object ID "
|
||||
"or a list of object IDs.")
|
||||
if not isinstance(object_refs, list):
|
||||
raise ValueError("'object_refs' must either be an object ref "
|
||||
"or a list of object refs.")
|
||||
|
||||
global last_task_error_raise_time
|
||||
# TODO(ujvl): Consider how to allow user to retrieve the ready objects.
|
||||
values = worker.get_objects(object_ids, timeout=timeout)
|
||||
values = worker.get_objects(object_refs, timeout=timeout)
|
||||
for i, value in enumerate(values):
|
||||
if isinstance(value, RayError):
|
||||
last_task_error_raise_time = time.time()
|
||||
@@ -1529,7 +1530,7 @@ def get(object_ids, timeout=None):
|
||||
|
||||
# Run post processors.
|
||||
for post_processor in worker._post_get_hooks:
|
||||
values = post_processor(object_ids, values)
|
||||
values = post_processor(object_refs, values)
|
||||
|
||||
if is_individual_id:
|
||||
values = values[0]
|
||||
@@ -1549,56 +1550,56 @@ def put(value, weakref=False):
|
||||
It allows Ray to more aggressively reclaim memory.
|
||||
|
||||
Returns:
|
||||
The object ID assigned to this value.
|
||||
The object ref assigned to this value.
|
||||
"""
|
||||
worker = global_worker
|
||||
worker.check_connected()
|
||||
with profiling.profile("ray.put"):
|
||||
try:
|
||||
object_id = worker.put_object(value, pin_object=not weakref)
|
||||
object_ref = worker.put_object(value, pin_object=not weakref)
|
||||
except ObjectStoreFullError:
|
||||
logger.info(
|
||||
"Put failed since the value was either too large or the "
|
||||
"store was full of pinned objects.")
|
||||
raise
|
||||
return object_id
|
||||
return object_ref
|
||||
|
||||
|
||||
# Global variable to make sure we only send out the warning once.
|
||||
blocking_wait_inside_async_warned = False
|
||||
|
||||
|
||||
def wait(object_ids, num_returns=1, timeout=None):
|
||||
def wait(object_refs, num_returns=1, timeout=None):
|
||||
"""Return a list of IDs that are ready and a list of IDs that are not.
|
||||
|
||||
If timeout is set, the function returns either when the requested number of
|
||||
IDs are ready or when the timeout is reached, whichever occurs first. If it
|
||||
is not set, the function simply waits until that number of objects is ready
|
||||
and returns that exact number of object IDs.
|
||||
and returns that exact number of object refs.
|
||||
|
||||
This method returns two lists. The first list consists of object IDs that
|
||||
This method returns two lists. The first list consists of object refs that
|
||||
correspond to objects that are available in the object store. The second
|
||||
list corresponds to the rest of the object IDs (which may or may not be
|
||||
list corresponds to the rest of the object refs (which may or may not be
|
||||
ready).
|
||||
|
||||
Ordering of the input list of object IDs is preserved. That is, if A
|
||||
Ordering of the input list of object refs is preserved. That is, if A
|
||||
precedes B in the input list, and both are in the ready list, then A will
|
||||
precede B in the ready list. This also holds true if A and B are both in
|
||||
the remaining list.
|
||||
|
||||
This method will issue a warning if it's running inside an async context.
|
||||
Instead of ``ray.wait(object_ids)``, you can use
|
||||
``await asyncio.wait(object_ids)``.
|
||||
Instead of ``ray.wait(object_refs)``, you can use
|
||||
``await asyncio.wait(object_refs)``.
|
||||
|
||||
Args:
|
||||
object_ids (List[ObjectID]): List of object IDs for objects that may or
|
||||
may not be ready. Note that these IDs must be unique.
|
||||
num_returns (int): The number of object IDs that should be returned.
|
||||
object_refs (List[ObjectRef]): List of object refs for objects that may
|
||||
or may not be ready. Note that these IDs must be unique.
|
||||
num_returns (int): The number of object refs that should be returned.
|
||||
timeout (float): The maximum amount of time in seconds to wait before
|
||||
returning.
|
||||
|
||||
Returns:
|
||||
A list of object IDs that are ready and a list of the remaining object
|
||||
A list of object refs that are ready and a list of the remaining object
|
||||
IDs.
|
||||
"""
|
||||
worker = global_worker
|
||||
@@ -1610,26 +1611,27 @@ def wait(object_ids, num_returns=1, timeout=None):
|
||||
if not blocking_wait_inside_async_warned:
|
||||
logger.debug("Using blocking ray.wait inside async method. "
|
||||
"This blocks the event loop. Please use `await` "
|
||||
"on object id with asyncio.wait. ")
|
||||
"on object ref with asyncio.wait. ")
|
||||
blocking_wait_inside_async_warned = True
|
||||
|
||||
if isinstance(object_ids, ObjectID):
|
||||
raise TypeError("wait() expected a list of ray.ObjectID, got a single "
|
||||
"ray.ObjectID")
|
||||
|
||||
if not isinstance(object_ids, list):
|
||||
if isinstance(object_refs, ObjectRef):
|
||||
raise TypeError(
|
||||
"wait() expected a list of ray.ObjectID, got {}".format(
|
||||
type(object_ids)))
|
||||
"wait() expected a list of ray.ObjectRef, got a single "
|
||||
"ray.ObjectRef")
|
||||
|
||||
if not isinstance(object_refs, list):
|
||||
raise TypeError(
|
||||
"wait() expected a list of ray.ObjectRef, got {}".format(
|
||||
type(object_refs)))
|
||||
|
||||
if timeout is not None and timeout < 0:
|
||||
raise ValueError("The 'timeout' argument must be nonnegative. "
|
||||
"Received {}".format(timeout))
|
||||
|
||||
for object_id in object_ids:
|
||||
if not isinstance(object_id, ObjectID):
|
||||
raise TypeError("wait() expected a list of ray.ObjectID, "
|
||||
"got list containing {}".format(type(object_id)))
|
||||
for object_ref in object_refs:
|
||||
if not isinstance(object_ref, ObjectRef):
|
||||
raise TypeError("wait() expected a list of ray.ObjectRef, "
|
||||
"got list containing {}".format(type(object_ref)))
|
||||
|
||||
worker.check_connected()
|
||||
# TODO(swang): Check main thread.
|
||||
@@ -1638,22 +1640,22 @@ def wait(object_ids, num_returns=1, timeout=None):
|
||||
# TODO(rkn): This is a temporary workaround for
|
||||
# https://github.com/ray-project/ray/issues/997. However, it should be
|
||||
# fixed in Arrow instead of here.
|
||||
if len(object_ids) == 0:
|
||||
if len(object_refs) == 0:
|
||||
return [], []
|
||||
|
||||
if len(object_ids) != len(set(object_ids)):
|
||||
raise ValueError("Wait requires a list of unique object IDs.")
|
||||
if len(object_refs) != len(set(object_refs)):
|
||||
raise ValueError("Wait requires a list of unique object refs.")
|
||||
if num_returns <= 0:
|
||||
raise ValueError(
|
||||
"Invalid number of objects to return %d." % num_returns)
|
||||
if num_returns > len(object_ids):
|
||||
if num_returns > len(object_refs):
|
||||
raise ValueError("num_returns cannot be greater than the number "
|
||||
"of objects provided to ray.wait.")
|
||||
|
||||
timeout = timeout if timeout is not None else 10**6
|
||||
timeout_milliseconds = int(timeout * 1000)
|
||||
ready_ids, remaining_ids = worker.core_worker.wait(
|
||||
object_ids,
|
||||
object_refs,
|
||||
num_returns,
|
||||
timeout_milliseconds,
|
||||
worker.current_task_id,
|
||||
@@ -1702,7 +1704,7 @@ def kill(actor, no_restart=True):
|
||||
worker.core_worker.kill_actor(actor._ray_actor_id, no_restart)
|
||||
|
||||
|
||||
def cancel(object_id, force=False):
|
||||
def cancel(object_ref, force=False):
|
||||
"""Cancels a task according to the following conditions.
|
||||
|
||||
If the specified task is pending execution, it will not be executed. If
|
||||
@@ -1717,7 +1719,7 @@ def cancel(object_id, force=False):
|
||||
Calling ray.get on a canceled task will raise a RayCancellationError.
|
||||
|
||||
Args:
|
||||
object_id (ObjectID): ObjectID returned by the task
|
||||
object_ref (ObjectRef): ObjectRef returned by the task
|
||||
that should be canceled.
|
||||
force (boolean): Whether to force-kill a running task by killing
|
||||
the worker that is running the task.
|
||||
@@ -1727,11 +1729,11 @@ def cancel(object_id, force=False):
|
||||
worker = ray.worker.global_worker
|
||||
worker.check_connected()
|
||||
|
||||
if not isinstance(object_id, ray.ObjectID):
|
||||
if not isinstance(object_ref, ray.ObjectRef):
|
||||
raise TypeError(
|
||||
"ray.cancel() only supported for non-actor object IDs. "
|
||||
"Got: {}.".format(type(object_id)))
|
||||
return worker.core_worker.cancel_task(object_id, force)
|
||||
"ray.cancel() only supported for non-actor object refs. "
|
||||
"Got: {}.".format(type(object_ref)))
|
||||
return worker.core_worker.cancel_task(object_ref, force)
|
||||
|
||||
|
||||
def _mode(worker=global_worker):
|
||||
@@ -1810,7 +1812,7 @@ def remote(*args, **kwargs):
|
||||
It can also be used with specific keyword arguments:
|
||||
|
||||
* **num_return_vals:** This is only for *remote functions*. It specifies
|
||||
the number of object IDs returned by the remote function invocation.
|
||||
the number of object refs returned by the remote function invocation.
|
||||
* **num_cpus:** The quantity of CPU cores to reserve for this task or for
|
||||
the lifetime of the actor.
|
||||
* **num_gpus:** The quantity of GPUs to reserve for this task or for the
|
||||
|
||||
@@ -1088,14 +1088,14 @@ class Trainer(Trainable):
|
||||
logger.info("Health checking all workers...")
|
||||
checks = []
|
||||
for ev in workers.remote_workers():
|
||||
_, obj_id = ev.sample_with_count.remote()
|
||||
checks.append(obj_id)
|
||||
_, obj_ref = ev.sample_with_count.remote()
|
||||
checks.append(obj_ref)
|
||||
|
||||
healthy_workers = []
|
||||
for i, obj_id in enumerate(checks):
|
||||
for i, obj_ref in enumerate(checks):
|
||||
w = workers.remote_workers()[i]
|
||||
try:
|
||||
ray.get(obj_id)
|
||||
ray.get(obj_ref)
|
||||
healthy_workers.append(w)
|
||||
logger.info("Worker {} looks healthy".format(i + 1))
|
||||
except RayError:
|
||||
|
||||
Vendored
+7
-7
@@ -61,11 +61,11 @@ class RemoteVectorEnv(BaseEnv):
|
||||
|
||||
# Get and return observations for each of the ready envs
|
||||
env_ids = set()
|
||||
for obj_id in ready:
|
||||
actor = self.pending.pop(obj_id)
|
||||
for obj_ref in ready:
|
||||
actor = self.pending.pop(obj_ref)
|
||||
env_id = self.actors.index(actor)
|
||||
env_ids.add(env_id)
|
||||
ob, rew, done, info = ray.get(obj_id)
|
||||
ob, rew, done, info = ray.get(obj_ref)
|
||||
obs[env_id] = ob
|
||||
rewards[env_id] = rew
|
||||
dones[env_id] = done
|
||||
@@ -78,15 +78,15 @@ class RemoteVectorEnv(BaseEnv):
|
||||
def send_actions(self, action_dict: MultiEnvDict) -> None:
|
||||
for env_id, actions in action_dict.items():
|
||||
actor = self.actors[env_id]
|
||||
obj_id = actor.step.remote(actions)
|
||||
self.pending[obj_id] = actor
|
||||
obj_ref = actor.step.remote(actions)
|
||||
self.pending[obj_ref] = actor
|
||||
|
||||
@PublicAPI
|
||||
def try_reset(self,
|
||||
env_id: Optional[EnvID] = None) -> Optional[MultiAgentDict]:
|
||||
actor = self.actors[env_id]
|
||||
obj_id = actor.reset.remote()
|
||||
self.pending[obj_id] = actor
|
||||
obj_ref = actor.reset.remote()
|
||||
self.pending[obj_ref] = actor
|
||||
return ASYNC_RESET_RETURN
|
||||
|
||||
@PublicAPI
|
||||
|
||||
@@ -40,7 +40,7 @@ def get_learner_stats(grad_info: GradInfoDict) -> LearnerStatsDict:
|
||||
@DeveloperAPI
|
||||
def collect_metrics(local_worker: Optional["RolloutWorker"] = None,
|
||||
remote_workers: List["ActorHandle"] = [],
|
||||
to_be_collected: List["ObjectID"] = [],
|
||||
to_be_collected: List["ObjectRef"] = [],
|
||||
timeout_seconds: int = 180) -> ResultDict:
|
||||
"""Gathers episode metrics from RolloutWorker instances."""
|
||||
|
||||
@@ -57,9 +57,9 @@ def collect_metrics(local_worker: Optional["RolloutWorker"] = None,
|
||||
def collect_episodes(
|
||||
local_worker: Optional["RolloutWorker"] = None,
|
||||
remote_workers: List["ActorHandle"] = [],
|
||||
to_be_collected: List["ObjectID"] = [],
|
||||
to_be_collected: List["ObjectRef"] = [],
|
||||
timeout_seconds: int = 180
|
||||
) -> Tuple[List[Union[RolloutMetrics, OffPolicyEstimate]], List["ObjectID"]]:
|
||||
) -> Tuple[List[Union[RolloutMetrics, OffPolicyEstimate]], List["ObjectRef"]]:
|
||||
"""Gathers new episodes metrics tuples from the given evaluators."""
|
||||
|
||||
if remote_workers:
|
||||
|
||||
+16
-16
@@ -14,13 +14,13 @@ class TaskPool:
|
||||
self._objects = {}
|
||||
self._fetching = deque()
|
||||
|
||||
def add(self, worker, all_obj_ids):
|
||||
if isinstance(all_obj_ids, list):
|
||||
obj_id = all_obj_ids[0]
|
||||
def add(self, worker, all_obj_refs):
|
||||
if isinstance(all_obj_refs, list):
|
||||
obj_ref = all_obj_refs[0]
|
||||
else:
|
||||
obj_id = all_obj_ids
|
||||
self._tasks[obj_id] = worker
|
||||
self._objects[obj_id] = all_obj_ids
|
||||
obj_ref = all_obj_refs
|
||||
self._tasks[obj_ref] = worker
|
||||
self._objects[obj_ref] = all_obj_refs
|
||||
|
||||
def completed(self, blocking_wait=False):
|
||||
pending = list(self._tasks)
|
||||
@@ -28,16 +28,16 @@ class TaskPool:
|
||||
ready, _ = ray.wait(pending, num_returns=len(pending), timeout=0)
|
||||
if not ready and blocking_wait:
|
||||
ready, _ = ray.wait(pending, num_returns=1, timeout=10.0)
|
||||
for obj_id in ready:
|
||||
yield (self._tasks.pop(obj_id), self._objects.pop(obj_id))
|
||||
for obj_ref in ready:
|
||||
yield (self._tasks.pop(obj_ref), self._objects.pop(obj_ref))
|
||||
|
||||
def completed_prefetch(self, blocking_wait=False, max_yield=999):
|
||||
"""Similar to completed but only returns once the object is local.
|
||||
|
||||
Assumes obj_id only is one id."""
|
||||
Assumes obj_ref only is one id."""
|
||||
|
||||
for worker, obj_id in self.completed(blocking_wait=blocking_wait):
|
||||
self._fetching.append((worker, obj_id))
|
||||
for worker, obj_ref in self.completed(blocking_wait=blocking_wait):
|
||||
self._fetching.append((worker, obj_ref))
|
||||
|
||||
for _ in range(max_yield):
|
||||
if not self._fetching:
|
||||
@@ -47,18 +47,18 @@ class TaskPool:
|
||||
|
||||
def reset_workers(self, workers):
|
||||
"""Notify that some workers may be removed."""
|
||||
for obj_id, ev in self._tasks.copy().items():
|
||||
for obj_ref, ev in self._tasks.copy().items():
|
||||
if ev not in workers:
|
||||
del self._tasks[obj_id]
|
||||
del self._objects[obj_id]
|
||||
del self._tasks[obj_ref]
|
||||
del self._objects[obj_ref]
|
||||
|
||||
# We want to keep the same deque reference so that we don't suffer from
|
||||
# stale references in generators that are still in flight
|
||||
for _ in range(len(self._fetching)):
|
||||
ev, obj_id = self._fetching.popleft()
|
||||
ev, obj_ref = self._fetching.popleft()
|
||||
if ev in workers:
|
||||
# Re-queue items that are still valid
|
||||
self._fetching.append((ev, obj_id))
|
||||
self._fetching.append((ev, obj_ref))
|
||||
|
||||
@property
|
||||
def count(self):
|
||||
|
||||
@@ -5,15 +5,15 @@ import ray
|
||||
from ray.rllib.utils.actors import TaskPool
|
||||
|
||||
|
||||
def createMockWorkerAndObjectId(obj_id):
|
||||
return ({obj_id: 1}, obj_id)
|
||||
def createMockWorkerAndObjectRef(obj_ref):
|
||||
return ({obj_ref: 1}, obj_ref)
|
||||
|
||||
|
||||
class TaskPoolTest(unittest.TestCase):
|
||||
@patch("ray.wait")
|
||||
def test_completed_prefetch_yieldsAllComplete(self, rayWaitMock):
|
||||
task1 = createMockWorkerAndObjectId(1)
|
||||
task2 = createMockWorkerAndObjectId(2)
|
||||
task1 = createMockWorkerAndObjectRef(1)
|
||||
task2 = createMockWorkerAndObjectRef(2)
|
||||
# Return the second task as complete and the first as pending
|
||||
rayWaitMock.return_value = ([2], [1])
|
||||
|
||||
@@ -32,12 +32,12 @@ class TaskPoolTest(unittest.TestCase):
|
||||
# items and the second call yields the final one
|
||||
pool = TaskPool()
|
||||
for i in range(1000):
|
||||
task = createMockWorkerAndObjectId(i)
|
||||
task = createMockWorkerAndObjectRef(i)
|
||||
pool.add(*task)
|
||||
|
||||
rayWaitMock.return_value = (list(range(1000)), [])
|
||||
|
||||
# For this test, we're only checking the object ids
|
||||
# For this test, we're only checking the object refs
|
||||
fetched = [pair[1] for pair in pool.completed_prefetch()]
|
||||
self.assertListEqual(fetched, list(range(999)))
|
||||
|
||||
@@ -53,7 +53,7 @@ class TaskPoolTest(unittest.TestCase):
|
||||
# and the second call yields the final one
|
||||
pool = TaskPool()
|
||||
for i in range(1000):
|
||||
task = createMockWorkerAndObjectId(i)
|
||||
task = createMockWorkerAndObjectRef(i)
|
||||
pool.add(*task)
|
||||
|
||||
rayWaitMock.return_value = (list(range(1000)), [])
|
||||
@@ -73,10 +73,10 @@ class TaskPoolTest(unittest.TestCase):
|
||||
# Test for issue #7106
|
||||
# In versions of Ray up to 0.8.1, if the pre-fetch generator failed to
|
||||
# run to completion, then the TaskPool would fail to clear up already
|
||||
# fetched tasks resulting in stale object ids being returned
|
||||
# fetched tasks resulting in stale object refs being returned
|
||||
pool = TaskPool()
|
||||
for i in range(10):
|
||||
task = createMockWorkerAndObjectId(i)
|
||||
task = createMockWorkerAndObjectRef(i)
|
||||
pool.add(*task)
|
||||
|
||||
rayWaitMock.return_value = (list(range(10)), [])
|
||||
@@ -102,7 +102,7 @@ class TaskPoolTest(unittest.TestCase):
|
||||
tasks = []
|
||||
|
||||
for i in range(10):
|
||||
task = createMockWorkerAndObjectId(i)
|
||||
task = createMockWorkerAndObjectRef(i)
|
||||
pool.add(*task)
|
||||
tasks.append(task)
|
||||
|
||||
|
||||
@@ -1892,7 +1892,7 @@ void CoreWorker::HandleGetCoreWorkerStats(const rpc::GetCoreWorkerStatsRequest &
|
||||
stats->set_num_pending_tasks(task_manager_->NumSubmissibleTasks());
|
||||
stats->set_task_queue_length(task_queue_length_);
|
||||
stats->set_num_executed_tasks(num_executed_tasks_);
|
||||
stats->set_num_object_ids_in_scope(reference_counter_->NumObjectIDsInScope());
|
||||
stats->set_num_object_refs_in_scope(reference_counter_->NumObjectIDsInScope());
|
||||
stats->set_current_task_func_desc(current_task_.FunctionDescriptor()->ToString());
|
||||
stats->set_ip_address(rpc_address_.ip_address());
|
||||
stats->set_port(rpc_address_.port());
|
||||
|
||||
@@ -303,8 +303,8 @@ message CoreWorkerStats {
|
||||
string current_task_desc = 1;
|
||||
// Number of pending normal and actor tasks.
|
||||
int32 num_pending_tasks = 2;
|
||||
// Number of object ids in local scope.
|
||||
int32 num_object_ids_in_scope = 3;
|
||||
// Number of object refs in local scope.
|
||||
int32 num_object_refs_in_scope = 3;
|
||||
// String representation of the function descriptor of the currently executing task.
|
||||
string current_task_func_desc = 4;
|
||||
// IP address of the core worker.
|
||||
|
||||
@@ -21,7 +21,7 @@ from ray.includes.unique_ids cimport (
|
||||
from ray._raylet cimport (
|
||||
Buffer,
|
||||
ActorID,
|
||||
ObjectID,
|
||||
ObjectRef,
|
||||
FunctionDescriptor,
|
||||
)
|
||||
|
||||
@@ -49,7 +49,7 @@ channel_logger = logging.getLogger(__name__)
|
||||
cdef class ChannelCreationParameter:
|
||||
cdef:
|
||||
CChannelCreationParameter parameter
|
||||
|
||||
|
||||
def __cinit__(self, ActorID actor_id, FunctionDescriptor async_func, FunctionDescriptor sync_func):
|
||||
cdef:
|
||||
shared_ptr[CRayFunction] async_func_ptr
|
||||
@@ -190,7 +190,7 @@ cdef class DataWriter:
|
||||
channel_logger.info("deleted DataWriter")
|
||||
self.writer = NULL
|
||||
|
||||
def write(self, ObjectID qid, const unsigned char[:] value):
|
||||
def write(self, ObjectRef qid, const unsigned char[:] value):
|
||||
"""support zero-copy bytes, bytearray, array of unsigned char"""
|
||||
cdef:
|
||||
CObjectID native_id = qid.data
|
||||
@@ -322,4 +322,4 @@ cdef c_vector[c_string] qid_vector_to_list(c_vector[CObjectID] queue_id_vec):
|
||||
queues = []
|
||||
for obj_id in queue_id_vec:
|
||||
queues.append(obj_id.Binary())
|
||||
return queues
|
||||
return queues
|
||||
|
||||
@@ -27,7 +27,8 @@ class ChannelID:
|
||||
channel_id_str: string representation of channel id
|
||||
"""
|
||||
self.channel_id_str = channel_id_str
|
||||
self.object_qid = ray.ObjectID(channel_id_str_to_bytes(channel_id_str))
|
||||
self.object_qid = ray.ObjectRef(
|
||||
channel_id_str_to_bytes(channel_id_str))
|
||||
|
||||
def __eq__(self, other):
|
||||
if other is None:
|
||||
|
||||
Reference in New Issue
Block a user