<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aman anand</title>
    <description>The latest articles on DEV Community by Aman anand (@neuralnoble).</description>
    <link>https://dev.to/neuralnoble</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1949075%2F0d0d0ef3-367f-458d-90b4-d8bd6f54b6b4.png</url>
      <title>DEV Community: Aman anand</title>
      <link>https://dev.to/neuralnoble</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/neuralnoble"/>
    <language>en</language>
    <item>
      <title>Ray Essentials: A Beginner's Roadmap to Distributed Python</title>
      <dc:creator>Aman anand</dc:creator>
      <pubDate>Mon, 19 Aug 2024 10:47:31 +0000</pubDate>
      <link>https://dev.to/neuralnoble/ray-essentials-a-beginners-roadmap-to-distributed-python-182p</link>
      <guid>https://dev.to/neuralnoble/ray-essentials-a-beginners-roadmap-to-distributed-python-182p</guid>
      <description>&lt;h1&gt;
  
  
  Ray Anyscale
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Introduction to Ray
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is Ray?
&lt;/h3&gt;

&lt;p&gt;Ray is an open-source framework designed to scale Python applications from a single machine to large clusters. It provides a unified interface for distributed computing, making it easier to build and run distributed applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why use Ray?
&lt;/h3&gt;

&lt;p&gt;Ray addresses several challenges in distributed computing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplifies the transition from local to distributed execution&lt;/li&gt;
&lt;li&gt;Provides efficient resource management across a cluster&lt;/li&gt;
&lt;li&gt;Enables seamless scaling of applications&lt;/li&gt;
&lt;li&gt;Offers a rich ecosystem of libraries for various tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Distributed Task Execution: Ray allows you to run functions (tasks) across multiple machines with minimal changes to your code.&lt;/li&gt;
&lt;li&gt;Actor Model: Ray implements the actor model, allowing you to create and manage stateful workers.&lt;/li&gt;
&lt;li&gt;Flexible Scaling: Ray can scale from a single machine to thousands of nodes in a cluster.&lt;/li&gt;
&lt;li&gt;Rich Ecosystem: Ray comes with libraries for machine learning (Ray Tune, RLlib), serving (Ray Serve), and data processing (Ray Data).&lt;/li&gt;
&lt;li&gt;Fault Tolerance: Ray provides mechanisms to handle failures and recover from them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before we go on to understand what are tasks we first need to understand what are remote functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remote Functions
&lt;/h3&gt;

&lt;p&gt;Remote functions in Ray are just regular Python functions with a special power: they can run on any computer in your Ray setup, not just the one you're typing on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Characteristics
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous Execution&lt;/strong&gt; : When called, remote functions return immediately with an ObjectRef (future), allowing for non-blocking operations.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When we say "remote functions return immediately with an ObjectRef (future), allowing for non-blocking operations," we're talking about how remote functions behave differently from regular functions. Let's break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Return immediately":
When you call a regular function, your program waits for it to finish before moving on. But when you call a remote function, it starts the work and immediately gives you back a kind of "receipt" (the ObjectRef). Your program can then continue right away without waiting.&lt;/li&gt;
&lt;li&gt; "ObjectRef (future)":
This "receipt" is called an ObjectRef. It's like a promise that you'll get the actual result later. We sometimes call it a "future" because it represents a value you'll get in the future.&lt;/li&gt;
&lt;li&gt;"Non-blocking operations":
This means your program doesn't get stuck waiting. It can do other things while the remote function is working.&lt;/li&gt;
&lt;li&gt;in code it looks like this
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@ray.remote&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Pretend this is doing some heavy work
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Done!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# Start the remote function
&lt;/span&gt;&lt;span class="n"&gt;future&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;slow_function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# This prints immediately, we don't wait for slow_function to finish
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I can do other things while waiting!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# When we actually need the result, we use ray.get()
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Distributed Execution&lt;/strong&gt;: They can be executed on any available worker in the Ray cluster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateless&lt;/strong&gt;: Each invocation of a remote function is independent and doesn't maintain state between calls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serialization&lt;/strong&gt;: Arguments to and return values from remote functions are automatically serialized and deserialized by Ray.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When we say remote functions are "stateless," it means they have no memory of previous calls. Each time you use a remote function, it's like starting fresh, with no information carried over from before.&lt;br&gt;
Let's break it down with a simple analogy:&lt;br&gt;
Imagine a vending machine (this represents our remote function):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stateful (what remote functions are NOT):
If the vending machine was stateful, it might remember your previous purchases. If you bought a soda yesterday, it might say "Welcome back! Want another soda?" the next time you use it.&lt;/li&gt;
&lt;li&gt;Stateless (what remote functions ARE):
A stateless vending machine treats every interaction as new. It doesn't remember if you've used it before or what you bought last time. Each time you use it, it's like it's meeting you for the first time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's a code example to illustrate this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;

