.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "generated/examples/ping_pong.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_generated_examples_ping_pong.py: Monarch Actor API: Ping Pong ==================================== This example demonstrates the basics of Monarch's Actor/endpoint API, which provides a generic interface for distributed computing. We'll cover: - Creating and spawning actors in process meshes - Calling endpoints on actors - Actor-to-actor communication with a ping-pong example .. GENERATED FROM PYTHON SOURCE LINES 20-25 Hello World ----------- Actors are spawned in Process meshes via the `monarch.actor` API. For those familiar with distributed systems, it can be helpful to think of each Actor as a server with endpoints that can be called. .. GENERATED FROM PYTHON SOURCE LINES 25-40 .. code-block:: default from monarch.actor import Actor, current_rank, endpoint, this_host NUM_ACTORS = 4 class ToyActor(Actor): def __init__(self): self.rank = current_rank().rank @endpoint def hello_world(self, msg): print(f"Identity: {self.rank}, {msg=}") .. GENERATED FROM PYTHON SOURCE LINES 41-42 Note: Meshes can be also be created on different nodes, but we're ignoring that in this example .. GENERATED FROM PYTHON SOURCE LINES 42-48 .. code-block:: default local_proc_mesh = this_host().spawn_procs(per_host={"gpus": NUM_ACTORS}) # This spawns 4 instances of 'ToyActor' toy_actor = local_proc_mesh.spawn("toy_actor", ToyActor) .. GENERATED FROM PYTHON SOURCE LINES 49-50 Once actors are spawned, we can call all of them simultaneously with `Actor.endpoint.call` .. GENERATED FROM PYTHON SOURCE LINES 50-54 .. code-block:: default toy_actor.hello_world.call("hey there, from script!!").get() .. GENERATED FROM PYTHON SOURCE LINES 55-56 We can also specify a single actor using the 'slice' API .. GENERATED FROM PYTHON SOURCE LINES 56-69 .. code-block:: default futures = [] for idx in range(NUM_ACTORS): actor_instance = toy_actor.slice(gpus=idx) futures.append( actor_instance.hello_world.call_one(f"Here's an arbitrary unique value: {idx}") ) # Wait for all futures to complete for fut in futures: fut.get() .. GENERATED FROM PYTHON SOURCE LINES 70-74 Ping Pong --------- Not only is it possible to call endpoints from a 'main' function, but actors have the useful property of being able to communicate with one another. .. GENERATED FROM PYTHON SOURCE LINES 74-97 .. code-block:: default class ExampleActor(Actor): def __init__(self, actor_name): self.actor_name = actor_name @endpoint def init(self, other_actor): self.other_actor = other_actor self.other_actor_pair = other_actor.slice(**current_rank()) self.identity = current_rank().rank @endpoint def send(self, msg): self.other_actor_pair.recv.call( f"Sender ({self.actor_name}:{self.identity}) {msg=}" ).get() @endpoint def recv(self, msg): print(f"Pong!, Receiver ({self.actor_name}:{self.identity}) received msg {msg}") .. GENERATED FROM PYTHON SOURCE LINES 98-99 Spawn two different Actors in different meshes, with two instances each .. GENERATED FROM PYTHON SOURCE LINES 99-115 .. code-block:: default local_mesh_0 = this_host().spawn_procs(per_host={"gpus": 2}) actor_0 = local_mesh_0.spawn( "actor_0", ExampleActor, "actor_0", # this arg is passed to ExampleActor.__init__ ) local_mesh_1 = this_host().spawn_procs(per_host={"gpus": 2}) actor_1 = local_mesh_1.spawn( "actor_1", ExampleActor, "actor_1", # this arg is passed to ExampleActor.__init__ ) .. GENERATED FROM PYTHON SOURCE LINES 116-117 Initialize each actor with references to each other .. GENERATED FROM PYTHON SOURCE LINES 117-122 .. code-block:: default actor_0.init.call(actor_1).get() actor_1.init.call(actor_0).get() .. GENERATED FROM PYTHON SOURCE LINES 123-124 Send messages between actors .. GENERATED FROM PYTHON SOURCE LINES 124-132 .. code-block:: default # Actor 0 sends to Actor 1 actor_0.send.call("Ping").get() # Actor 1 sends to Actor 0 actor_1.send.call("Ping").get() print("Example completed successfully!") .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.000 seconds) .. _sphx_glr_download_generated_examples_ping_pong.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: ping_pong.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: ping_pong.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_