What is Ray Core?¶
Ray Core provides a small number of core primitives (i.e., tasks, actors, objects) for building and scaling distributed applications. Below we’ll walk through simple examples that show you how to turn your functions and classes easily into Ray tasks and actors, and how to work with Ray objects.
To get started, install Ray via
pip install -U ray. See Installing Ray for more installation options. The following few sections will walk through the basics of using Ray Core.
The first step is to import and initialize Ray:
import ray ray.init()
In recent versions of Ray (>=1.5),
ray.init() is automatically called on the first use of a Ray remote API.
Running a Task¶
Ray lets you run functions as remote tasks in the cluster. To do this, you decorate your function with
@ray.remote to declare that you want to run this function remotely.
Then, you call that function with
.remote() instead of calling it normally.
This remote call yields a future, a so-called Ray object reference, that you can then fetch with
# Define the square task. @ray.remote def square(x): return x * x # Launch four parallel square tasks. futures = [square.remote(i) for i in range(4)] # Retrieve results. print(ray.get(futures)) # -> [0, 1, 4, 9]
Calling an Actor¶
Ray provides actors to allow you to parallelize computation across multiple actor instances. When you instantiate a class that is a Ray actor, Ray will start a remote instance of that class in the cluster. This actor can then execute remote method calls and maintain its own internal state:
# Define the Counter actor. @ray.remote class Counter: def __init__(self): self.i = 0 def get(self): return self.i def incr(self, value): self.i += value # Create a Counter actor. c = Counter.remote() # Submit calls to the actor. These calls run asynchronously but in # submission order on the remote actor process. for _ in range(10): c.incr.remote(1) # Retrieve final actor state. print(ray.get(c.get.remote())) # -> 10
The above covers very basic actor usage. For a more in-depth example, including using both tasks and actors together, check out Monte Carlo Estimation of π.
Passing an Object¶
As seen above, Ray stores task and actor call results in its distributed object store, returning object references that can be later retrieved. Object references can also be created explicitly via
ray.put, and object references can be passed to tasks as substitutes for argument values:
import numpy as np # Define a task that sums the values in a matrix. @ray.remote def sum_matrix(matrix): return np.sum(matrix) # Call the task with a literal argument value. print(ray.get(sum_matrix.remote(np.ones((100, 100))))) # -> 10000.0 # Put a large array into the object store. matrix_ref = ray.put(np.ones((1000, 1000))) # Call the task with the object reference as an argument. print(ray.get(sum_matrix.remote(matrix_ref))) # -> 1000000.0