&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@ray.remote&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StatefulCounter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;

&lt;span class="nd"&gt;@ray.remote&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stateless_increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;# Stateful example (this is NOT how remote functions work)
&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StatefulCounter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;  &lt;span class="c1"&gt;# Prints 1
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;  &lt;span class="c1"&gt;# Prints 2
&lt;/span&gt;
&lt;span class="c1"&gt;# Stateless example (this IS how remote functions work)
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stateless_increment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;  &lt;span class="c1"&gt;# Prints 1
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stateless_increment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;  &lt;span class="c1"&gt;# Prints 1 again
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the stateful example, the StatefulCounter remembers its count between calls. This is not how remote functions work.&lt;/p&gt;

&lt;p&gt;In the stateless example, stateless_increment doesn't remember anything. Each call starts fresh, so if you always pass in 0, you'll always get 1 back.&lt;/p&gt;

&lt;p&gt;The key points are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each call to a remote function is independent.&lt;/li&gt;
&lt;li&gt;Remote functions don't remember anything from previous calls.&lt;/li&gt;
&lt;li&gt;If you need to keep track of something between calls, you need to manage that yourself (maybe by passing in updated values each time).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This stateless nature makes remote functions simpler and more predictable, especially when running them across multiple computers.&lt;/p&gt;

&lt;p&gt;Serialization is like packing a suitcase for a trip, and deserialization is like unpacking it when you arrive. Here's how it works in Ray:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Serialization:&lt;/strong&gt;
When you call a remote function, Ray needs to send the function and its arguments to another computer (or process) to run. But computers can't directly send Python objects over a network. So, Ray "packs" (serializes) these objects into a format that can be sent easily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deserialization:&lt;/strong&gt;
When the packed data arrives at the destination, Ray "unpacks" (deserializes) it back into Python objects so the function can use them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tasks
&lt;/h2&gt;

&lt;p&gt;Tasks in Ray are one of the core building blocks for parallel and distributed computing. They represent units of work that can be executed asynchronously and in parallel across a cluster of machines.&lt;em&gt;Think of a task as a job that you want to get done, but you're okay with someone else doing it for you.&lt;/em&gt;&lt;br&gt;
More technically Tasks are remote functions that can be executed anywhere in a Ray cluster. They are defined using the &lt;code&gt;@ray.remote&lt;/code&gt; decorator.&lt;/p&gt;
&lt;h3&gt;
  
  
  How to Create and Use Tasks?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creating Tasks:&lt;/strong&gt;
To create a task, you simply decorate a Python function with &lt;a class="mentioned-user" href="https://dev.to/ray"&gt;@ray&lt;/a&gt;.remote
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import ray

ray.init()

@ray.remote
def add(x, y):
    return x + y

# Start the task
result_ref = add.remote(2, 3)

# Get the result
result = ray.get(result_ref)
print(result)  # Prints: 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Executing Tasks:&lt;/strong&gt;&lt;br&gt;
Tasks are executed by calling the remote method and using ray.get() to retrieve the result&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Task Scheduling:&lt;/strong&gt;&lt;br&gt;
When you call a remote task, Ray's scheduler decides where to execute the task based on available resources and any specified resource requirements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Return Values:&lt;/strong&gt;&lt;br&gt;
Tasks return Ray ObjectRefs, which are futures representing the eventual result of the computation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Specification:&lt;/strong&gt;&lt;br&gt;
You can specify resource requirements for tasks&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ray.remote(num_cpus=2, num_gpus=1)
def resource_intensive_task():
    # This task requires 2 CPUs and 1 GPU
    pass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling:&lt;/strong&gt;
