From ce65e3e0615f1b3f2a408f1fee003b5974d4f14b Mon Sep 17 00:00:00 2001 From: Martin Quinson Date: Mon, 31 Dec 2018 02:31:47 +0100 Subject: [PATCH] python: two more examples, the basics are here --- examples/python/CMakeLists.txt | 2 +- examples/python/actor-create/actor-create.py | 100 ++++++++++++++++++ .../python/actor-create/actor-create.tesh | 13 +++ .../python/actor-create/actor-create_d.xml | 19 ++++ examples/python/actor-yield/actor-yield.py | 34 ++++++ examples/python/actor-yield/actor-yield.tesh | 5 + 6 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 examples/python/actor-create/actor-create.py create mode 100644 examples/python/actor-create/actor-create.tesh create mode 100644 examples/python/actor-create/actor-create_d.xml create mode 100644 examples/python/actor-yield/actor-yield.py create mode 100644 examples/python/actor-yield/actor-yield.tesh diff --git a/examples/python/CMakeLists.txt b/examples/python/CMakeLists.txt index 4f1bd5e65f..8c014b06ad 100644 --- a/examples/python/CMakeLists.txt +++ b/examples/python/CMakeLists.txt @@ -1,4 +1,4 @@ -foreach(example exec-basic) +foreach(example actor-create actor-yield exec-basic) set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/${example}/${example}.tesh) set(examples_src ${examples_src} ${CMAKE_CURRENT_SOURCE_DIR}/${example}/${example}.py) diff --git a/examples/python/actor-create/actor-create.py b/examples/python/actor-create/actor-create.py new file mode 100644 index 0000000000..2bc05b0783 --- /dev/null +++ b/examples/python/actor-create/actor-create.py @@ -0,0 +1,100 @@ +# Copyright (c) 2006-2018. 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. + +# 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 paramter 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. + +import simgrid, sys + +# Our first class of actors is simply implemented with a function, that takes a single string as parameter. +# +# Later, this actor class is instantiated within the simulation. +def receiver(mailbox_name): + mailbox = simgrid.Mailbox.by_name(mailbox_name) + + simgrid.info("Hello s4u, I'm ready to get any message you'd want on {:s}".format(mailbox.get_name())) + + msg1 = mailbox.get() + msg2 = mailbox.get() + msg3 = mailbox.get() + simgrid.info("I received '{:s}', '{:s}' and '{:s}'".format(msg1, msg2, msg3)) + simgrid.info("I'm done. See you.") + +# Our second class of actors is also a function +def forwarder(*args): + if len(args) < 2: raise AssertionError("Actor forwarder requires 2 parameters, but got only {:d}".format(len(args))) + mb_in = simgrid.Mailbox.by_name(args[0]) + mb_out = simgrid.Mailbox.by_name(args[1]) + + msg = mb_in.get() + simgrid.info("Forward '{:s}'.".format(msg)) + mb_out.put(msg, len(msg)) + +# Declares a third class of actors which sends a message to the mailbox 'mb42'. +# The sent message is what was passed as parameter on creation (or 'GaBuZoMeu' by default) +# +# Later, this actor class is instantiated twice in the simulation. +class Sender: + mbox = "mb42" + msg = "GaBuZoMeu"; + def __init__(self, *args): + if len(args) > 0: self.msg = args[0]; + if len(args) > 1: self.mbox = args[1]; + if len(args) > 2: raise AssertionError("Actor sender requires 2 parameters, but got only {:d}".format(len(args))) + + def __call__(self): + simgrid.info("Hello s4u, I have something to send") + mailbox = simgrid.Mailbox.by_name(self.mbox) + + mailbox.put(self.msg, len(self.msg)) + simgrid.info("I'm done. See you.") + +# Here comes the main function of your program +if __name__ == '__main__': + # When your program starts, you have to first start a new simulation engine, as follows + e = simgrid.Engine(sys.argv) + + # Then you should load a platform file, describing your simulated platform + e.load_platform("../platforms/small_platform.xml"); + + # And now you have to ask SimGrid to actually start your actors. + # + # The easiest way to do so is to implement the behavior of your actor in a single function, + # as we do here for the receiver actors. This function can take any kind of parameters, as + # long as the last parameters of Actor::create() match what your function expects. + simgrid.Actor.create("receiver", simgrid.Host.by_name("Fafard"), receiver, "mb42") + + # If your actor is getting more complex, you probably want to implement it as a class instead, + # as we do here for the sender actors. The main behavior goes into operator()() of the class. + # + # You can then directly start your actor, as follows: + simgrid.Actor.create("sender1", simgrid.Host.by_name("Tremblay"), Sender()) + # If you want to pass parameters to your class, that's very easy: just use your constructors + simgrid.Actor.create("sender2", simgrid.Host.by_name("Jupiter"), Sender("GloubiBoulga")); + + # But starting actors directly is considered as a bad experimental habit, since it ties the code + # you want to test with the experimental scenario. Starting your actors from an external deployment + # file in XML ensures that you can test your code in several scenarios without changing the code itself. + # + # For that, you first need to register your function or your actor as follows. + e.register_actor("sender", Sender) + e.register_actor("forwarder", forwarder) + # Once actors and functions are registered, just load the deployment file + e.load_deployment("actor-create/actor-create_d.xml") + + # Once every actors are started in the engine, the simulation can start + e.run(); + + # Once the simulation is done, the program is ended diff --git a/examples/python/actor-create/actor-create.tesh b/examples/python/actor-create/actor-create.tesh new file mode 100644 index 0000000000..c93449dd46 --- /dev/null +++ b/examples/python/actor-create/actor-create.tesh @@ -0,0 +1,13 @@ +#!/usr/bin/env tesh + +$ python3 ${srcdir:=.}/actor-create.py +> [Tremblay:sender1:(2) 0.000000] [python/INFO] Hello s4u, I have something to send +> [Jupiter:sender2:(3) 0.000000] [python/INFO] Hello s4u, I have something to send +> [Fafard:sender:(4) 0.000000] [python/INFO] Hello s4u, I have something to send +> [Fafard:receiver:(1) 0.000000] [python/INFO] Hello s4u, I'm ready to get any message you'd want on mb42 +> [Fafard:sender:(4) 0.016392] [python/INFO] I'm done. See you. +> [Ginette:forwarder:(5) 0.016392] [python/INFO] Forward 'PopPop!'. +> [Tremblay:sender1:(2) 0.025709] [python/INFO] I'm done. See you. +> [Jupiter:sender2:(3) 0.070434] [python/INFO] I'm done. See you. +> [Fafard:receiver:(1) 0.086825] [python/INFO] I received 'GaBuZoMeu', 'GloubiBoulga' and 'PopPop!' +> [Fafard:receiver:(1) 0.086825] [python/INFO] I'm done. See you. diff --git a/examples/python/actor-create/actor-create_d.xml b/examples/python/actor-create/actor-create_d.xml new file mode 100644 index 0000000000..753a9c40f4 --- /dev/null +++ b/examples/python/actor-create/actor-create_d.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/examples/python/actor-yield/actor-yield.py b/examples/python/actor-yield/actor-yield.py new file mode 100644 index 0000000000..db190d090e --- /dev/null +++ b/examples/python/actor-yield/actor-yield.py @@ -0,0 +1,34 @@ +# Copyright (c) 2017-2018. 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. + +import simgrid, sys + +# 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. + +# Main function of the Yielder process +class Yielder: + number_of_yields = 0 + def __init__(self, *args): + self.number_of_yields = int(args[0]) + def __call__(self): + for i in range(self.number_of_yields): + simgrid.yield_() + simgrid.info("I yielded {:d} times. Goodbye now!".format(self.number_of_yields)) + +if __name__ == '__main__': + e = simgrid.Engine(sys.argv) + + e.load_platform(sys.argv[1]) # Load the platform description + e.register_actor("yielder", Yielder) # Register the class representing the actors + + e.load_deployment(sys.argv[2]) + + e.run() # - Run the simulation diff --git a/examples/python/actor-yield/actor-yield.tesh b/examples/python/actor-yield/actor-yield.tesh new file mode 100644 index 0000000000..6cbf8baaa1 --- /dev/null +++ b/examples/python/actor-yield/actor-yield.tesh @@ -0,0 +1,5 @@ +#!/usr/bin/env tesh + +$ python3 ${srcdir:=.}/actor-yield.py ${platfdir}/small_platform_fatpipe.xml ${srcdir:=.}/../../s4u/actor-yield/s4u-actor-yield_d.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" +> [ 0.000000] (1:yielder@Tremblay) I yielded 10 times. Goodbye now! +> [ 0.000000] (2:yielder@Ruby) I yielded 15 times. Goodbye now! -- 2.20.1