Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Actually, read()=0 is not an issue in the AppSide
[simgrid.git] / docs / source / Tutorial_DAG.rst
1 .. _simdag:
2
3 Simulating DAG
4 ==============
5
6 This tutorial presents the basics to understand how DAG are represented in Simgrid and how to simulate their workflow. 
7
8 Definition of a DAG
9 -------------------
10
11 Directed Acyclic Graph: 
12
13 .. math::
14
15    \mathcal{G} = (\mathcal{V},\mathcal{E})
16
17 Set of vertices representing :ref:`Activities <API_s4u_Activity>`: 
18
19 .. math::
20
21    \mathcal{V} = {v_i | i = 1, ..., V}
22
23 Set of edges representing precedence constraints between :ref:`Activities <API_s4u_Activity>`: 
24
25 .. math::
26
27    \mathcal{E} = {e_i,j | (i,j) \in {1, ..., V} x {1, ..., V}}
28
29 .. image:: /tuto_dag/img/dag.svg
30    :align: center
31
32 Representing Vertices/Activities
33 ................................
34
35 There is two types of :ref:`Activities <API_s4u_Activity>` that can represent Vertices: :ref:`Exec <API_s4u_Exec>` and :ref:`Comm <API_s4u_Comm>`.
36 Thoses activities must be initiated and configured to properly describe your worflow.
37
38 An Exec represents the execution of an amount of flop on a :ref:`Host <API_s4u_Host>` of your platform.
39
40 .. code-block:: cpp
41
42    ExecPtr exec = Exec::init();
43    exec->set_flops_amount(int);
44    exec->set_host(Host*);
45    exec->start();
46
47 A Comm represents a data transfer between two :ref:`Hosts <API_s4u_Host>` of your platform. 
48
49 .. code-block:: cpp
50
51    CommPtr comm = Comm::sendto_init();
52    comm->set_source(Host*);
53    comm->set_destination(Host*);
54    comm->start();
55
56 Representing Edges/Dependencies
57 ...............................
58
59 An activity will not start until all of its dependencies have been completed.
60 Activities may have any number of successors.
61 Dependencies between Activities are created using :cpp:func:`Activity::add_successor(ActivityPtr)`.
62
63 .. code-block:: cpp
64
65    exec->add_successor(comm);
66
67 The Activity ``comm`` will not start until ``exec`` has been completed.
68
69 Lab 1: Basics
70 ---------------
71
72 The goal of this lab is to describe the following DAG: 
73
74 .. image:: /tuto_dag/img/dag1.svg
75    :align: center
76
77 In this DAG we want ``c1`` to compute 1e9 flops, ``c2`` to compute 5e9 flops and ``c3`` to compute 2e9 flops. 
78 There is also a data transfer of 5e8 bytes between ``c1`` and ``c3``.
79
80 First of all, include the Simgrid library and define the log category.
81
82 .. code-block:: cpp
83
84    #include "simgrid/s4u.hpp"
85
86    XBT_LOG_NEW_DEFAULT_CATEGORY(main, "Messages specific for this s4u tutorial");
87
88 Inside the ``main`` function create an instance of :ref:`Engine <API_s4u_Engine>` and load the platform.
89
90 .. code-block:: cpp
91
92     simgrid::s4u::Engine e(&argc, argv);
93     e.load_platform(argv[1]);
94
95 Retrieve pointers to some hosts.
96
97 .. code-block:: cpp
98
99     simgrid::s4u::Host* tremblay = e.host_by_name("Tremblay");
100     simgrid::s4u::Host* jupiter  = e.host_by_name("Jupiter");
101
102 Initiate the activities.
103
104 .. code-block:: cpp
105
106     simgrid::s4u::ExecPtr c1 = simgrid::s4u::Exec::init();
107     simgrid::s4u::ExecPtr c2 = simgrid::s4u::Exec::init();
108     simgrid::s4u::ExecPtr c3 = simgrid::s4u::Exec::init();
109     simgrid::s4u::CommPtr t1 = simgrid::s4u::Comm::sendto_init();
110
111 Give names to thoses activities.
112
113 .. code-block:: cpp
114
115     c1->set_name("c1");
116     c2->set_name("c2");
117     c3->set_name("c3");
118     t1->set_name("t1");
119
120 Set the amount of work for each activity.
121
122 .. code-block:: cpp
123
124     c1->set_flops_amount(1e9);
125     c2->set_flops_amount(5e9);
126     c3->set_flops_amount(2e9);
127     t1->set_payload_size(5e8);
128
129 Define the dependencies between the activities.
130
131 .. code-block:: cpp
132
133     c1->add_successor(t1);
134     t1->add_successor(c3);
135     c2->add_successor(c3);
136
137 Set the location of each Exec activity and source and destination for the Comm activity.
138
139 .. code-block:: cpp
140
141     c1->set_host(tremblay);
142     c2->set_host(jupiter);
143     c3->set_host(jupiter);
144     t1->set_source(tremblay);
145     t1->set_destination(jupiter);
146
147 Start the executions of Activities without dependencies.
148
149 .. code-block:: cpp
150
151     c1->start();
152     c2->start();
153
154 Add a callback to monitor the activities.
155
156 .. code-block:: cpp
157
158    Activity::on_completion_cb([](simgrid::s4u::Activity const& activity) {
159       XBT_INFO("Activity '%s' is complete (start time: %f, finish time: %f)", activity.get_cname(), activity.get_start_time(),
160                activity.get_finish_time());
161       });
162
163 Finally, run the simulation.
164
165 .. code-block:: cpp
166
167    e.run();
168
169 The execution of this code should give you the following output:
170
171 .. code-block:: bash
172
173    [10.194200] [main/INFO] Activity 'c1' is complete (start time: 0.000000, finish time: 10.194200)
174    [65.534235] [main/INFO] Activity 'c2' is complete (start time: 0.000000, finish time: 65.534235)
175    [85.283378] [main/INFO] Activity 't1' is complete (start time: 10.194200, finish time: 85.283378)
176    [111.497072] [main/INFO] Activity 'c3' is complete (start time: 85.283378, finish time: 111.497072)
177
178 Lab 2: Import a DAG from a file
179 ---------------
180
181 In this lab we present how to import a DAG into you Simgrid simulation, either using a DOT file, a JSON file, or a DAX file. 
182
183 The files presented in this lab describe the following DAG:
184
185 .. image:: /tuto_dag/img/dag2.svg
186    :align: center
187
188 From a DOT file
189 ...............
190
191 A DOT file describes a workflow in accordance with the graphviz format.
192
193 The following DOT file describes the workflow presented at the beginning of this lab:
194
195 .. code-block:: xml
196
197    digraph G {
198       c1 [size="1e9"];
199       c2 [size="5e9"];
200       c3 [size="2e9"];
201
202       root->c1 [size="2e8"];
203       root->c2 [size="1e8"];
204       c1->c3   [size="5e8"];
205       c2->c3   [size="-1"];
206       c3->end  [size="2e8"];
207    }
208
209 It can be imported as a vector of Activities into Simgrid using :cpp:func:`create_DAG_from_DOT(const std::string& filename)`. Then, you have to assign hosts to your Activities.
210
211 .. code-block:: cpp
212
213    #include "simgrid/s4u.hpp"
214
215    XBT_LOG_NEW_DEFAULT_CATEGORY(main, "Messages specific for this s4u example");
216
217    int main(int argc, char* argv[]) {
218       simgrid::s4u::Engine e(&argc, argv);
219       e.load_platform(argv[1]);
220
221       std::vector<simgrid::s4u::ActivityPtr> dag = simgrid::s4u::create_DAG_from_dot(argv[2]);
222
223       simgrid::s4u::Host* tremblay = e.host_by_name("Tremblay");
224       simgrid::s4u::Host* jupiter  = e.host_by_name("Jupiter");
225       simgrid::s4u::Host* fafard  = e.host_by_name("Fafard");
226
227       dynamic_cast<simgrid::s4u::Exec*>(dag[0].get())->set_host(fafard);
228       dynamic_cast<simgrid::s4u::Exec*>(dag[1].get())->set_host(tremblay);
229       dynamic_cast<simgrid::s4u::Exec*>(dag[2].get())->set_host(jupiter);
230       dynamic_cast<simgrid::s4u::Exec*>(dag[3].get())->set_host(jupiter);
231       dynamic_cast<simgrid::s4u::Exec*>(dag[8].get())->set_host(jupiter);
232     
233       for (const auto& a : dag) {
234          if (auto* comm = dynamic_cast<simgrid::s4u::Comm*>(a.get())) {
235                auto pred = dynamic_cast<simgrid::s4u::Exec*>((*comm->get_dependencies().begin()).get());
236                auto succ = dynamic_cast<simgrid::s4u::Exec*>(comm->get_successors().front().get());
237                comm->set_source(pred->get_host())->set_destination(succ->get_host());
238          }
239       }
240
241       simgrid::s4u::Activity::on_completion_cb([](simgrid::s4u::Activity const& activity) {
242       XBT_INFO("Activity '%s' is complete (start time: %f, finish time: %f)", activity.get_cname(), activity.get_start_time(),
243              activity.get_finish_time());
244       });
245
246       e.run();
247       return 0;
248    }
249
250 The execution of this code should give you the following output:
251
252 .. code-block:: bash
253
254    [0.000000] [main/INFO] Activity 'root' is complete (start time: 0.000000, finish time: 0.000000)
255    [33.394394] [main/INFO] Activity 'root->c2' is complete (start time: 0.000000, finish time: 33.394394)
256    [39.832311] [main/INFO] Activity 'root->c1' is complete (start time: 0.000000, finish time: 39.832311)
257    [50.026511] [main/INFO] Activity 'c1' is complete (start time: 39.832311, finish time: 50.026511)
258    [98.928629] [main/INFO] Activity 'c2' is complete (start time: 33.394394, finish time: 98.928629)
259    [125.115689] [main/INFO] Activity 'c1->c3' is complete (start time: 50.026511, finish time: 125.115689)
260    [151.329383] [main/INFO] Activity 'c3' is complete (start time: 125.115689, finish time: 151.329383)
261    [151.743605] [main/INFO] Activity 'c3->end' is complete (start time: 151.329383, finish time: 151.743605)
262    [151.743605] [main/INFO] Activity 'end' is complete (start time: 151.743605, finish time: 151.743605)
263
264 From a JSON file
265 ................
266
267 A JSON file describes a workflow in accordance with the `wfformat <https://github.com/wfcommons/wfformat>`_ .
268
269 The following JSON file describes the workflow presented at the beginning of this lab:
270
271 .. code-block:: JSON
272
273    {
274       "name": "simple_json",
275       "schemaVersion": "1.0",
276       "workflow": {
277          "makespan": 0,
278          "executedAt": "2023-03-09T00:00:00-00:00",
279          "tasks": [
280          {
281             "name": "c1",
282             "type": "compute",
283             "parents": [],
284             "runtime": 1e9,
285             "machine": "Tremblay"
286          },
287          {
288             "name": "t1",
289             "type": "transfer",
290             "parents": ["c1"],
291             "bytesWritten": 5e8,
292             "machine": "Jupiter"
293          },
294          {
295             "name": "c2",
296             "type": "compute",
297             "parents": [],
298             "runtime": 5e9,
299             "machine": "Jupiter"
300          },
301          {
302             "name": "c3",
303             "type": "compute",
304             "parents": ["t1","c2"],
305          "runtime": 2e9,
306          "machine": "Jupiter"
307          }
308          ],
309          "machines": [
310             {"nodeName": "Tremblay"},
311             {"nodeName": "Jupiter"}
312          ]
313       }
314    }
315
316 It can be imported as a vector of Activities into Simgrid using :cpp:func:`create_DAG_from_json(const std::string& filename)`. 
317
318 .. code-block:: cpp
319
320    #include "simgrid/s4u.hpp"
321
322    XBT_LOG_NEW_DEFAULT_CATEGORY(main, "Messages specific for this s4u example");
323
324    int main(int argc, char* argv[]) {
325       simgrid::s4u::Engine e(&argc, argv);
326       e.load_platform(argv[1]);
327
328       std::vector<simgrid::s4u::ActivityPtr> dag = simgrid::s4u::create_DAG_from_json(argv[2]);
329
330       simgrid::s4u::Activity::on_completion_cb([](simgrid::s4u::Activity const& activity) {
331       XBT_INFO("Activity '%s' is complete (start time: %f, finish time: %f)", activity.get_cname(), activity.get_start_time(),
332              activity.get_finish_time());
333       });
334
335       e.run();
336       return 0;
337    }
338
339 The execution of this code should give you the following output:
340
341 .. code-block:: bash
342
343    [10.194200] [main/INFO] Activity 'c1' is complete (start time: 0.000000, finish time: 10.194200)
344    [65.534235] [main/INFO] Activity 'c2' is complete (start time: 0.000000, finish time: 65.534235)
345    [85.283378] [main/INFO] Activity 't1' is complete (start time: 10.194200, finish time: 85.283378)
346    [111.497072] [main/INFO] Activity 'c3' is complete (start time: 85.283378, finish time: 111.497072)
347
348 From a DAX file [deprecated]
349 ............................
350
351 A DAX file describes a workflow in accordance with the `Pegasus <http://pegasus.isi.edu/>`_ format.
352
353 The following DAX file describes the workflow presented at the beginning of this lab:
354
355 .. code-block:: xml
356
357    <?xml version="1.0" encoding="UTF-8"?>
358    <adag xmlns="http://pegasus.isi.edu/schema/DAX" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
359       xsi:schemaLocation="http://pegasus.isi.edu/schema/DAX http://pegasus.isi.edu/schema/dax-2.1.xsd"
360       version="2.1">
361       <job id="1" name="c1" runtime="10">
362          <uses file="i1" link="input" register="true" transfer="true" optional="false" type="data" size="2e8"/>
363          <uses file="o1" link="output" register="true" transfer="true" optional="false" type="data" size="5e8"/>
364       </job>
365       <job id="2" name="c2" runtime="50">
366          <uses file="i2" link="input" register="true" transfer="true" optional="false" type="data" size="1e8"/>
367       </job>
368       <job id="3" name="c3" runtime="20">
369          <uses file="o1" link="input" register="true" transfer="true" optional="false" type="data" size="5e8"/>
370          <uses file="o3" link="output" register="true" transfer="true" optional="false" type="data" size="2e8"/>
371       </job>
372       <child ref="3">
373          <parent ref="1"/>
374          <parent ref="2"/>
375       </child>
376    </adag>
377
378 It can be imported as a vector of Activities into Simgrid using :cpp:func:`create_DAG_from_DAX(std::string)`.
379
380 .. code-block:: cpp
381
382    #include "simgrid/s4u.hpp"
383
384    XBT_LOG_NEW_DEFAULT_CATEGORY(main, "Messages specific for this s4u example");
385
386    int main(int argc, char* argv[]) {
387       simgrid::s4u::Engine e(&argc, argv);
388       e.load_platform(argv[1]);
389
390       std::vector<simgrid::s4u::ActivityPtr> dag = simgrid::s4u::create_DAG_from_DAX(argv[2]);
391
392       simgrid::s4u::Host* tremblay = e.host_by_name("Tremblay");
393       simgrid::s4u::Host* jupiter  = e.host_by_name("Jupiter");
394       simgrid::s4u::Host* fafard  = e.host_by_name("Fafard");
395
396       dynamic_cast<simgrid::s4u::Exec*>(dag[0].get())->set_host(fafard);
397       dynamic_cast<simgrid::s4u::Exec*>(dag[1].get())->set_host(tremblay);
398       dynamic_cast<simgrid::s4u::Exec*>(dag[2].get())->set_host(jupiter);
399       dynamic_cast<simgrid::s4u::Exec*>(dag[3].get())->set_host(jupiter);
400       dynamic_cast<simgrid::s4u::Exec*>(dag[8].get())->set_host(jupiter);
401     
402       for (const auto& a : dag) {
403          if (auto* comm = dynamic_cast<simgrid::s4u::Comm*>(a.get())) {
404             auto pred = dynamic_cast<simgrid::s4u::Exec*>((*comm->get_dependencies().begin()).get());
405             auto succ = dynamic_cast<simgrid::s4u::Exec*>(comm->get_successors().front().get());
406             comm->set_source(pred->get_host())->set_destination(succ->get_host());
407          }
408       }
409
410       simgrid::s4u::Activity::on_completion_cb([](simgrid::s4u::Activity const& activity) {
411       XBT_INFO("Activity '%s' is complete (start time: %f, finish time: %f)", activity.get_cname(), activity.get_start_time(),
412          activity.get_finish_time());
413       });
414
415       e.run();
416       return 0;
417    }
418