If a task raises an exception, it's propagated when you call ray.get()&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Parallelism in Ray
&lt;/h3&gt;

&lt;p&gt;example -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;futures = [my_task.remote(i, i) for i in range(100)]
results = ray.get(futures)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1. Parallel Execution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This code is setting up 100 tasks to run in parallel.&lt;/li&gt;
&lt;li&gt;Each &lt;code&gt;my_task.remote(i, i)&lt;/code&gt; call creates a separate task.&lt;/li&gt;
&lt;li&gt;Ray will try to run these tasks simultaneously, depending on available resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The list comprehension [my_task.remote(i, i) for i in range(100)] quickly creates 100 task invocations.&lt;/li&gt;
&lt;li&gt;Each my_task.remote(i, i) returns immediately with an ObjectRef (future).&lt;/li&gt;
&lt;li&gt;The futures list contains 100 ObjectRefs, not actual results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Resource management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ray will distribute these tasks across available workers in your Ray cluster.&lt;/li&gt;
&lt;li&gt;If you have multiple CPUs or machines, many tasks can truly run at the same time.&lt;/li&gt;
&lt;li&gt;If you have fewer resources than tasks, Ray will automatically queue and schedule them efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Getting results:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ray.get(futures)&lt;/code&gt; waits for all 100 tasks to complete and collects their results.&lt;/li&gt;
&lt;li&gt;The results are returned in the same order as the futures list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Potential speedup:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;my_task&lt;/code&gt; takes 1 second to run sequentially, doing 100 tasks might take 100 seconds.&lt;/li&gt;
&lt;li&gt;With Ray, if you have enough resources, it could potentially complete in just over 1 second.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What are Actors?
&lt;/h2&gt;

&lt;p&gt;Actors in Ray are like special workers that remember things. Think of an actor as a person with a notebook. They can do tasks and write down information to use later.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Characteristics of Actors
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Stateful: Unlike tasks, actors can remember information between calls.&lt;/li&gt;
&lt;li&gt;Persistent: They keep running and maintain their state until you specifically tell them to stop.&lt;/li&gt;
&lt;li&gt;Concurrent: Multiple actors can run at the same time, each with its own state.&lt;/li&gt;
&lt;li&gt;Single-threaded: By default, an actor processes one method call at a time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll explain the key characteristics of actors using an analogy of a personal assistant, and then provide code examples for each characteristic.&lt;/p&gt;

&lt;p&gt;Imagine an actor as a personal assistant named Alex. Here are the key characteristics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stateful (Memory)&lt;/li&gt;
&lt;li&gt;Persistent (Always available)&lt;/li&gt;
&lt;li&gt;Concurrent (Multiple assistants can work simultaneously)&lt;/li&gt;
&lt;li&gt;Single-threaded (Focuses on one task at a time)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's break these down:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Stateful (Memory):&lt;/strong&gt;&lt;br&gt;
   Analogy: Alex keeps a notebook and remembers information from previous tasks.&lt;/p&gt;

&lt;p&gt;Code example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;

   &lt;span class="nd"&gt;@ray.remote&lt;/span&gt;
   &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Assistant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
       &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks_completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

       &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks_completed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Completed task. Total tasks done: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks_completed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

   &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;alex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;do_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;  &lt;span class="c1"&gt;# Output: Completed task. Total tasks done: 1
&lt;/span&gt;   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;do_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;  &lt;span class="c1"&gt;# Output: Completed task. Total tasks done: 2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Persistent (Always available):&lt;/strong&gt;&lt;br&gt;
   Analogy: Alex doesn't go home at the end of the day; they're always ready to work.&lt;/p&gt;

