Skip to content

Commit

Permalink
[Doc] Revamp ray core design patterns doc [12/n]: global variables (#…
Browse files Browse the repository at this point in the history
…29124)

Signed-off-by: Jiajun Yao <[email protected]>
Signed-off-by: Stephanie Wang <[email protected]>
Co-authored-by: Stephanie Wang <[email protected]>
  • Loading branch information
jjyao and stephanie-wang authored Oct 7, 2022
1 parent 07692ab commit 366f2a9
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 69 deletions.
51 changes: 51 additions & 0 deletions doc/source/ray-core/doc_code/anti_pattern_global_variables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# __anti_pattern_start__
import ray

ray.init()

global_var = 3


@ray.remote
class Actor:
def f(self):
return global_var + 3


actor = Actor.remote()
global_var = 4
# This returns 6, not 7. It is because the value change of global_var
# inside a driver is not reflected to the actor
# because they are running in different processes.
assert ray.get(actor.f.remote()) == 6
# __anti_pattern_end__


# __better_approach_start__
@ray.remote
class GlobalVarActor:
def __init__(self):
self.global_var = 3

def set_global_var(self, var):
self.global_var = var

def get_global_var(self):
return self.global_var


@ray.remote
class Actor:
def __init__(self, global_var_actor):
self.global_var_actor = global_var_actor

def f(self):
return ray.get(self.global_var_actor.get_global_var.remote()) + 3


global_var_actor = GlobalVarActor.remote()
actor = Actor.remote(global_var_actor)
ray.get(global_var_actor.set_global_var.remote(4))
# This returns 7 correctly.
assert ray.get(actor.f.remote()) == 7
# __better_approach_end__
30 changes: 30 additions & 0 deletions doc/source/ray-core/patterns/global-variables.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Anti-pattern: Using global variables to share state between tasks and actors
============================================================================

**TLDR:** Don't use global variables to share state with tasks and actors. Instead, encapsulate the global variables in an actor and pass the actor handle to other tasks and actors.

Ray drivers, tasks and actors are running in
different processes, so they don’t share the same address space.
This means that if you modify global variables
in one process, changes are not reflected in other processes.

The solution is to use an actor's instance variables to hold the global state and pass the actor handle to places where the state needs to be modified or accessed.
Note that using class variables to manage state between instances of the same class is not supported.
Each actor instance is instantiated in its own process, so each actor will have its own copy of the class variables.

Code example
------------

**Anti-pattern:**

.. literalinclude:: ../doc_code/anti_pattern_global_variables.py
:language: python
:start-after: __anti_pattern_start__
:end-before: __anti_pattern_end__

**Better approach:**

.. literalinclude:: ../doc_code/anti_pattern_global_variables.py
:language: python
:start-after: __better_approach_start__
:end-before: __better_approach_end__
1 change: 1 addition & 0 deletions doc/source/ray-core/patterns/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ This section is a collection of common design patterns and anti-patterns for wri
redefine-task-actor-loop
pass-large-arg-by-value
closure-capture-large-objects
global-variables
68 changes: 0 additions & 68 deletions doc/source/ray-core/tasks/patterns/global-variables.rst

This file was deleted.

1 change: 0 additions & 1 deletion doc/source/ray-core/tasks/patterns/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@ You may also be interested in visiting the design patterns section for :ref:`act

tree-of-tasks
map-reduce
global-variables

0 comments on commit 366f2a9

Please sign in to comment.