Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'example-battery-chiller-solar' into 'master'
[simgrid.git] / examples / python / task-switch-host / task-switch-host.py
1 # Copyright (c) 2006-2023. 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 """
7 This example demonstrates how to dynamically modify a graph of tasks.
8
9 Assuming we have two instances of a service placed on different hosts,
10 we want to send data alternatively to thoses instances.
11
12 We consider the following graph:
13
14            comm1
15      ┌────────────────────────┐
16      │                        │
17      │               Fafard   │
18      │              ┌───────┐ │
19      │      ┌──────►│ exec1 ├─┘
20      ▼      │       └───────┘
21  Tremblay ──┤comm0
22      ▲      │        Jupiter
23      │      │       ┌───────┐
24      │      └──────►│ exec2 ├─┐
25      │              └───────┘ │
26      │                        │
27      └────────────────────────┘
28            comm2
29
30 """
31
32 from argparse import ArgumentParser
33 import sys
34 from simgrid import Engine, Task, CommTask, ExecTask
35
36 def parse():
37     parser = ArgumentParser()
38     parser.add_argument(
39         '--platform',
40         type=str,
41         required=True,
42         help='path to the platform description'
43     )
44     return parser.parse_args()
45
46 def callback(t):
47     print(f'[{Engine.clock}] {t} finished ({t.get_count()})')
48
49 def switch_destination(t, hosts):
50     t.destination = hosts[switch_destination.count % 2]
51     switch_destination.count += 1
52 switch_destination.count = 0
53
54 def switch_successor(t, execs):
55     t.remove_successor(execs[t.get_count() % 2])
56     t.add_successor(execs[t.get_count() % 2 - 1])
57
58 if __name__ == '__main__':
59     args = parse()
60     e = Engine(sys.argv)
61     e.load_platform(args.platform)
62
63     # Retrieve hosts
64     tremblay = e.host_by_name('Tremblay')
65     jupiter = e.host_by_name('Jupiter')
66     fafard = e.host_by_name('Fafard')
67
68     # Create tasks
69     comm0 = CommTask.init("comm0")
70     comm0.bytes = 1e7
71     comm0.source = tremblay
72     exec1 = ExecTask.init("exec1", 1e9, jupiter)
73     exec2 = ExecTask.init("exec2", 1e9, fafard)
74     comm1 = CommTask.init("comm1", 1e7, jupiter, tremblay)
75     comm2 = CommTask.init("comm2", 1e7, fafard, tremblay)
76
77     # Create the initial graph by defining dependencies between tasks
78     exec1.add_successor(comm1)
79     exec2.add_successor(comm2)
80
81     # Add a callback when tasks end for log purpose
82     Task.on_completion_cb(callback)
83
84     # Add a callback before each firing of comm0
85     # It switches the destination of comm0
86     comm0.on_this_start_cb(lambda t: switch_destination(t, [jupiter, fafard]))
87
88     # Add a callback before comm0 send tokens to successors
89     # It switches the successor of comm0
90     comm0.on_this_completion_cb(lambda t: switch_successor(t, [exec1,exec2]))
91
92     # Enqueue two firings for task exec1
93     comm0.enqueue_firings(4)
94
95     # runs the simulation
96     e.run()