&lt;p&gt;Code example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="c1"&gt;# Alex is available as long as the Ray cluster is running
&lt;/span&gt;   &lt;span class="c1"&gt;# You can keep using the same 'alex' instance
&lt;/span&gt;   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;do_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;  &lt;span class="c1"&gt;# Output: Completed task. Total tasks done: 3
&lt;/span&gt;   &lt;span class="c1"&gt;# Even after a long time...
&lt;/span&gt;   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;do_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;  &lt;span class="c1"&gt;# Output: Completed task. Total tasks done: 4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Concurrent (Multiple assistants can work simultaneously):&lt;/strong&gt;&lt;br&gt;
   Analogy: You can hire multiple assistants, each working independently.&lt;/p&gt;

&lt;p&gt;Code example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;alex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;bob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

   &lt;span class="c1"&gt;# Alex and Bob can work at the same time
&lt;/span&gt;   &lt;span class="n"&gt;alex_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;alex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;do_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;bob_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;do_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alex_task&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# Output: Completed task. Total tasks done: 1
&lt;/span&gt;   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bob_task&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;# Output: Completed task. Total tasks done: 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Single Threaded&lt;/strong&gt;&lt;br&gt;
Now, I'll explain what "single-threaded" means for actors using a simple analogy and then provide a code example.&lt;/p&gt;

&lt;p&gt;Imagine an actor as a chef in a kitchen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Single-threaded means the chef can only do one task at a time.&lt;/li&gt;
&lt;li&gt;If you ask the chef to make a sandwich and then immediately ask them to make a salad, they'll finish the sandwich first before starting the salad.&lt;/li&gt;
&lt;li&gt;The chef won't try to make both at the same time, which could lead to a mess.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, let's see this in action with a code example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@ray.remote&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Chef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_sandwich&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Starting to make a sandwich&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Pretend it takes 3 seconds to make a sandwich
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Finished making a sandwich&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sandwich ready!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_salad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Starting to make a salad&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Pretend it takes 2 seconds to make a salad
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Finished making a salad&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Salad ready!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Hire our chef
&lt;/span&gt;&lt;span class="n"&gt;chef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Chef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Ask the chef to make a sandwich and a salad
&lt;/span&gt;&lt;span class="n"&gt;sandwich_order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_sandwich&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;salad_order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;make_salad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Get the results
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sandwich_order&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salad_order&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run this code, you'll see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Starting to make a sandwich
Finished making a sandwich
Starting to make a salad
Finished making a salad
Sandwich ready!
Salad ready!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's happening here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We ask the chef to make a sandwich and then immediately ask for a salad.&lt;/li&gt;
&lt;li&gt;However, the chef (our actor) finishes the sandwich completely before starting the salad.&lt;/li&gt;
&lt;li&gt;This happens even though making a salad is quicker (2 seconds) than making a sandwich (3 seconds).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is what "single-threaded" means - the actor (our chef) handles one request at a time, in the order they were received, and finishes each task before moving to the next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an Actor
&lt;/h2&gt;

&lt;p&gt;To create an actor, you use the &lt;code&gt;@ray.remote&lt;/code&gt; decorator on a Python class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;

&lt;span class="nd"&gt;@ray.remote&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using an Actor
&lt;/h2&gt;

&lt;p&gt;Here's how you use an actor:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an actor instance:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Call methods on the actor:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;increment_ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;increment_ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Prints: 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Detailed Explanation of Actor Behavior
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;State Persistence&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;When you call &lt;code&gt;counter.increment.remote()&lt;/code&gt; multiple times, the actor remembers and updates its internal &lt;code&gt;value&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# Returns 2
&lt;/span&gt;   &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# Returns 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Concurrent Access&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple parts of your program can use the same actor concurrently.&lt;/li&gt;
&lt;li&gt;Ray ensures that method calls to a single actor are processed one at a time to avoid conflicts.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Multiple Actors&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can create multiple instances of an actor, each with its own state:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;counter1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;counter2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# Returns 1
&lt;/span&gt;   &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# Also returns 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Passing Actors&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;You can pass actor handles to tasks or other actors:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ray.remote
def use_counter(counter):
    return ray.get(counter.increment.remote())

