Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
7ea66d3e97a58e76e78924a58475f5e07b5a86f8
[simgrid.git] / examples / python / platform-failures / platform-failures.py
1 ## Copyright (c) 2007-2022. The SimGrid Team. All rights reserved.
2 #
3 # This program is free software; you can redistribute it and/or modify it
4 # under the terms of the license (GNU LGPL) which comes with this package.
5  
6 from simgrid import Actor, Engine, Host, Mailbox, this_actor, NetworkFailureException, TimeoutException
7 import sys
8
9 # This example shows how to work with the state profile of a host or a link,
10 # specifying when the resource must be turned on or off.
11 #
12 # To set such a profile, the first way is to use a file in the XML, while the second is to use the programmatic
13 # interface, as exemplified in the main() below. Once this profile is in place, the resource will automatically
14 # be turned on and off.
15 #
16 # The actors running on a host that is turned off are forcefully killed
17 # once their on_exit callbacks are executed. They cannot avoid this fate.
18 # Since we specified on_failure="RESTART" for each actors in the XML file,
19 # they will be automatically restarted when the host starts again.
20 #
21 # Communications using failed links will .. fail.
22
23 def master(* args):
24   assert len(args) == 4, f"Actor master requires 4 parameters, but got {len(args)} ones."
25   tasks_count   = int(args[0])
26   comp_size     = int(args[1])
27   comm_size     = int(args[2])
28   workers_count = int(args[3])
29
30   this_actor.info(f"Got {workers_count} workers and {tasks_count} tasks to process")
31
32   for i in range(tasks_count): # For each task to be executed: 
33     # - Select a worker in a round-robin way
34     mailbox = Mailbox.by_name(f"worker-{i % workers_count}")
35     try:
36       this_actor.info(f"Send a message to {mailbox.name}")
37       mailbox.put(comp_size, comm_size, 10.0)
38       this_actor.info(f"Send to {mailbox.name} completed")
39     except TimeoutException:
40       this_actor.info(f"Mmh. Got timeouted while speaking to '{mailbox.name}'. Nevermind. Let's keep going!")
41     except NetworkFailureException:
42       this_actor.info(f"Mmh. The communication with '{mailbox.name}' failed. Nevermind. Let's keep going!")
43
44   this_actor.info("All tasks have been dispatched. Let's tell everybody the computation is over.")
45   for i in range (workers_count):
46     # - Eventually tell all the workers to stop by sending a "finalize" task
47     mailbox = Mailbox.by_name(f"worker-{i % workers_count}")
48     try:
49       mailbox.put(-1.0, 0, 1.0)
50     except TimeoutException:
51       this_actor.info(f"Mmh. Got timeouted while speaking to '{mailbox.name}'. Nevermind. Let's keep going!")
52     except NetworkFailureException:
53       this_actor.info(f"Mmh. The communication with '{mailbox.name}' failed. Nevermind. Let's keep going!")
54
55   this_actor.info("Goodbye now!")
56
57 def worker(* args):
58   assert len(args) == 1, "Expecting one parameter"
59   my_id               = int(args[0])
60
61   mailbox = Mailbox.by_name(f"worker-{my_id}")
62   done = False
63   while not done:
64     try:
65       this_actor.info(f"Waiting a message on {mailbox.name}")
66       compute_cost = mailbox.get()
67       if compute_cost > 0: # If compute_cost is valid, execute a computation of that cost 
68         this_actor.info("Start execution...")
69         this_actor.execute(compute_cost)
70         this_actor.info("Execution complete.")
71       else: # Stop when receiving an invalid compute_cost
72         this_actor.info("I'm done. See you!")
73         done = True
74     except NetworkFailureException:
75       this_actor.info("Mmh. Something went wrong. Nevermind. Let's keep going!")
76
77 def sleeper():
78   this_actor.info("Start sleeping...")
79   this_actor.sleep_for(1)
80   this_actor.info("done sleeping.")
81
82 if __name__ == '__main__':
83   assert len(sys.argv) > 2, f"Usage: python app-masterworkers.py platform_file deployment_file"
84
85   e = Engine(sys.argv)
86
87   # This is how to attach a profile to an host that is created from the XML file.
88   # This should be done before calling load_platform(), as the on_creation() event is fired when loading the platform.
89   # You can never set a new profile to a resource that already have one.
90   def on_creation(host):
91     if (host.name == "Bourrassa"):
92       host.set_state_profile("67 0\n70 1\n", 0)
93   Host.on_creation_cb(on_creation)
94
95   e.load_platform(sys.argv[1])
96
97   e.register_actor("master", master)
98   e.register_actor("worker", worker)
99   e.load_deployment(sys.argv[2])
100
101   # Add a new host programatically, and attach a state profile to it
102   lili = e.get_netzone_root().create_host("Lilibeth", 1e15)
103   lili.set_state_profile("4 0\n5 1\n", 10)
104   lili.seal()
105
106   # Create an actor on that new host, to monitor its own state
107   actor = Actor.create("sleeper", lili, sleeper)
108   actor.set_auto_restart(True)
109
110   e.run()
111
112   this_actor.info(f"Simulation time {e.get_clock():.4f}")