From: Arnaud Giersch Date: Thu, 17 Feb 2022 14:40:05 +0000 (+0100) Subject: Pylint examples/*.py. X-Git-Tag: v3.31~398 X-Git-Url: http://bilbo.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/b83bdf8faae7ba64d66c529754159a164b70104d Pylint examples/*.py. --- diff --git a/examples/c/app-bittorrent/generate.py b/examples/c/app-bittorrent/generate.py index 345e739618..aaaa1f9d59 100755 --- a/examples/c/app-bittorrent/generate.py +++ b/examples/c/app-bittorrent/generate.py @@ -6,10 +6,12 @@ # 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 diff --git a/examples/c/dht-kademlia/generate.py b/examples/c/dht-kademlia/generate.py index 1af0de62c5..9986fb88d4 100755 --- a/examples/c/dht-kademlia/generate.py +++ b/examples/c/dht-kademlia/generate.py @@ -6,6 +6,10 @@ # 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 diff --git a/examples/c/dht-pastry/generate.py b/examples/c/dht-pastry/generate.py index e517a3c313..0db8029686 100755 --- a/examples/c/dht-pastry/generate.py +++ b/examples/c/dht-pastry/generate.py @@ -6,10 +6,12 @@ # 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 diff --git a/examples/cpp/dht-kademlia/generate.py b/examples/cpp/dht-kademlia/generate.py index 1af0de62c5..9986fb88d4 100755 --- a/examples/cpp/dht-kademlia/generate.py +++ b/examples/cpp/dht-kademlia/generate.py @@ -6,6 +6,10 @@ # 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 diff --git a/examples/deprecated/java/app/bittorrent/generate.py b/examples/deprecated/java/app/bittorrent/generate.py index efb011ddb3..a565dc1815 100755 --- a/examples/deprecated/java/app/bittorrent/generate.py +++ b/examples/deprecated/java/app/bittorrent/generate.py @@ -6,10 +6,12 @@ # 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 diff --git a/examples/python/actor-create/actor-create.py b/examples/python/actor-create/actor-create.py index 4b04a0682c..0f4e01e3c0 100644 --- a/examples/python/actor-create/actor-create.py +++ b/examples/python/actor-create/actor-create.py @@ -3,21 +3,23 @@ # 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): diff --git a/examples/python/actor-daemon/actor-daemon.py b/examples/python/actor-daemon/actor-daemon.py index 457aed1271..a6f1b83aee 100644 --- a/examples/python/actor-daemon/actor-daemon.py +++ b/examples/python/actor-daemon/actor-daemon.py @@ -3,8 +3,12 @@ # 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(): diff --git a/examples/python/actor-join/actor-join.py b/examples/python/actor-join/actor-join.py index 25dfab0f33..d64118d366 100644 --- a/examples/python/actor-join/actor-join.py +++ b/examples/python/actor-join/actor-join.py @@ -3,8 +3,12 @@ # 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(): diff --git a/examples/python/actor-kill/actor-kill.py b/examples/python/actor-kill/actor-kill.py index a662641f07..5adff3112d 100644 --- a/examples/python/actor-kill/actor-kill.py +++ b/examples/python/actor-kill/actor-kill.py @@ -3,8 +3,12 @@ # 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(): diff --git a/examples/python/actor-lifetime/actor-lifetime.py b/examples/python/actor-lifetime/actor-lifetime.py index adc4658bba..a8dec3f25b 100644 --- a/examples/python/actor-lifetime/actor-lifetime.py +++ b/examples/python/actor-lifetime/actor-lifetime.py @@ -3,17 +3,19 @@ # 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): diff --git a/examples/python/actor-migrate/actor-migrate.py b/examples/python/actor-migrate/actor-migrate.py index b78dbfc26f..9cac4bbf01 100644 --- a/examples/python/actor-migrate/actor-migrate.py +++ b/examples/python/actor-migrate/actor-migrate.py @@ -3,20 +3,22 @@ # 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): diff --git a/examples/python/actor-suspend/actor-suspend.py b/examples/python/actor-suspend/actor-suspend.py index fae11b64e2..af021b6cfd 100644 --- a/examples/python/actor-suspend/actor-suspend.py +++ b/examples/python/actor-suspend/actor-suspend.py @@ -3,8 +3,12 @@ # 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(): diff --git a/examples/python/actor-yield/actor-yield.py b/examples/python/actor-yield/actor-yield.py index d20a54b6ff..d82b20fcbb 100644 --- a/examples/python/actor-yield/actor-yield.py +++ b/examples/python/actor-yield/actor-yield.py @@ -3,19 +3,20 @@ # 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)) @@ -24,7 +25,7 @@ if __name__ == '__main__': 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) diff --git a/examples/python/app-masterworkers/app-masterworkers.py b/examples/python/app-masterworkers/app-masterworkers.py index 6eb8b190cb..9ae26538e7 100644 --- a/examples/python/app-masterworkers/app-masterworkers.py +++ b/examples/python/app-masterworkers/app-masterworkers.py @@ -1,56 +1,57 @@ -# 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 @@ -64,7 +65,7 @@ if __name__ == '__main__': 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 diff --git a/examples/python/clusters-multicpu/clusters-multicpu.py b/examples/python/clusters-multicpu/clusters-multicpu.py index 8673890e6a..637eab55b9 100644 --- a/examples/python/clusters-multicpu/clusters-multicpu.py +++ b/examples/python/clusters-multicpu/clusters-multicpu.py @@ -3,15 +3,17 @@ # 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: @@ -56,8 +58,9 @@ class Receiver: ##################################################################################################### -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. @@ -103,8 +106,8 @@ def create_hostzone(zone: simgrid.NetZone, coord: typing.List[int], ident: int) 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() @@ -119,8 +122,8 @@ def create_limiter(zone: simgrid.NetZone, coord: typing.List[int], ident: int) - 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). @@ -169,14 +172,15 @@ def create_torus_cluster(): Cluster """ # 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 @@ -224,14 +228,15 @@ def create_fat_tree_cluster(): Cluster """ # 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 @@ -269,13 +274,14 @@ def create_dragonfly_cluster(): Cluster """ # 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] @@ -298,3 +304,6 @@ if __name__ == '__main__': # runs the simulation e.run() + +if __name__ == '__main__': + main() diff --git a/examples/python/comm-wait/comm-wait.py b/examples/python/comm-wait/comm-wait.py index 8f4f728e77..95c1e9c3aa 100644 --- a/examples/python/comm-wait/comm-wait.py +++ b/examples/python/comm-wait/comm-wait.py @@ -4,57 +4,59 @@ # 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__': @@ -64,5 +66,5 @@ 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() diff --git a/examples/python/comm-waitall/comm-waitall.py b/examples/python/comm-waitall/comm-waitall.py index 38a34f148d..0ffa0d22f5 100644 --- a/examples/python/comm-waitall/comm-waitall.py +++ b/examples/python/comm-waitall/comm-waitall.py @@ -3,53 +3,55 @@ # 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: diff --git a/examples/python/comm-waitany/comm-waitany.py b/examples/python/comm-waitany/comm-waitany.py index c59ccd0098..d19c590b05 100644 --- a/examples/python/comm-waitany/comm-waitany.py +++ b/examples/python/comm-waitany/comm-waitany.py @@ -3,67 +3,70 @@ # 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() diff --git a/examples/python/exec-async/exec-async.py b/examples/python/exec-async/exec-async.py index 86c7b16341..07585437a3 100644 --- a/examples/python/exec-async/exec-async.py +++ b/examples/python/exec-async/exec-async.py @@ -3,12 +3,19 @@ # 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 diff --git a/examples/python/exec-basic/exec-basic.py b/examples/python/exec-basic/exec-basic.py index 0e6e2e2ab0..754fe7168f 100644 --- a/examples/python/exec-basic/exec-basic.py +++ b/examples/python/exec-basic/exec-basic.py @@ -3,8 +3,8 @@ # 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(): diff --git a/examples/python/exec-cpu-nonlinear/exec-cpu-nonlinear.py b/examples/python/exec-cpu-nonlinear/exec-cpu-nonlinear.py index e95f64a18b..d4d9498ec0 100644 --- a/examples/python/exec-cpu-nonlinear/exec-cpu-nonlinear.py +++ b/examples/python/exec-cpu-nonlinear/exec-cpu-nonlinear.py @@ -3,21 +3,21 @@ # 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)] @@ -64,4 +64,4 @@ if __name__ == '__main__': # 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 diff --git a/examples/python/exec-dvfs/exec-dvfs.py b/examples/python/exec-dvfs/exec-dvfs.py index 7a7a5dd709..f8d8dffc73 100644 --- a/examples/python/exec-dvfs/exec-dvfs.py +++ b/examples/python/exec-dvfs/exec-dvfs.py @@ -3,8 +3,12 @@ # 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: @@ -26,7 +30,8 @@ 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 @@ -47,7 +52,8 @@ class Dvfs: 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()) diff --git a/examples/python/exec-remote/exec-remote.py b/examples/python/exec-remote/exec-remote.py index ba1cf1266b..2e4f2b93c1 100644 --- a/examples/python/exec-remote/exec-remote.py +++ b/examples/python/exec-remote/exec-remote.py @@ -3,8 +3,8 @@ # 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: @@ -21,7 +21,8 @@ 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!") diff --git a/examples/python/io-degradation/io-degradation.py b/examples/python/io-degradation/io-degradation.py index de16c34837..f6b60429c5 100644 --- a/examples/python/io-degradation/io-degradation.py +++ b/examples/python/io-degradation/io-degradation.py @@ -3,20 +3,22 @@ # 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): @@ -35,7 +37,7 @@ 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(): @@ -57,11 +59,12 @@ def ssd_dynamic_sharing(disk: Disk, op: str, capacity: float, n: int) -> float: # 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 @@ -112,7 +115,7 @@ if __name__ == '__main__': 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) @@ -121,4 +124,4 @@ if __name__ == '__main__': # 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 diff --git a/examples/python/network-nonlinear/network-nonlinear.py b/examples/python/network-nonlinear/network-nonlinear.py index e8f2de6259..40cb0b7035 100644 --- a/examples/python/network-nonlinear/network-nonlinear.py +++ b/examples/python/network-nonlinear/network-nonlinear.py @@ -3,129 +3,128 @@ # 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 diff --git a/examples/python/platform-failures/platform-failures.py b/examples/python/platform-failures/platform-failures.py index d285aaf01c..a94446642f 100644 --- a/examples/python/platform-failures/platform-failures.py +++ b/examples/python/platform-failures/platform-failures.py @@ -2,111 +2,113 @@ # # 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}") diff --git a/examples/python/platform-profile/platform-profile.py b/examples/python/platform-profile/platform-profile.py index 1fb9611e1b..82b6146916 100644 --- a/examples/python/platform-profile/platform-profile.py +++ b/examples/python/platform-profile/platform-profile.py @@ -3,46 +3,50 @@ # 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()