result = ray.get(use_counter.remote(counter))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Actor Features
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Resource Specification&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;You can specify resource requirements for actors:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="nd"&gt;@ray.remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_cpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_gpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ResourceHeavyActor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
       &lt;span class="c1"&gt;# This actor requires 2 CPUs and 1 GPU
&lt;/span&gt;       &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Actor Options&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;You can set options when creating an actor instance:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;options&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my_counter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lifetime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;detached&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a named, detached actor that persists even if the creating process exits.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Async Methods&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Actors can have async methods for concurrent processing:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="nd"&gt;@ray.remote&lt;/span&gt;
   &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AsyncActor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
       &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;async_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
           &lt;span class="c1"&gt;# Do some async work
&lt;/span&gt;           &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Actor Pools&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;You can create a pool of actors for load balancing:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ray.util.actor_pool&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ActorPool&lt;/span&gt;

   &lt;span class="n"&gt;actors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
   &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ActorPool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use Cases for Actors
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Shared State&lt;/strong&gt;: When you need to maintain state across multiple calls or tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Management&lt;/strong&gt;: For managing access to a limited resource, like a database connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encapsulation&lt;/strong&gt;: To encapsulate complex logic and state in an object-oriented manner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateful Services&lt;/strong&gt;: For implementing services that need to maintain state, like a game server or a chat room.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Comparison with Tasks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tasks are stateless and good for parallel, independent work.&lt;/li&gt;
&lt;li&gt;Actors are stateful and good for maintaining information across calls.&lt;/li&gt;
&lt;li&gt;Use tasks for distributing work that doesn't need to remember anything.&lt;/li&gt;
&lt;li&gt;Use actors when you need to keep track of changing information.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Avoid creating too many actors, as each actor consumes resources.&lt;/li&gt;
&lt;li&gt;Use actors for maintaining state, not for one-off computations.&lt;/li&gt;
&lt;li&gt;Be mindful of the single-threaded nature of actors when designing your system.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;ray.get()&lt;/code&gt; judiciously to avoid blocking unnecessarily.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Ray Objects
&lt;/h1&gt;

&lt;p&gt;Ray objects are units of data stored in Ray's distributed object store. They represent the actual values or results of computations in a Ray system. These objects can be any Python data structure or object that can be serialized (converted to a format that can be stored or transmitted).&lt;/p&gt;

&lt;h3&gt;
  
  
  Key characteristics of Ray objects:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Storage: They are stored in Ray's distributed object store, which spans across the memory of all nodes in a Ray cluster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Immutability: Once created, Ray objects are immutable (cannot be changed).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference: They are accessed via ObjectRefs (also known as futures), which act like pointers or tickets to the actual data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creation: Ray objects are typically created as return values of remote functions or actor methods, or explicitly using ray.put().&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieval: The actual data of a Ray object is retrieved using ray.get() on its corresponding ObjectRef.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Distribution: Ray manages the distribution and movement of these objects across the cluster as needed for computations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Garbage collection: Ray automatically manages the lifecycle of these objects, removing them when they're no longer needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Size: They can range from small values to large datasets, with Ray optimizing storage and transfer based on size.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In essence, Ray objects are the fundamental data units in Ray's distributed computing model, allowing efficient data sharing and management across a distributed environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ray Objects vs ObjectRefs/Futures:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ray Objects are the actual data stored in Ray's object store.&lt;/li&gt;
