# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-# This script generates a specific deployment file for the Bittorrent example.
-# It assumes that the platform will be a cluster.
-# Usage: python generate.py nb_nodes nb_bits end_date percentage
-# Example: python generate.py 10000 5000
+"""
+This script generates a specific deployment file for the Bittorrent example.
+It assumes that the platform will be a cluster.
+Usage: python generate.py nb_nodes nb_bits end_date percentage
+Example: python generate.py 10000 5000
+"""
import sys
import random
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
+"""
+Usage: python generate.py nb_nodes nb_bits end_date > deployment_file.xml
+"""
+
import sys
import random
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-# This script generates a specific deployment file for the Chord example.
-# It assumes that the platform will be a cluster.
-# Usage: python generate.py nb_nodes nb_bits end_date
-# Example: python generate.py 100000 32 1000
+"""
+This script generates a specific deployment file for the Chord example.
+It assumes that the platform will be a cluster.
+Usage: python generate.py nb_nodes nb_bits end_date
+Example: python generate.py 100000 32 1000
+"""
import sys
import random
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
+"""
+Usage: python generate.py nb_nodes nb_bits end_date > deployment_file.xml
+"""
+
import sys
import random
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-# This script generates a specific deployment file for the Bittorrent example.
-# It assumes that the platform will be a cluster.
-# Usage: python generate.py nb_nodes nb_bits end_date percentage
-# Example: python generate.py 10000 5000
+"""
+This script generates a specific deployment file for the Bittorrent example.
+It assumes that the platform will be a cluster.
+Usage: python generate.py nb_nodes nb_bits end_date percentage
+Example: python generate.py 10000 5000
+"""
import sys
import random
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-# This example shows how to declare and start your actors.
-#
-# The first step is to declare the code of your actors (what they do exactly does not matter to this example) and then
-# you ask SimGrid to start your actors. There is three ways of doing so:
-# - Directly, by instantiating your actor as parameter to Actor::create()
-# - By first registering your actors before instantiating it;
-# - Through the deployment file.
-#
-# This example shows all these solutions, even if you obviously should use only one of these solutions to start your
-# actors. The most advised solution is to use a deployment file, as it creates a clear separation between your
-# application and the settings to test it. This is a better scientific methodology. Actually, starting an actor with
-# Actor.create() is mostly useful to start an actor from another actor.
+"""
+This example shows how to declare and start your actors.
+
+The first step is to declare the code of your actors (what they do exactly does not matter to this example) and then
+you ask SimGrid to start your actors. There is three ways of doing so:
+- Directly, by instantiating your actor as parameter to Actor::create()
+- By first registering your actors before instantiating it;
+- Through the deployment file.
+
+This example shows all these solutions, even if you obviously should use only one of these solutions to start your
+actors. The most advised solution is to use a deployment file, as it creates a clear separation between your
+application and the settings to test it. This is a better scientific methodology. Actually, starting an actor with
+Actor.create() is mostly useful to start an actor from another actor.
+"""
-from simgrid import Actor, Engine, Host, Mailbox, this_actor
import sys
+from simgrid import Actor, Engine, Host, Mailbox, this_actor
def receiver(mailbox_name):
# This program is free software you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, Host, this_actor
+"""
+Usage: actor-daemon.py platform_file [other parameters]
+"""
+
import sys
+from simgrid import Actor, Engine, Host, this_actor
def worker():
# This program is free software you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, Host, this_actor
+"""
+Usage: actor-join.py platform_file [other parameters]
+"""
+
import sys
+from simgrid import Actor, Engine, Host, this_actor
def sleeper():
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, Host, this_actor
+"""
+Usage: actor-kill.py platform_file [other parameters]
+"""
+
import sys
+from simgrid import Actor, Engine, Host, this_actor
def victim_a_fun():
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-# This Python file acts as the foil to the corresponding XML file, where the
-# action takes place: Actors are started and stopped at predefined time
+"""
+This Python file acts as the foil to the corresponding XML file, where the
+action takes place: Actors are started and stopped at predefined time
+"""
-from simgrid import Engine, this_actor
import sys
+from simgrid import Engine, this_actor
class Sleeper:
"""This actor just sleeps until termination"""
- def __init__(self, *args):
+ def __init__(self):
this_actor.on_exit(lambda: this_actor.info("Exiting now (done sleeping or got killed)."))
def __call__(self):
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-# This example demonstrate the actor migrations.
-#
-# The worker actor first move by itself, and then start an execution.
-# During that execution, the monitor migrates the worker, that wakes up on another host.
-# The execution was of the right amount of flops to take exactly 5 seconds on the first host
-# and 5 other seconds on the second one, so it stops after 10 seconds.
-#
-# Then another migration is done by the monitor while the worker is suspended.
-#
-# Note that worker() takes an uncommon set of parameters,
-# and that this is perfectly accepted by create().
+"""
+This example demonstrate the actor migrations.
+
+The worker actor first move by itself, and then start an execution.
+During that execution, the monitor migrates the worker, that wakes up on another host.
+The execution was of the right amount of flops to take exactly 5 seconds on the first host
+and 5 other seconds on the second one, so it stops after 10 seconds.
+
+Then another migration is done by the monitor while the worker is suspended.
+
+Note that worker() takes an uncommon set of parameters,
+and that this is perfectly accepted by create().
+"""
-from simgrid import Actor, Engine, Host, this_actor
import sys
+from simgrid import Actor, Engine, Host, this_actor
def worker(first_host, second_host):
# This program is free software you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, this_actor
+"""
+Usage: actor-suspend.py platform_file [other parameters]
+"""
+
import sys
+from simgrid import Actor, Engine, this_actor
def lazy_guy():
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, Host, this_actor
-import sys
+"""
+This example does not much: It just spans over-polite actor that yield a large amount
+of time before ending.
-# This example does not much: It just spans over-polite actor that yield a large amount
-# of time before ending.
-#
-# This serves as an example for the simgrid.yield() function, with which an actor can request
-# to be rescheduled after the other actor that are ready at the current timestamp.
-#
-# It can also be used to benchmark our context-switching mechanism.
+This serves as an example for the simgrid.yield() function, with which an actor can request
+to be rescheduled after the other actor that are ready at the current timestamp.
+It can also be used to benchmark our context-switching mechanism.
+"""
-def yielder (number_of_yields):
+import sys
+from simgrid import Actor, Engine, Host, this_actor
+
+def yielder(number_of_yields):
for _ in range(number_of_yields):
this_actor.yield_()
this_actor.info("I yielded {:d} times. Goodbye now!".format(number_of_yields))
e = Engine(sys.argv)
e.load_platform(sys.argv[1]) # Load the platform description
-
+
Actor.create("yielder", Host.by_name("Tremblay"), yielder, 10)
Actor.create("yielder", Host.by_name("Ruby"), yielder, 15)
-# Copyright (c) 2010-2022. The SimGrid Team. All rights reserved.
+# Copyright (c) 2010-2022. The SimGrid Team. All rights reserved.
# This program is free software; you can redistribute it and/or modify it
-# under the terms of the license (GNU LGPL) which comes with this package.
+# under the terms of the license (GNU LGPL) which comes with this package.
+"""
# ##################################################################################
# Take this tutorial online: https://simgrid.org/doc/latest/Tutorial_Algorithms.html
# ##################################################################################
+"""
-from simgrid import Engine, Mailbox, this_actor
import sys
+from simgrid import Engine, Mailbox, this_actor
# master-begin
def master(*args):
- assert len(args) > 3, f"Actor master requires 3 parameters plus the workers' names, but got {len(args)}"
- tasks_count = int(args[0])
- compute_cost = int(args[1])
- communicate_cost = int(args[2])
- workers = []
- for i in range(3, len(args)):
- workers.append(Mailbox.by_name(args[i]))
- this_actor.info(f"Got {len(workers)} workers and {tasks_count} tasks to process")
-
- for i in range(tasks_count): # For each task to be executed:
- # - Select a worker in a round-robin way
- mailbox = workers[i % len(workers)]
-
- # - Send the computation amount to the worker
- if (tasks_count < 10000 or (tasks_count < 100000 and i % 10000 == 0) or i % 100000 == 0):
- this_actor.info(f"Sending task {i} of {tasks_count} to mailbox '{mailbox.name}'")
- mailbox.put(compute_cost, communicate_cost)
-
- this_actor.info("All tasks have been dispatched. Request all workers to stop.")
- for i in range (len(workers)):
- # The workers stop when receiving a negative compute_cost
- mailbox = workers[i]
- mailbox.put(-1, 0)
+ assert len(args) > 3, f"Actor master requires 3 parameters plus the workers' names, but got {len(args)}"
+ tasks_count = int(args[0])
+ compute_cost = int(args[1])
+ communicate_cost = int(args[2])
+ workers = []
+ for i in range(3, len(args)):
+ workers.append(Mailbox.by_name(args[i]))
+ this_actor.info(f"Got {len(workers)} workers and {tasks_count} tasks to process")
+
+ for i in range(tasks_count): # For each task to be executed:
+ # - Select a worker in a round-robin way
+ mailbox = workers[i % len(workers)]
+
+ # - Send the computation amount to the worker
+ if (tasks_count < 10000 or (tasks_count < 100000 and i % 10000 == 0) or i % 100000 == 0):
+ this_actor.info(f"Sending task {i} of {tasks_count} to mailbox '{mailbox.name}'")
+ mailbox.put(compute_cost, communicate_cost)
+
+ this_actor.info("All tasks have been dispatched. Request all workers to stop.")
+ for mailbox in workers:
+ # The workers stop when receiving a negative compute_cost
+ mailbox.put(-1, 0)
# master-end
# worker-begin
def worker(*args):
- assert len(args) == 0, "The worker expects to not get any argument"
-
- mailbox = Mailbox.by_name(this_actor.get_host().name)
- done = False
- while not done:
- compute_cost = mailbox.get()
- if compute_cost > 0: # If compute_cost is valid, execute a computation of that cost
- this_actor.execute(compute_cost)
- else: # Stop when receiving an invalid compute_cost
- done = True
-
- this_actor.info("Exiting now.")
+ assert not args, "The worker expects to not get any argument"
+
+ mailbox = Mailbox.by_name(this_actor.get_host().name)
+ done = False
+ while not done:
+ compute_cost = mailbox.get()
+ if compute_cost > 0: # If compute_cost is valid, execute a computation of that cost
+ this_actor.execute(compute_cost)
+ else: # Stop when receiving an invalid compute_cost
+ done = True
+
+ this_actor.info("Exiting now.")
# worker-end
# main-begin
e.register_actor("worker", worker)
# Load the platform description and then deploy the application
- e.load_platform(sys.argv[1])
+ e.load_platform(sys.argv[1])
e.load_deployment(sys.argv[2])
# Run the simulation
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-# This example shows how to build a torus cluster with multi-core hosts.
-#
-# However, each leaf in the torus is a StarZone, composed of several CPUs
-#
-# Each actor runs in a specific CPU. One sender broadcasts a message to all receivers.
+"""
+This example shows how to build a torus cluster with multi-core hosts.
+
+However, each leaf in the torus is a StarZone, composed of several CPUs
+
+Each actor runs in a specific CPU. One sender broadcasts a message to all receivers.
+"""
-import simgrid
import sys
import typing
+import simgrid
class Sender:
#####################################################################################################
-def create_hostzone(zone: simgrid.NetZone, coord: typing.List[int], ident: int) -> typing.Tuple[simgrid.NetPoint, simgrid.NetPoint]:
- """
+def create_hostzone(zone: simgrid.NetZone, coord: typing.List[int], ident: int) -> typing.Tuple[simgrid.NetPoint,
+ simgrid.NetPoint]:
+ r"""
Callback to set a cluster leaf/element
In our example, each leaf if a StarZone, composed of 8 CPUs.
link = host_zone.create_split_duplex_link("link-" + cpu_name, link_bw)
link.set_latency(link_lat).seal()
# connecting CPU to outer world
- host_zone.add_route(host.netpoint, None, None, None, [
- simgrid.LinkInRoute(link, simgrid.LinkInRoute.Direction.UP)], True)
+ host_zone.add_route(host.netpoint, None, None, None,
+ [simgrid.LinkInRoute(link, simgrid.LinkInRoute.Direction.UP)], True)
# seal newly created netzone
host_zone.seal()
The coord parameter depends on the cluster being created:
- Torus: Direct translation of the Torus' dimensions, e.g. (0, 0, 0) for a 3-D Torus
- - Fat-Tree: A pair (level in the tree, ident), e.g. (0, 0) for first leaf in the tree and (1,0) for the first switch at
- level 1.
+ - Fat-Tree: A pair (level in the tree, ident), e.g. (0, 0) for first leaf in the tree and (1,0) for the first switch
+ at level 1.
- Dragonfly: a tuple (group, chassis, blades/routers, nodes), e.g. (0, 0, 0, 0) for first node in the cluster. To
identify the router inside a (group, chassis, blade), we use MAX_UINT in the last parameter (e.g. 0, 0, 0,
4294967295).
Cluster</a>
"""
# create the torus cluster, 10Gbs link between elements in the cluster
- simgrid.NetZone.create_torus_zone("cluster", None, [2, 2, 2], simgrid.ClusterCallbacks(create_hostzone, None, create_limiter), 10e9, 10e-6,
+ simgrid.NetZone.create_torus_zone("cluster", None, [2, 2, 2],
+ simgrid.ClusterCallbacks(create_hostzone, None, create_limiter), 10e9, 10e-6,
simgrid.Link.SharingPolicy.SPLITDUPLEX).seal()
#####################################################################################################
def create_fat_tree_cluster():
- """
+ r"""
Creates a Fat-Tree cluster
Creates a Fat-Tree cluster with 2 levels and 6 nodes
Cluster</a>
"""
# create the fat tree cluster, 10Gbs link between elements in the cluster
- simgrid.NetZone.create_fatTree_zone("cluster", None, simgrid.FatTreeParams(2, [2, 3], [1, 2], [1, 1]), simgrid.ClusterCallbacks(create_hostzone, None, create_limiter), 10e9,
- 10e-6, simgrid.Link.SharingPolicy.SPLITDUPLEX).seal()
+ simgrid.NetZone.create_fatTree_zone("cluster", None, simgrid.FatTreeParams(2, [2, 3], [1, 2], [1, 1]),
+ simgrid.ClusterCallbacks(create_hostzone, None, create_limiter), 10e9, 10e-6,
+ simgrid.Link.SharingPolicy.SPLITDUPLEX).seal()
#####################################################################################################
def create_dragonfly_cluster():
- """
+ r"""
Creates a Dragonfly cluster
Creates a Dragonfly cluster with 2 groups and 16 nodes
Cluster</a>
"""
# create the dragonfly cluster, 10Gbs link between elements in the cluster
- simgrid.NetZone.create_dragonfly_zone("cluster", None, simgrid.DragonflyParams([2, 2], [2, 1], [2, 2], 2), simgrid.ClusterCallbacks(
- create_hostzone, None, create_limiter), 10e9, 10e-6, simgrid.Link.SharingPolicy.SPLITDUPLEX).seal()
+ simgrid.NetZone.create_dragonfly_zone("cluster", None, simgrid.DragonflyParams([2, 2], [2, 1], [2, 2], 2),
+ simgrid.ClusterCallbacks(create_hostzone, None, create_limiter), 10e9, 10e-6,
+ simgrid.Link.SharingPolicy.SPLITDUPLEX).seal()
###################################################################################################
-if __name__ == '__main__':
+def main():
e = simgrid.Engine(sys.argv)
platform = sys.argv[1]
# runs the simulation
e.run()
+
+if __name__ == '__main__':
+ main()
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, Host, Mailbox, this_actor
-import sys
+"""
+This example shows how to use simgrid::s4u::this_actor::wait() to wait for a given communication.
-# This example shows how to use simgrid::s4u::this_actor::wait() to wait for a given communication.
-#
-# As for the other asynchronous examples, the sender initiate all the messages it wants to send and
-# pack the resulting simgrid::s4u::CommPtr objects in a vector. All messages thus occurs concurrently.
-#
-# The sender then loops until there is no ongoing communication.
+As for the other asynchronous examples, the sender initiate all the messages it wants to send and
+pack the resulting simgrid::s4u::CommPtr objects in a vector. All messages thus occurs concurrently.
+
+The sender then loops until there is no ongoing communication.
+"""
+
+import sys
+from simgrid import Actor, Engine, Host, Mailbox, this_actor
def sender(messages_count, msg_size, receivers_count):
- # List in which we store all ongoing communications
- pending_comms = []
+ # List in which we store all ongoing communications
+ pending_comms = []
- # Vector of the used mailboxes
- mboxes = [Mailbox.by_name("receiver-{:d}".format(i)) for i in range(0, receivers_count)]
+ # Vector of the used mailboxes
+ mboxes = [Mailbox.by_name("receiver-{:d}".format(i)) for i in range(0, receivers_count)]
- # Start dispatching all messages to receivers, in a round robin fashion
- for i in range(0, messages_count):
- content = "Message {:d}".format(i)
- mbox = mboxes[i % receivers_count]
+ # Start dispatching all messages to receivers, in a round robin fashion
+ for i in range(0, messages_count):
+ content = "Message {:d}".format(i)
+ mbox = mboxes[i % receivers_count]
- this_actor.info("Send '{:s}' to '{:s}'".format(content, str(mbox)))
+ this_actor.info("Send '{:s}' to '{:s}'".format(content, str(mbox)))
- # Create a communication representing the ongoing communication, and store it in pending_comms
- comm = mbox.put_async(content, msg_size)
- pending_comms.append(comm)
+ # Create a communication representing the ongoing communication, and store it in pending_comms
+ comm = mbox.put_async(content, msg_size)
+ pending_comms.append(comm)
- # Start sending messages to let the workers know that they should stop
- for i in range(0, receivers_count):
- mbox = mboxes[i]
- this_actor.info("Send 'finalize' to '{:s}'".format(str(mbox)))
- comm = mbox.put_async("finalize", 0)
- pending_comms.append(comm)
+ # Start sending messages to let the workers know that they should stop
+ for i in range(0, receivers_count):
+ mbox = mboxes[i]
+ this_actor.info("Send 'finalize' to '{:s}'".format(str(mbox)))
+ comm = mbox.put_async("finalize", 0)
+ pending_comms.append(comm)
- this_actor.info("Done dispatching all messages")
+ this_actor.info("Done dispatching all messages")
- # Now that all message exchanges were initiated, wait for their completion, in order of creation.
- for comm in pending_comms:
- comm.wait()
- this_actor.info("Goodbye now!")
+ # Now that all message exchanges were initiated, wait for their completion, in order of creation.
+ for comm in pending_comms:
+ comm.wait()
+ this_actor.info("Goodbye now!")
-def receiver(id):
- mbox = Mailbox.by_name("receiver-{:d}".format(id))
- this_actor.info("Wait for my first message")
- while True:
- received = mbox.get()
- this_actor.info("I got a '{:s}'.".format(received))
- if received == "finalize":
- break # If it's a finalize message, we're done.
+def receiver(my_id):
+ mbox = Mailbox.by_name("receiver-{:d}".format(my_id))
+ this_actor.info("Wait for my first message")
+ while True:
+ received = mbox.get()
+ this_actor.info("I got a '{:s}'.".format(received))
+ if received == "finalize":
+ break # If it's a finalize message, we're done.
if __name__ == '__main__':
Actor.create("sender", Host.by_name("Tremblay"), sender, 3, 50000000, 1)
Actor.create("receiver", Host.by_name("Ruby"), receiver, 0)
-
+
e.run()
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor,Comm, Engine, Host, Mailbox, this_actor
-import sys
+"""
+This example shows how to block on the completion of a set of communications.
-# This example shows how to block on the completion of a set of communications.
-#
-# As for the other asynchronous examples, the sender initiate all the messages it wants to send and
-# pack the resulting simgrid.Comm objects in a list. All messages thus occur concurrently.
-#
-# The sender then blocks until all ongoing communication terminate, using simgrid.Comm.wait_all()
+As for the other asynchronous examples, the sender initiate all the messages it wants to send and
+pack the resulting simgrid.Comm objects in a list. All messages thus occur concurrently.
+
+The sender then blocks until all ongoing communication terminate, using simgrid.Comm.wait_all()
+"""
+
+import sys
+from simgrid import Actor, Comm, Engine, Host, Mailbox, this_actor
def sender(messages_count, msg_size, receivers_count):
- # List in which we store all ongoing communications
- pending_comms = []
+ # List in which we store all ongoing communications
+ pending_comms = []
- # Vector of the used mailboxes
- mboxes = [Mailbox.by_name("receiver-{:d}".format(i))
- for i in range(0, receivers_count)]
+ # Vector of the used mailboxes
+ mboxes = [Mailbox.by_name("receiver-{:d}".format(i))
+ for i in range(0, receivers_count)]
- # Start dispatching all messages to receivers, in a round robin fashion
- for i in range(0, messages_count):
- content = "Message {:d}".format(i)
- mbox = mboxes[i % receivers_count]
+ # Start dispatching all messages to receivers, in a round robin fashion
+ for i in range(0, messages_count):
+ content = "Message {:d}".format(i)
+ mbox = mboxes[i % receivers_count]
- this_actor.info("Send '{:s}' to '{:s}'".format(content, str(mbox)))
+ this_actor.info("Send '{:s}' to '{:s}'".format(content, str(mbox)))
- # Create a communication representing the ongoing communication, and store it in pending_comms
- comm = mbox.put_async(content, msg_size)
- pending_comms.append(comm)
+ # Create a communication representing the ongoing communication, and store it in pending_comms
+ comm = mbox.put_async(content, msg_size)
+ pending_comms.append(comm)
- # Start sending messages to let the workers know that they should stop
- for i in range(0, receivers_count):
- mbox = mboxes[i]
- this_actor.info("Send 'finalize' to '{:s}'".format(str(mbox)))
- comm = mbox.put_async("finalize", 0)
- pending_comms.append(comm)
+ # Start sending messages to let the workers know that they should stop
+ for i in range(0, receivers_count):
+ mbox = mboxes[i]
+ this_actor.info("Send 'finalize' to '{:s}'".format(str(mbox)))
+ comm = mbox.put_async("finalize", 0)
+ pending_comms.append(comm)
- this_actor.info("Done dispatching all messages")
+ this_actor.info("Done dispatching all messages")
- # Now that all message exchanges were initiated, wait for their completion in one single call
- Comm.wait_all(pending_comms)
+ # Now that all message exchanges were initiated, wait for their completion in one single call
+ Comm.wait_all(pending_comms)
- this_actor.info("Goodbye now!")
+ this_actor.info("Goodbye now!")
-def receiver(id):
- mbox = Mailbox.by_name("receiver-{:d}".format(id))
+def receiver(my_id):
+ mbox = Mailbox.by_name("receiver-{:d}".format(my_id))
this_actor.info("Wait for my first message")
while True:
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Comm, Engine, Host, Mailbox, this_actor
-import sys
+"""
+This example shows how to block on the completion of a set of communications.
-# This example shows how to block on the completion of a set of communications.
-#
-# As for the other asynchronous examples, the sender initiate all the messages it wants to send and
-# pack the resulting simgrid.Comm objects in a list. All messages thus occur concurrently.
-#
-# The sender then loops until there is no ongoing communication. Using wait_any() ensures that the sender
-# will notice events as soon as they occur even if it does not follow the order of the container.
-#
-# Here, finalize messages will terminate earlier because their size is 0, so they travel faster than the
-# other messages of this application. As expected, the trace shows that the finalize of worker 1 is
-# processed before 'Message 5' that is sent to worker 0.
+As for the other asynchronous examples, the sender initiate all the messages it wants to send and
+pack the resulting simgrid.Comm objects in a list. All messages thus occur concurrently.
+
+The sender then loops until there is no ongoing communication. Using wait_any() ensures that the sender
+will notice events as soon as they occur even if it does not follow the order of the container.
+
+Here, finalize messages will terminate earlier because their size is 0, so they travel faster than the
+other messages of this application. As expected, the trace shows that the finalize of worker 1 is
+processed before 'Message 5' that is sent to worker 0.
+"""
+
+import sys
+from simgrid import Actor, Comm, Engine, Host, Mailbox, this_actor
def sender(messages_count, msg_size, receivers_count):
- # List in which we store all ongoing communications
- pending_comms = []
-
- # Vector of the used mailboxes
- mboxes = [Mailbox.by_name("receiver-{:d}".format(i))
- for i in range(0, receivers_count)]
-
- # Start dispatching all messages to receivers, in a round robin fashion
- for i in range(0, messages_count):
- content = "Message {:d}".format(i)
- mbox = mboxes[i % receivers_count]
-
- this_actor.info("Send '{:s}' to '{:s}'".format(content, str(mbox)))
-
- # Create a communication representing the ongoing communication, and store it in pending_comms
- comm = mbox.put_async(content, msg_size)
- pending_comms.append(comm)
-
- # Start sending messages to let the workers know that they should stop
- for i in range(0, receivers_count):
- mbox = mboxes[i]
- this_actor.info("Send 'finalize' to '{:s}'".format(str(mbox)))
- comm = mbox.put_async("finalize", 0)
- pending_comms.append(comm)
-
- this_actor.info("Done dispatching all messages")
-
- # Now that all message exchanges were initiated, wait for their completion, in order of completion.
- #
- # This loop waits for first terminating message with wait_any() and remove it with del, until all comms are
- # terminated.
- # Even in this simple example, the pending comms do not terminate in the exact same order of creation.
- while pending_comms:
- changed_pos = Comm.wait_any(pending_comms)
- del pending_comms[changed_pos]
- if (changed_pos != 0):
- this_actor.info(
- "Remove the {:d}th pending comm: it terminated earlier than another comm that was initiated first.".format(changed_pos))
-
- this_actor.info("Goodbye now!")
-
-
-def receiver(id):
- mbox = Mailbox.by_name("receiver-{:d}".format(id))
+ # List in which we store all ongoing communications
+ pending_comms = []
+
+ # Vector of the used mailboxes
+ mboxes = [Mailbox.by_name("receiver-{:d}".format(i))
+ for i in range(0, receivers_count)]
+
+ # Start dispatching all messages to receivers, in a round robin fashion
+ for i in range(0, messages_count):
+ content = "Message {:d}".format(i)
+ mbox = mboxes[i % receivers_count]
+
+ this_actor.info("Send '{:s}' to '{:s}'".format(content, str(mbox)))
+
+ # Create a communication representing the ongoing communication, and store it in pending_comms
+ comm = mbox.put_async(content, msg_size)
+ pending_comms.append(comm)
+
+ # Start sending messages to let the workers know that they should stop
+ for i in range(0, receivers_count):
+ mbox = mboxes[i]
+ this_actor.info("Send 'finalize' to '{:s}'".format(str(mbox)))
+ comm = mbox.put_async("finalize", 0)
+ pending_comms.append(comm)
+
+ this_actor.info("Done dispatching all messages")
+
+ # Now that all message exchanges were initiated, wait for their completion, in order of completion.
+ #
+ # This loop waits for first terminating message with wait_any() and remove it with del, until all comms are
+ # terminated.
+ # Even in this simple example, the pending comms do not terminate in the exact same order of creation.
+ while pending_comms:
+ changed_pos = Comm.wait_any(pending_comms)
+ del pending_comms[changed_pos]
+ if changed_pos != 0:
+ this_actor.info(
+ "Remove the {:d}th pending comm: it terminated earlier than another comm that was initiated first."
+ .format(changed_pos))
+
+ this_actor.info("Goodbye now!")
+
+
+def receiver(my_id):
+ mbox = Mailbox.by_name("receiver-{:d}".format(my_id))
this_actor.info("Wait for my first message")
while True:
received = mbox.get()
# This program is free software you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, Host, this_actor
+"""
+Usage: exec-async.py platform_file [other parameters]
+"""
+
import sys
+from simgrid import Actor, Engine, Host, this_actor
class Waiter:
- """ This actor simply waits for its task completion after starting it. That's exactly equivalent to synchronous execution. """
+ """
+ This actor simply waits for its task completion after starting it.
+ That's exactly equivalent to synchronous execution.
+ """
def __call__(self):
computation_amount = this_actor.get_host().speed
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, Host, this_actor
import sys
+from simgrid import Actor, Engine, Host, this_actor
def executor():
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-# This example shows how to simulate a non-linear resource sharing for
-# CPUs.
+"""
+This example shows how to simulate a non-linear resource sharing for CPUs.
+"""
-
-from simgrid import Actor, Engine, NetZone, Host, this_actor
-import sys
import functools
+import sys
+from simgrid import Actor, Engine, NetZone, Host, this_actor
def runner():
computation_amount = this_actor.get_host().speed
n_task = 10
- this_actor.info("Execute %d tasks of %g flops, should take %d second in a CPU without degradation. It will take the double here." % (
- n_task, computation_amount, n_task))
+ this_actor.info("Execute %d tasks of %g flops, should take %d second in a CPU without degradation. \
+It will take the double here." % (n_task, computation_amount, n_task))
tasks = [this_actor.exec_init(computation_amount).start()
for _ in range(n_task)]
# During Engine destruction, the cleanup of std::function linked to non_linear callback is called.
# If we let the cleanup by itself, it fails trying on its destruction because the python main program
# has already freed its variables
- del(e)
+ del e
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, Host, this_actor
+"""
+Usage: exec-dvfs.py platform_file [other parameters]
+"""
+
import sys
+from simgrid import Actor, Engine, Host, this_actor
class Dvfs:
# Change power peak
new_pstate = 2
- this_actor.info("Changing power peak value to {:f} (at index {:d})".format( host.pstate_speed(new_pstate), new_pstate))
+ this_actor.info("Changing power peak value to {:f} (at index {:d})".format(host.pstate_speed(new_pstate),
+ new_pstate))
host.pstate = new_pstate
if __name__ == '__main__':
e = Engine(sys.argv)
if len(sys.argv) < 2:
- raise AssertionError("Usage: exec-dvfs.py platform_file [other parameters] (got {:d} params)".format(len(sys.argv)))
+ raise AssertionError("Usage: exec-dvfs.py platform_file [other parameters] (got {:d} params)"
+ .format(len(sys.argv)))
e.load_platform(sys.argv[1])
Actor.create("dvfs_test", Host.by_name("MyHost1"), Dvfs())
# This program is free software you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, Host, this_actor
import sys
+from simgrid import Actor, Engine, Host, this_actor
class Wizard:
this_actor.info("It started. Running 48.492Mf takes exactly one second on Ginette (but not on Fafard).")
this_actor.sleep_for(0.1)
- this_actor.info("Loads in flops/s: Boivin={:.0f}; Fafard={:.0f}; Ginette={:.0f}".format(boivin.load, fafard.load,
+ this_actor.info("Loads in flops/s: Boivin={:.0f}; Fafard={:.0f}; Ginette={:.0f}".format(boivin.load,
+ fafard.load,
ginette.load))
activity.wait()
this_actor.info("Done!")
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-# This example shows how to simulate a non-linear resource sharing for disk
-# operations.
-#
-# It is inspired on the paper
-# "Adding Storage Simulation Capacities to the SimGridToolkit: Concepts, Models, and API"
-# Available at : https://hal.inria.fr/hal-01197128/document
-#
-# It shows how to simulate concurrent operations degrading overall performance of IO
-# operations (specifically the effects presented in Fig. 8 of the paper).
+"""
+This example shows how to simulate a non-linear resource sharing for disk
+operations.
+
+It is inspired on the paper
+"Adding Storage Simulation Capacities to the SimGridToolkit: Concepts, Models, and API"
+Available at : https://hal.inria.fr/hal-01197128/document
+
+It shows how to simulate concurrent operations degrading overall performance of IO
+operations (specifically the effects presented in Fig. 8 of the paper).
+"""
-from simgrid import Actor, Engine, NetZone, Host, Disk, this_actor
-import sys
import functools
+import sys
+from simgrid import Actor, Engine, NetZone, Host, Disk, this_actor
def estimate_bw(disk: Disk, n_flows: int, read: bool):
disk.name, "read" if read else "write", n_flows, estimated_bw))
-def host():
+def host_runner():
# Estimating bw for each disk and considering concurrent flows
for n in range(1, 15, 2):
for disk in Host.current().get_disks():
# measurements for SSD disks
speed = {
"write": {1: 131.},
- "read": {1: 152., 2: 161., 3: 184., 4: 197., 5: 207., 6: 215., 7: 220., 8: 224., 9: 227., 10: 231., 11: 233., 12: 235., 13: 237., 14: 238., 15: 239.}
+ "read": {1: 152., 2: 161., 3: 184., 4: 197., 5: 207., 6: 215., 7: 220., 8: 224., 9: 227., 10: 231., 11: 233.,
+ 12: 235., 13: 237., 14: 238., 15: 239.}
}
# no special bandwidth for this disk sharing N flows, just returns maximal capacity
- if (n in speed[op]):
+ if n in speed[op]:
capacity = speed[op][n]
return capacity
create_sata_disk(bob, "Griffon (SATA II)")
zone.seal()
- Actor.create("runner", bob, host)
+ Actor.create("runner", bob, host_runner)
e.run()
this_actor.info("Simulated time: %g" % e.clock)
# During Engine destruction, the cleanup of std::function linked to non_linear callback is called.
# If we let the cleanup by itself, it fails trying on its destruction because the python main program
# has already freed its variables
- del(e)
+ del e
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-# This example shows how to simulate a non-linear resource sharing for
-# network links.
+"""
+This example shows how to simulate a non-linear resource sharing for network links.
+"""
-from simgrid import Actor, Engine, Comm, Mailbox, NetZone, Link, LinkInRoute, this_actor
-import sys
import functools
+import sys
+from simgrid import Actor, Engine, Comm, Mailbox, NetZone, Link, LinkInRoute, this_actor
class Sender:
- """
- Send a series of messages to mailbox "receiver"
- """
- def __init__(self, msg_count: int, msg_size=int(1e6)):
- self.msg_count = msg_count
- self.msg_size = msg_size
+ """
+ Send a series of messages to mailbox "receiver"
+ """
+ def __init__(self, msg_count: int, msg_size=int(1e6)):
+ self.msg_count = msg_count
+ self.msg_size = msg_size
- # Actors that are created as object will execute their __call__ method.
- # So, the following constitutes the main function of the Sender actor.
- def __call__(self):
- pending_comms = []
- mbox = Mailbox.by_name("receiver")
+ # Actors that are created as object will execute their __call__ method.
+ # So, the following constitutes the main function of the Sender actor.
+ def __call__(self):
+ pending_comms = []
+ mbox = Mailbox.by_name("receiver")
- for i in range(self.msg_count):
- msg = "Message " + str(i)
- size = self.msg_size * (i + 1)
- this_actor.info("Send '%s' to '%s, msg size: %d'" % (msg, mbox.name, size))
- comm = mbox.put_async(msg, size)
- pending_comms.append(comm)
+ for i in range(self.msg_count):
+ msg = "Message " + str(i)
+ size = self.msg_size * (i + 1)
+ this_actor.info("Send '%s' to '%s, msg size: %d'" % (msg, mbox.name, size))
+ comm = mbox.put_async(msg, size)
+ pending_comms.append(comm)
- this_actor.info("Done dispatching all messages")
+ this_actor.info("Done dispatching all messages")
- # Now that all message exchanges were initiated, wait for their completion in one single call
- Comm.wait_all(pending_comms)
+ # Now that all message exchanges were initiated, wait for their completion in one single call
+ Comm.wait_all(pending_comms)
- this_actor.info("Goodbye now!")
+ this_actor.info("Goodbye now!")
class Receiver:
- """
- Receiver actor: wait for N messages on the mailbox "receiver"
- """
+ """
+ Receiver actor: wait for N messages on the mailbox "receiver"
+ """
- def __init__(self, msg_count=10):
- self.msg_count = msg_count
+ def __init__(self, msg_count=10):
+ self.msg_count = msg_count
- def __call__(self):
- mbox = Mailbox.by_name("receiver")
+ def __call__(self):
+ mbox = Mailbox.by_name("receiver")
- pending_msgs = []
- pending_comms = []
+ pending_msgs = []
+ pending_comms = []
- this_actor.info("Wait for %d messages asynchronously" % self.msg_count)
- for _ in range(self.msg_count):
- comm, data = mbox.get_async()
- pending_comms.append(comm)
- pending_msgs.append(data)
+ this_actor.info("Wait for %d messages asynchronously" % self.msg_count)
+ for _ in range(self.msg_count):
+ comm, data = mbox.get_async()
+ pending_comms.append(comm)
+ pending_msgs.append(data)
- while len(pending_comms) > 0:
- index = Comm.wait_any(pending_comms)
- msg = pending_msgs[index].get()
- this_actor.info("I got '%s'." % msg)
- del pending_comms[index]
- del pending_msgs[index]
+ while pending_comms:
+ index = Comm.wait_any(pending_comms)
+ msg = pending_msgs[index].get()
+ this_actor.info("I got '%s'." % msg)
+ del pending_comms[index]
+ del pending_msgs[index]
####################################################################################################
def link_nonlinear(link: Link, capacity: float, n: int) -> float:
- """
- Non-linear resource sharing for links
-
- Note that the callback is called twice in this example:
- 1) link UP: with the number of active flows (from 9 to 1)
- 2) link DOWN: with 0 active flows. A crosstraffic communication is happing
- in the down link, but it's not considered as an active flow.
- """
- # emulates a degradation in link according to the number of flows
- # you probably want something more complex than that and based on real
- # experiments
- capacity = min(capacity, capacity * (1.0 - (n - 1) / 10.0))
- this_actor.info("Link %s, %d active communications, new capacity %f" % (link.name, n, capacity))
- return capacity
+ """
+ Non-linear resource sharing for links
+
+ Note that the callback is called twice in this example:
+ 1) link UP: with the number of active flows (from 9 to 1)
+ 2) link DOWN: with 0 active flows. A crosstraffic communication is happing
+ in the down link, but it's not considered as an active flow.
+ """
+ # emulates a degradation in link according to the number of flows
+ # you probably want something more complex than that and based on real
+ # experiments
+ capacity = min(capacity, capacity * (1.0 - (n - 1) / 10.0))
+ this_actor.info("Link %s, %d active communications, new capacity %f" % (link.name, n, capacity))
+ return capacity
def load_platform():
- """
- Create a simple 2-hosts platform */
- ________ __________
- | Sender |===============| Receiver |
- |________| Link1 |__________|
-
- """
- zone = NetZone.create_full_zone("Zone1")
- sender = zone.create_host("sender", 1).seal()
- receiver = zone.create_host("receiver", 1).seal()
-
- link = zone.create_split_duplex_link("link1", 1e6)
- # setting same callbacks (could be different) for link UP/DOWN in split-duplex link
- link.link_up.set_sharing_policy(
- Link.SharingPolicy.NONLINEAR,
- functools.partial(link_nonlinear, link.link_up))
- link.link_down.set_sharing_policy(
- Link.SharingPolicy.NONLINEAR,
- functools.partial(link_nonlinear, link.link_down))
- link.set_latency(10e-6).seal()
-
- # create routes between nodes
- zone.add_route(sender.netpoint, receiver.netpoint, None, None,
- [LinkInRoute(link, LinkInRoute.Direction.UP)], True)
- zone.seal()
-
- # create actors Sender/Receiver
- Actor.create("receiver", receiver, Receiver(9))
- Actor.create("sender", sender, Sender(9))
+ """
+ Create a simple 2-hosts platform
+ ________ __________
+ | Sender |===============| Receiver |
+ |________| Link1 |__________|
+
+ """
+ zone = NetZone.create_full_zone("Zone1")
+ sender = zone.create_host("sender", 1).seal()
+ receiver = zone.create_host("receiver", 1).seal()
+
+ link = zone.create_split_duplex_link("link1", 1e6)
+ # setting same callbacks (could be different) for link UP/DOWN in split-duplex link
+ link.link_up.set_sharing_policy(Link.SharingPolicy.NONLINEAR,
+ functools.partial(link_nonlinear, link.link_up))
+ link.link_down.set_sharing_policy(Link.SharingPolicy.NONLINEAR,
+ functools.partial(link_nonlinear, link.link_down))
+ link.set_latency(10e-6).seal()
+
+ # create routes between nodes
+ zone.add_route(sender.netpoint, receiver.netpoint, None, None,
+ [LinkInRoute(link, LinkInRoute.Direction.UP)], True)
+ zone.seal()
+
+ # create actors Sender/Receiver
+ Actor.create("receiver", receiver, Receiver(9))
+ Actor.create("sender", sender, Sender(9))
###################################################################################################
if __name__ == '__main__':
- e = Engine(sys.argv)
+ e = Engine(sys.argv)
- # create platform
- load_platform()
+ # create platform
+ load_platform()
- # runs the simulation
- e.run()
+ # runs the simulation
+ e.run()
- # explicitly deleting Engine object to avoid segfault during cleanup phase.
- # During Engine destruction, the cleanup of std::function linked to link_non_linear callback is called.
- # If we let the cleanup by itself, it fails trying on its destruction because the python main program
- # has already freed its variables
- del(e)
+ # explicitly deleting Engine object to avoid segfault during cleanup phase.
+ # During Engine destruction, the cleanup of std::function linked to link_non_linear callback is called.
+ # If we let the cleanup by itself, it fails trying on its destruction because the python main program
+ # has already freed its variables
+ del e
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-
-from simgrid import Actor, Engine, Host, Mailbox, this_actor, NetworkFailureException, TimeoutException
-import sys
-# This example shows how to work with the state profile of a host or a link,
-# specifying when the resource must be turned on or off.
-#
-# To set such a profile, the first way is to use a file in the XML, while the second is to use the programmatic
-# interface, as exemplified in the main() below. Once this profile is in place, the resource will automatically
-# be turned on and off.
-#
-# The actors running on a host that is turned off are forcefully killed
-# once their on_exit callbacks are executed. They cannot avoid this fate.
-# Since we specified on_failure="RESTART" for each actors in the XML file,
-# they will be automatically restarted when the host starts again.
-#
-# Communications using failed links will .. fail.
+"""
+This example shows how to work with the state profile of a host or a link,
+specifying when the resource must be turned on or off.
+
+To set such a profile, the first way is to use a file in the XML, while the second is to use the programmatic
+interface, as exemplified in the main() below. Once this profile is in place, the resource will automatically
+be turned on and off.
+
+The actors running on a host that is turned off are forcefully killed
+once their on_exit callbacks are executed. They cannot avoid this fate.
+Since we specified on_failure="RESTART" for each actors in the XML file,
+they will be automatically restarted when the host starts again.
+
+Communications using failed links will .. fail.
+"""
+
+import sys
+from simgrid import Actor, Engine, Host, Mailbox, this_actor, NetworkFailureException, TimeoutException
def master(* args):
- assert len(args) == 4, f"Actor master requires 4 parameters, but got {len(args)} ones."
- tasks_count = int(args[0])
- comp_size = int(args[1])
- comm_size = int(args[2])
- workers_count = int(args[3])
-
- this_actor.info(f"Got {workers_count} workers and {tasks_count} tasks to process")
-
- for i in range(tasks_count): # For each task to be executed:
- # - Select a worker in a round-robin way
- mailbox = Mailbox.by_name(f"worker-{i % workers_count}")
- try:
- this_actor.info(f"Send a message to {mailbox.name}")
- mailbox.put(comp_size, comm_size, 10.0)
- this_actor.info(f"Send to {mailbox.name} completed")
- except TimeoutException:
- this_actor.info(f"Mmh. Got timeouted while speaking to '{mailbox.name}'. Nevermind. Let's keep going!")
- except NetworkFailureException:
- this_actor.info(f"Mmh. The communication with '{mailbox.name}' failed. Nevermind. Let's keep going!")
-
- this_actor.info("All tasks have been dispatched. Let's tell everybody the computation is over.")
- for i in range (workers_count):
- # - Eventually tell all the workers to stop by sending a "finalize" task
- mailbox = Mailbox.by_name(f"worker-{i % workers_count}")
- try:
- mailbox.put(-1.0, 0, 1.0)
- except TimeoutException:
- this_actor.info(f"Mmh. Got timeouted while speaking to '{mailbox.name}'. Nevermind. Let's keep going!")
- except NetworkFailureException:
- this_actor.info(f"Mmh. The communication with '{mailbox.name}' failed. Nevermind. Let's keep going!")
-
- this_actor.info("Goodbye now!")
+ assert len(args) == 4, f"Actor master requires 4 parameters, but got {len(args)} ones."
+ tasks_count = int(args[0])
+ comp_size = int(args[1])
+ comm_size = int(args[2])
+ workers_count = int(args[3])
+
+ this_actor.info(f"Got {workers_count} workers and {tasks_count} tasks to process")
+
+ for i in range(tasks_count): # For each task to be executed:
+ # - Select a worker in a round-robin way
+ mailbox = Mailbox.by_name(f"worker-{i % workers_count}")
+ try:
+ this_actor.info(f"Send a message to {mailbox.name}")
+ mailbox.put(comp_size, comm_size, 10.0)
+ this_actor.info(f"Send to {mailbox.name} completed")
+ except TimeoutException:
+ this_actor.info(f"Mmh. Got timeouted while speaking to '{mailbox.name}'. Nevermind. Let's keep going!")
+ except NetworkFailureException:
+ this_actor.info(f"Mmh. The communication with '{mailbox.name}' failed. Nevermind. Let's keep going!")
+
+ this_actor.info("All tasks have been dispatched. Let's tell everybody the computation is over.")
+ for i in range(workers_count):
+ # - Eventually tell all the workers to stop by sending a "finalize" task
+ mailbox = Mailbox.by_name(f"worker-{i % workers_count}")
+ try:
+ mailbox.put(-1.0, 0, 1.0)
+ except TimeoutException:
+ this_actor.info(f"Mmh. Got timeouted while speaking to '{mailbox.name}'. Nevermind. Let's keep going!")
+ except NetworkFailureException:
+ this_actor.info(f"Mmh. The communication with '{mailbox.name}' failed. Nevermind. Let's keep going!")
+
+ this_actor.info("Goodbye now!")
def worker(* args):
- assert len(args) == 1, "Expecting one parameter"
- my_id = int(args[0])
-
- mailbox = Mailbox.by_name(f"worker-{my_id}")
- done = False
- while not done:
- try:
- this_actor.info(f"Waiting a message on {mailbox.name}")
- compute_cost = mailbox.get()
- if compute_cost > 0: # If compute_cost is valid, execute a computation of that cost
- this_actor.info("Start execution...")
- this_actor.execute(compute_cost)
- this_actor.info("Execution complete.")
- else: # Stop when receiving an invalid compute_cost
- this_actor.info("I'm done. See you!")
- done = True
- except NetworkFailureException:
- this_actor.info("Mmh. Something went wrong. Nevermind. Let's keep going!")
+ assert len(args) == 1, "Expecting one parameter"
+ my_id = int(args[0])
+
+ mailbox = Mailbox.by_name(f"worker-{my_id}")
+ done = False
+ while not done:
+ try:
+ this_actor.info(f"Waiting a message on {mailbox.name}")
+ compute_cost = mailbox.get()
+ if compute_cost > 0: # If compute_cost is valid, execute a computation of that cost
+ this_actor.info("Start execution...")
+ this_actor.execute(compute_cost)
+ this_actor.info("Execution complete.")
+ else: # Stop when receiving an invalid compute_cost
+ this_actor.info("I'm done. See you!")
+ done = True
+ except NetworkFailureException:
+ this_actor.info("Mmh. Something went wrong. Nevermind. Let's keep going!")
def sleeper():
- this_actor.info("Start sleeping...")
- this_actor.sleep_for(1)
- this_actor.info("done sleeping.")
+ this_actor.info("Start sleeping...")
+ this_actor.sleep_for(1)
+ this_actor.info("done sleeping.")
if __name__ == '__main__':
- assert len(sys.argv) > 2, f"Usage: python app-masterworkers.py platform_file deployment_file"
+ assert len(sys.argv) > 2, f"Usage: python app-masterworkers.py platform_file deployment_file"
- e = Engine(sys.argv)
+ e = Engine(sys.argv)
- # This is how to attach a profile to an host that is created from the XML file.
- # This should be done before calling load_platform(), as the on_creation() event is fired when loading the platform.
- # You can never set a new profile to a resource that already have one.
- def on_creation(host):
- if (host.name == "Bourrassa"):
- host.set_state_profile("67 0\n70 1\n", 0)
- Host.on_creation_cb(on_creation)
+ # This is how to attach a profile to an host that is created from the XML file.
+ # This should be done before calling load_platform(), as the on_creation() event is fired when loading the platform.
+ # You can never set a new profile to a resource that already have one.
+ def on_creation(host):
+ if host.name == "Bourrassa":
+ host.set_state_profile("67 0\n70 1\n", 0)
+ Host.on_creation_cb(on_creation)
- e.load_platform(sys.argv[1])
+ e.load_platform(sys.argv[1])
- e.register_actor("master", master)
- e.register_actor("worker", worker)
- e.load_deployment(sys.argv[2])
+ e.register_actor("master", master)
+ e.register_actor("worker", worker)
+ e.load_deployment(sys.argv[2])
- # Add a new host programatically, and attach a state profile to it
- lili = e.netzone_root.create_host("Lilibeth", 1e15)
- lili.set_state_profile("4 0\n5 1\n", 10)
- lili.seal()
+ # Add a new host programatically, and attach a state profile to it
+ lili = e.netzone_root.create_host("Lilibeth", 1e15)
+ lili.set_state_profile("4 0\n5 1\n", 10)
+ lili.seal()
- # Create an actor on that new host, to monitor its own state
- actor = Actor.create("sleeper", lili, sleeper)
- actor.set_auto_restart(True)
+ # Create an actor on that new host, to monitor its own state
+ actor = Actor.create("sleeper", lili, sleeper)
+ actor.set_auto_restart(True)
- e.run()
+ e.run()
- this_actor.info(f"Simulation time {e.clock:.4f}")
+ this_actor.info(f"Simulation time {e.clock:.4f}")
# This program is free software; you can redistribute it and/or modify it
# under the terms of the license (GNU LGPL) which comes with this package.
-from simgrid import Actor, Engine, Host, Link, this_actor
-import sys
+"""
+This example demonstrates how to attach a profile to a host or a link, to specify external changes to the resource
+speed.
+The first way to do so is to use a file in the XML, while the second is to use the programmatic interface.
+"""
-# This example demonstrates how to attach a profile to a host or a link, to specify external changes to the resource speed.
-# The first way to do so is to use a file in the XML, while the second is to use the programmatic interface.
+import sys
+from simgrid import Actor, Engine, Host, Link, this_actor
def watcher():
- jupiter = Host.by_name("Jupiter")
- fafard = Host.by_name("Fafard")
- lilibeth = Host.by_name("Lilibeth")
- link1 = Link.by_name("1")
- link2 = Link.by_name("2")
-
- (links, lat) = jupiter.route_to(fafard)
- path = ""
- for l in links:
- path += ("" if len(path)==0 else ", ") + "link '" + l.name + "'"
- this_actor.info(f"Path from Jupiter to Fafard: {path} (latency: {lat:.6f}s).")
-
- for _ in range(10):
- this_actor.info("Fafard: %.0fMflops, Jupiter: %4.0fMflops, Lilibeth: %3.1fMflops, Link1: (%.2fMB/s %.0fms), Link2: (%.2fMB/s %.0fms)" % (
- fafard.speed * fafard.available_speed / 1000000,
- jupiter.speed * jupiter.available_speed / 1000000,
- lilibeth.speed * lilibeth.available_speed / 1000000,
- link1.bandwidth / 1000, link1.latency * 1000,
- link2.bandwidth / 1000, link2.latency * 1000))
- this_actor.sleep_for(1)
+ jupiter = Host.by_name("Jupiter")
+ fafard = Host.by_name("Fafard")
+ lilibeth = Host.by_name("Lilibeth")
+ link1 = Link.by_name("1")
+ link2 = Link.by_name("2")
+
+ (links, lat) = jupiter.route_to(fafard)
+ path = ""
+ for l in links:
+ path += ("" if not path else ", ") + "link '" + l.name + "'"
+ this_actor.info(f"Path from Jupiter to Fafard: {path} (latency: {lat:.6f}s).")
+
+ for _ in range(10):
+ this_actor.info("Fafard: %.0fMflops, Jupiter: %4.0fMflops, Lilibeth: %3.1fMflops, \
+Link1: (%.2fMB/s %.0fms), Link2: (%.2fMB/s %.0fms)" % (fafard.speed * fafard.available_speed / 1000000,
+ jupiter.speed * jupiter.available_speed / 1000000,
+ lilibeth.speed * lilibeth.available_speed / 1000000,
+ link1.bandwidth / 1000, link1.latency * 1000,
+ link2.bandwidth / 1000, link2.latency * 1000))
+ this_actor.sleep_for(1)
if __name__ == '__main__':
- e = Engine(sys.argv)
- # Load the platform description
- e.load_platform(sys.argv[1])
+ e = Engine(sys.argv)
+ # Load the platform description
+ e.load_platform(sys.argv[1])
- # Add a new host programmatically, and attach a simple speed profile to it (alternate between full and half speed every two seconds
- lili = e.netzone_root.create_host("Lilibeth", 25e6)
- lili.set_speed_profile("""0 1.0
-2 0.5""", 2)
- lili.seal()
+ # Add a new host programmatically, and attach a simple speed profile to it (alternate between full and half speed
+ # every two seconds
+ lili = e.netzone_root.create_host("Lilibeth", 25e6)
+ lili.set_speed_profile("""0 1.0
+ 2 0.5""", 2)
+ lili.seal()
- # Add a watcher of the changes
- Actor.create("watcher", Host.by_name("Fafard"), watcher)
+ # Add a watcher of the changes
+ Actor.create("watcher", Host.by_name("Fafard"), watcher)
- e.run()
+ e.run()