&lt;li&gt;ObjectRefs (also called futures) are references to these Ray Objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ray Object: The actual "thing" (data, result of a computation, etc.)&lt;/li&gt;
&lt;li&gt;ObjectRef/Future: A ticket or reference that lets you access that "thing"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a simple analogy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ray Object: A book in a library&lt;/li&gt;
&lt;li&gt;ObjectRef: The library card that tells you where to find the book&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you call a remote function, it creates a Ray Object (the result) in Ray's object store.&lt;/li&gt;
&lt;li&gt;You get back an ObjectRef, which is a reference to that Ray Object.&lt;/li&gt;
&lt;li&gt;You use ray.get() on the ObjectRef to retrieve the actual data (the Ray Object).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this distinction matters:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It allows Ray to manage data efficiently across a distributed system.&lt;/li&gt;
&lt;li&gt;Ray can move the actual data (Ray Objects) around as needed without you having to manage it.&lt;/li&gt;
&lt;li&gt;You work with lightweight references (ObjectRefs) instead of potentially large data objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ObjectRefs (or futures) are not the Ray Objects themselves, but rather references to Ray Objects. This distinction is crucial for understanding how Ray manages data in a distributed environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ray.put()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now, let's break down what &lt;code&gt;ray.put()&lt;/code&gt; does and why it's useful:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Purpose of ray.put():&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It explicitly puts an object into Ray's object store.&lt;/li&gt;
&lt;li&gt;Returns an ObjectRef (a reference to the stored object).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When to use ray.put():&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you have data you want to share across multiple tasks or actors.&lt;/li&gt;
&lt;li&gt;For large objects that you'll use multiple times, to avoid repeated serialization.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example 1: Simple Python object&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We store a simple list using &lt;code&gt;ray.put()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We get an ObjectRef back, which we can use to retrieve the data later.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="c1"&gt;# Example 1: Storing a simple Python object
&lt;/span&gt;    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;data_ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ObjectRef for data:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;retrieved_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Retrieved data:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieved_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example 2: Large NumPy array&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We store a large NumPy array.&lt;/li&gt;
&lt;li&gt;This is particularly useful for big data that you don't want to keep copying.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;     &lt;span class="c1"&gt;# Example 2: Storing a large NumPy array
&lt;/span&gt;    &lt;span class="n"&gt;large_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;array_ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;large_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ObjectRef for large array:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;array_ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;retrieved_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array_ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Shape of retrieved array:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieved_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example 3: Using in a remote function&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We pass the ObjectRef to a remote function.&lt;/li&gt;
&lt;li&gt;The function can then retrieve the data using &lt;code&gt;ray.get()&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;

    &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Define the remote function
&lt;/span&gt;    &lt;span class="nd"&gt;@ray.remote&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# No need to use ray.get() here, 'data' is already the actual data
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Create some data
&lt;/span&gt;    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Put the data in the object store and get an ObjectRef
&lt;/span&gt;    &lt;span class="n"&gt;data_ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Call the remote function with the ObjectRef
&lt;/span&gt;    &lt;span class="n"&gt;result_ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;process_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Get the result
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sum of data:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;ray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key points to remember:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use ray.put() to store data in Ray's object store. This returns an ObjectRef.&lt;/li&gt;
&lt;li&gt;Pass this ObjectRef to remote functions.&lt;/li&gt;
&lt;li&gt;Inside remote functions, you receive the actual data, not the ObjectRef. So you don't need to use ray.get() there.&lt;/li&gt;
&lt;li&gt;Use ray.get() only when you want to retrieve results from a remote function call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This pattern ensures that:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data is properly stored in Ray's object store.&lt;/li&gt;
&lt;li&gt;Remote functions can efficiently access the data.&lt;/li&gt;
&lt;li&gt;You're working with ObjectRefs when appropriate.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Benefits of using ray.put():&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Efficiency: Avoid repeatedly serializing large objects.&lt;/li&gt;
&lt;li&gt;Sharing: Easy to share data across multiple tasks or actors.&lt;/li&gt;
&lt;li&gt;Memory management: Ray manages the object's lifecycle in the distributed setting.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Things to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Objects stored with &lt;code&gt;ray.put()&lt;/code&gt; are immutable.&lt;/li&gt;
&lt;li&gt;Ray will automatically garbage collect objects when they're no longer needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By using &lt;code&gt;ray.put()&lt;/code&gt;, you're explicitly telling Ray to manage this data in its object store, which can lead to more efficient distributed computations, especially when dealing with large datasets or objects that are used multiple times.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
