Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Replace non-breaking spaces.
[simgrid.git] / docs / source / app_smpi.rst
1 .. _SMPI_doc:
2
3 ===============================
4 SMPI: Simulate MPI Applications
5 ===============================
6
7 .. raw:: html
8
9    <object id="TOC" data="graphical-toc.svg" type="image/svg+xml"></object>
10    <script>
11    window.onload=function() { // Wait for the SVG to be loaded before changing it
12      var elem=document.querySelector("#TOC").contentDocument.getElementById("SMPIBox")
13      elem.style="opacity:0.93999999;fill:#ff0000;fill-opacity:0.1";
14      elem.style="opacity:0.93999999;fill:#ff0000;fill-opacity:0.1;stroke:#000000;stroke-width:0.35277778;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1";
15    }
16    </script>
17    <br/>
18    <br/>
19
20 SMPI enables the study of MPI application by emulating them on top of
21 the SimGrid simulator. This is particularly interesting to study
22 existing MPI applications within the comfort of the simulator.
23
24 To get started with SMPI, you should head to :ref:`the SMPI tutorial
25 <usecase_smpi>`. You may also want to read the `SMPI reference
26 article <https://hal.inria.fr/hal-01415484>`_ or these `introductory
27 slides <http://simgrid.org/tutorials/simgrid-smpi-101.pdf>`_.  If you
28 are new to MPI, you should first take our online `SMPI CourseWare
29 <https://simgrid.github.io/SMPI_CourseWare/>`_. It consists in several
30 projects that progressively introduce the MPI concepts. It proposes to
31 use SimGrid and SMPI to run the experiments, but the learning
32 objectives are centered on MPI itself.
33
34 Our goal is to enable the study of **unmodified MPI applications**.
35 Some constructs and features are still missing, but we can probably
36 add them on demand.  If you already used MPI before, SMPI should sound
37 very familiar to you: Use smpicc instead of mpicc, and smpirun instead
38 of mpirun. The main difference is that smpirun takes a :ref:`simulated
39 platform <platform>` as an extra parameter.
40
41 For **further scalability**, you may modify your code to speed up your
42 studies or save memory space.  Maximal **simulation accuracy**
43 requires some specific care from you.
44
45 .. _SMPI_online:
46
47 -----------------
48 Using SMPI online
49 -----------------
50
51 In this mode, your application is actually executed. Every computation
52 occurs for real while every communication is simulated. In addition,
53 the executions are automatically benchmarked so that their timings can
54 be applied within the simulator.
55
56 SMPI can also go offline by replaying a trace. :ref:`Trace replay
57 <SMPI_offline>` is usually ways faster than online simulation (because
58 the computation are skipped), but it can only applied to applications
59 with constant execution and communication patterns (for the exact same
60 reason).
61
62 ...................
63 Compiling your Code
64 ...................
65
66 If your application is in C, then simply use ``smpicc`` as a
67 compiler just like you use mpicc with other MPI implementations. This
68 script still calls your default compiler (gcc, clang, ...) and adds
69 the right compilation flags along the way. If your application is in
70 C++, Fortran 77 or Fortran 90, use respectively ``smpicxx``,
71 ``smpiff`` or ``smpif90``.
72
73 If you use cmake, set the variables ``MPI_C_COMPILER``, ``MPI_CXX_COMPILER`` and
74 ``MPI_Fortran_COMPILER`` to the full path of smpicc, smpicxx and smpiff (or
75 smpif90), respectively. Example:
76
77 .. code-block:: shell
78
79    cmake -DMPI_C_COMPILER=/opt/simgrid/bin/smpicc -DMPI_CXX_COMPILER=/opt/simgrid/bin/smpicxx -DMPI_Fortran_COMPILER=/opt/simgrid/bin/smpiff .
80
81 ....................
82 Simulating your Code
83 ....................
84
85 Use the ``smpirun`` script as follows:
86
87 .. code-block:: shell
88
89    smpirun -hostfile my_hostfile.txt -platform my_platform.xml ./program -blah
90
91 - ``my_hostfile.txt`` is a classical MPI hostfile (that is, this file
92   lists the machines on which the processes must be dispatched, one
93   per line)
94 - ``my_platform.xml`` is a classical SimGrid platform file. Of course,
95   the hosts of the hostfile must exist in the provided platform.
96 - ``./program`` is the MPI program to simulate, that you compiled with ``smpicc``
97 - ``-blah`` is a command-line parameter passed to this program.
98
99 ``smpirun`` accepts other parameters, such as ``-np`` if you don't
100 want to use all the hosts defined in the hostfile, ``-map`` to display
101 on which host each rank gets mapped of ``-trace`` to activate the
102 tracing during the simulation. You can get the full list by running
103 ``smpirun -help``
104
105 ...............................
106 Debugging your Code within SMPI
107 ...............................
108
109 If you want to explore the automatic platform and deployment files
110 that are generated by ``smpirun``, add ``-keep-temps`` to the command
111 line.
112
113 You can also run your simulation within valgrind or gdb using the
114 following commands. Once in GDB, each MPI ranks will be represented as
115 a regular thread, and you can explore the state of each of them as
116 usual.
117
118 .. code-block:: shell
119
120    smpirun -wrapper valgrind ...other args...
121    smpirun -wrapper "gdb --args" --cfg=contexts/factory:thread ...other args...
122
123 .. _SMPI_use_colls:
124
125 ................................
126 Simulating Collective Operations
127 ................................
128
129 MPI collective operations are crucial to the performance of MPI
130 applications and must be carefully optimized according to many
131 parameters. Every existing implementation provides several algorithms
132 for each collective operation, and selects by default the best suited
133 one, depending on the sizes sent, the number of nodes, the
134 communicator, or the communication library being used.  These
135 decisions are based on empirical results and theoretical complexity
136 estimation, and are very different between MPI implementations. In
137 most cases, the users can also manually tune the algorithm used for
138 each collective operation.
139
140 SMPI can simulate the behavior of several MPI implementations:
141 OpenMPI, MPICH, `STAR-MPI <http://star-mpi.sourceforge.net/>`_, and
142 MVAPICH2. For that, it provides 115 collective algorithms and several
143 selector algorithms, that were collected directly in the source code
144 of the targeted MPI implementations.
145
146 You can switch the automatic selector through the
147 ``smpi/coll-selector`` configuration item. Possible values:
148
149  - **ompi:** default selection logic of OpenMPI (version 3.1.2)
150  - **mpich**: default selection logic of MPICH (version 3.3b)
151  - **mvapich2**: selection logic of MVAPICH2 (version 1.9) tuned
152    on the Stampede cluster
153  - **impi**: preliminary version of an Intel MPI selector (version
154    4.1.3, also tuned for the Stampede cluster). Due the closed source
155    nature of Intel MPI, some of the algorithms described in the
156    documentation are not available, and are replaced by mvapich ones.
157  - **default**: legacy algorithms used in the earlier days of
158    SimGrid. Do not use for serious perform performance studies.
159
160 .. todo:: default should not even exist.
161
162 ....................
163 Available Algorithms
164 ....................
165
166 You can also pick the algorithm used for each collective with the
167 corresponding configuration item. For example, to use the pairwise
168 alltoall algorithm, one should add ``--cfg=smpi/alltoall:pair`` to the
169 line. This will override the selector (if any) for this algorithm.  It
170 means that the selected algorithm will be used
171
172 .. Warning:: Some collective may require specific conditions to be
173    executed correctly (for instance having a communicator with a power
174    of two number of nodes only), which are currently not enforced by
175    Simgrid. Some crashes can be expected while trying these algorithms
176    with unusual sizes/parameters
177
178 MPI_Alltoall
179 ^^^^^^^^^^^^
180
181 Most of these are best described in `STAR-MPI's white paper <https://doi.org/10.1145/1183401.1183431>`_.
182
183  - default: naive one, by default
184  - ompi: use openmpi selector for the alltoall operations
185  - mpich: use mpich selector for the alltoall operations
186  - mvapich2: use mvapich2 selector for the alltoall operations
187  - impi: use intel mpi selector for the alltoall operations
188  - automatic (experimental): use an automatic self-benchmarking algorithm
189  - bruck: Described by Bruck et.al. in <a href="http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=642949">this paper</a>
190  - 2dmesh: organizes the nodes as a two dimensional mesh, and perform allgather
191    along the dimensions
192  - 3dmesh: adds a third dimension to the previous algorithm
193  - rdb: recursive doubling: extends the mesh to a nth dimension, each one
194    containing two nodes
195  - pair: pairwise exchange, only works for power of 2 procs, size-1 steps,
196    each process sends and receives from the same process at each step
197  - pair_light_barrier: same, with small barriers between steps to avoid
198    contention
199  - pair_mpi_barrier: same, with MPI_Barrier used
200  - pair_one_barrier: only one barrier at the beginning
201  - ring: size-1 steps, at each step a process send to process (n+i)%size, and receives from (n-i)%size
202  - ring_light_barrier: same, with small barriers between some phases to avoid contention
203  - ring_mpi_barrier: same, with MPI_Barrier used
204  - ring_one_barrier: only one barrier at the beginning
205  - basic_linear: posts all receives and all sends,
206    starts the communications, and waits for all communication to finish
207  - mvapich2_scatter_dest: isend/irecv with scattered destinations, posting only a few messages at the same time
208
209 MPI_Alltoallv
210 ^^^^^^^^^^^^^
211  - default: naive one, by default
212  - ompi: use openmpi selector for the alltoallv operations
213  - mpich: use mpich selector for the alltoallv operations
214  - mvapich2: use mvapich2 selector for the alltoallv operations
215  - impi: use intel mpi selector for the alltoallv operations
216  - automatic (experimental): use an automatic self-benchmarking algorithm
217  - bruck: same as alltoall
218  - pair: same as alltoall
219  - pair_light_barrier: same as alltoall
220  - pair_mpi_barrier: same as alltoall
221  - pair_one_barrier: same as alltoall
222  - ring: same as alltoall
223  - ring_light_barrier: same as alltoall
224  - ring_mpi_barrier: same as alltoall
225  - ring_one_barrier: same as alltoall
226  - ompi_basic_linear: same as alltoall
227
228 MPI_Gather
229 ^^^^^^^^^^
230
231  - default: naive one, by default
232  - ompi: use openmpi selector for the gather operations
233  - mpich: use mpich selector for the gather operations
234  - mvapich2: use mvapich2 selector for the gather operations
235  - impi: use intel mpi selector for the gather operations
236  - automatic (experimental): use an automatic self-benchmarking algorithm which will iterate over all implemented versions and output the best
237  - ompi_basic_linear: basic linear algorithm from openmpi, each process sends to the root
238  - ompi_binomial: binomial tree algorithm
239  - ompi_linear_sync: same as basic linear, but with a synchronization at the
240    beginning and message cut into two segments.
241  - mvapich2_two_level: SMP-aware version from MVAPICH. Gather first intra-node (defaults to mpich's gather), and then exchange with only one process/node. Use mvapich2 selector to change these to tuned algorithms for Stampede cluster.
242
243 MPI_Barrier
244 ^^^^^^^^^^^
245
246  - default: naive one, by default
247  - ompi: use openmpi selector for the barrier operations
248  - mpich: use mpich selector for the barrier operations
249  - mvapich2: use mvapich2 selector for the barrier operations
250  - impi: use intel mpi selector for the barrier operations
251  - automatic (experimental): use an automatic self-benchmarking algorithm
252  - ompi_basic_linear: all processes send to root
253  - ompi_two_procs: special case for two processes
254  - ompi_bruck: nsteps = sqrt(size), at each step, exchange data with rank-2^k and rank+2^k
255  - ompi_recursivedoubling: recursive doubling algorithm
256  - ompi_tree: recursive doubling type algorithm, with tree structure
257  - ompi_doublering: double ring algorithm
258  - mvapich2_pair: pairwise algorithm
259  - mpich_smp: barrier intra-node, then inter-node
260
261 MPI_Scatter
262 ^^^^^^^^^^^
263
264  - default: naive one, by default
265  - ompi: use openmpi selector for the scatter operations
266  - mpich: use mpich selector for the scatter operations
267  - mvapich2: use mvapich2 selector for the scatter operations
268  - impi: use intel mpi selector for the scatter operations
269  - automatic (experimental): use an automatic self-benchmarking algorithm
270  - ompi_basic_linear: basic linear scatter
271  - ompi_binomial: binomial tree scatter
272  - mvapich2_two_level_direct: SMP aware algorithm, with an intra-node stage (default set to mpich selector), and then a basic linear inter node stage. Use mvapich2 selector to change these to tuned algorithms for Stampede cluster. 
273  - mvapich2_two_level_binomial: SMP aware algorithm, with an intra-node stage (default set to mpich selector), and then a binomial phase. Use mvapich2 selector to change these to tuned algorithms for Stampede cluster.
274
275 MPI_Reduce
276 ^^^^^^^^^^
277
278  - default: naive one, by default
279  - ompi: use openmpi selector for the reduce operations
280  - mpich: use mpich selector for the reduce operations
281  - mvapich2: use mvapich2 selector for the reduce operations
282  - impi: use intel mpi selector for the reduce operations
283  - automatic (experimental): use an automatic self-benchmarking algorithm
284  - arrival_pattern_aware: root exchanges with the first process to arrive
285  - binomial: uses a binomial tree
286  - flat_tree: uses a flat tree
287  - NTSL: Non-topology-specific pipelined linear-bcast function
288    0->1, 1->2 ,2->3, ....., ->last node: in a pipeline fashion, with segments
289    of 8192 bytes
290  - scatter_gather: scatter then gather
291  - ompi_chain: openmpi reduce algorithms are built on the same basis, but the
292    topology is generated differently for each flavor
293    chain = chain with spacing of size/2, and segment size of 64KB
294  - ompi_pipeline: same with pipeline (chain with spacing of 1), segment size
295    depends on the communicator size and the message size
296  - ompi_binary: same with binary tree, segment size of 32KB
297  - ompi_in_order_binary: same with binary tree, enforcing order on the
298    operations
299  - ompi_binomial: same with binomial algo (redundant with default binomial
300    one in most cases)
301  - ompi_basic_linear: basic algorithm, each process sends to root
302  - mvapich2_knomial: k-nomial algorithm. Default factor is 4 (mvapich2 selector adapts it through tuning)
303  - mvapich2_two_level: SMP-aware reduce, with default set to mpich both for intra and inter communicators. Use mvapich2 selector to change these to tuned algorithms for Stampede cluster.
304  - rab: `Rabenseifner <https://fs.hlrs.de/projects/par/mpi//myreduce.html>`_'s reduce algorithm
305
306 MPI_Allreduce
307 ^^^^^^^^^^^^^
308
309  - default: naive one, by default
310  - ompi: use openmpi selector for the allreduce operations
311  - mpich: use mpich selector for the allreduce operations
312  - mvapich2: use mvapich2 selector for the allreduce operations
313  - impi: use intel mpi selector for the allreduce operations
314  - automatic (experimental): use an automatic self-benchmarking algorithm
315  - lr: logical ring reduce-scatter then logical ring allgather
316  - rab1: variations of the  <a href="https://fs.hlrs.de/projects/par/mpi//myreduce.html">Rabenseifner</a> algorithm: reduce_scatter then allgather
317  - rab2: variations of the  <a href="https://fs.hlrs.de/projects/par/mpi//myreduce.html">Rabenseifner</a> algorithm: alltoall then allgather
318  - rab_rsag: variation of the  <a href="https://fs.hlrs.de/projects/par/mpi//myreduce.html">Rabenseifner</a> algorithm: recursive doubling
319    reduce_scatter then recursive doubling allgather
320  - rdb: recursive doubling
321  - smp_binomial: binomial tree with smp: binomial intra
322    SMP reduce, inter reduce, inter broadcast then intra broadcast
323  - smp_binomial_pipeline: same with segment size = 4096 bytes
324  - smp_rdb: intra: binomial allreduce, inter: Recursive
325    doubling allreduce, intra: binomial broadcast
326  - smp_rsag: intra: binomial allreduce, inter: reduce-scatter,
327    inter:allgather, intra: binomial broadcast
328  - smp_rsag_lr: intra: binomial allreduce, inter: logical ring
329    reduce-scatter, logical ring inter:allgather, intra: binomial broadcast
330  - smp_rsag_rab: intra: binomial allreduce, inter: rab
331    reduce-scatter, rab inter:allgather, intra: binomial broadcast
332  - redbcast: reduce then broadcast, using default or tuned algorithms if specified
333  - ompi_ring_segmented: ring algorithm used by OpenMPI
334  - mvapich2_rs: rdb for small messages, reduce-scatter then allgather else
335  - mvapich2_two_level: SMP-aware algorithm, with mpich as intra algorithm, and rdb as inter (Change this behavior by using mvapich2 selector to use tuned values)
336  - rab: default `Rabenseifner <https://fs.hlrs.de/projects/par/mpi//myreduce.html>`_ implementation
337
338 MPI_Reduce_scatter
339 ^^^^^^^^^^^^^^^^^^
340
341  - default: naive one, by default
342  - ompi: use openmpi selector for the reduce_scatter operations
343  - mpich: use mpich selector for the reduce_scatter operations
344  - mvapich2: use mvapich2 selector for the reduce_scatter operations
345  - impi: use intel mpi selector for the reduce_scatter operations
346  - automatic (experimental): use an automatic self-benchmarking algorithm
347  - ompi_basic_recursivehalving: recursive halving version from OpenMPI
348  - ompi_ring: ring version from OpenMPI
349  - mpich_pair: pairwise exchange version from MPICH
350  - mpich_rdb: recursive doubling version from MPICH
351  - mpich_noncomm: only works for power of 2 procs, recursive doubling for noncommutative ops
352
353
354 MPI_Allgather
355 ^^^^^^^^^^^^^
356
357  - default: naive one, by default
358  - ompi: use openmpi selector for the allgather operations
359  - mpich: use mpich selector for the allgather operations
360  - mvapich2: use mvapich2 selector for the allgather operations
361  - impi: use intel mpi selector for the allgather operations
362  - automatic (experimental): use an automatic self-benchmarking algorithm
363  - 2dmesh: see alltoall
364  - 3dmesh: see alltoall
365  - bruck: Described by Bruck et.al. in <a href="http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=642949">
366    Efficient algorithms for all-to-all communications in multiport message-passing systems</a>
367  - GB: Gather - Broadcast (uses tuned version if specified)
368  - loosely_lr: Logical Ring with grouping by core (hardcoded, default
369    processes/node: 4)
370  - NTSLR: Non Topology Specific Logical Ring
371  - NTSLR_NB: Non Topology Specific Logical Ring, Non Blocking operations
372  - pair: see alltoall
373  - rdb: see alltoall
374  - rhv: only power of 2 number of processes
375  - ring: see alltoall
376  - SMP_NTS: gather to root of each SMP, then every root of each SMP node
377    post INTER-SMP Sendrecv, then do INTRA-SMP Bcast for each receiving message,
378    using logical ring algorithm (hardcoded, default processes/SMP: 8)
379  - smp_simple: gather to root of each SMP, then every root of each SMP node
380    post INTER-SMP Sendrecv, then do INTRA-SMP Bcast for each receiving message,
381    using simple algorithm (hardcoded, default processes/SMP: 8)
382  - spreading_simple: from node i, order of communications is i -> i + 1, i ->
383    i + 2, ..., i -> (i + p -1) % P
384  - ompi_neighborexchange: Neighbor Exchange algorithm for allgather.
385    Described by Chen et.al. in  `Performance Evaluation of Allgather
386    Algorithms on Terascale Linux Cluster with Fast Ethernet <http://ieeexplore.ieee.org/xpl/articleDetails.jsp?tp=&arnumber=1592302>`_
387  - mvapich2_smp: SMP aware algorithm, performing intra-node gather, inter-node allgather with one process/node, and bcast intra-node
388
389 MPI_Allgatherv
390 ^^^^^^^^^^^^^^
391
392  - default: naive one, by default
393  - ompi: use openmpi selector for the allgatherv operations
394  - mpich: use mpich selector for the allgatherv operations
395  - mvapich2: use mvapich2 selector for the allgatherv operations
396  - impi: use intel mpi selector for the allgatherv operations
397  - automatic (experimental): use an automatic self-benchmarking algorithm
398  - GB: Gatherv - Broadcast (uses tuned version if specified, but only for Bcast, gatherv is not tuned)
399  - pair: see alltoall
400  - ring: see alltoall
401  - ompi_neighborexchange: see allgather
402  - ompi_bruck: see allgather
403  - mpich_rdb: recursive doubling algorithm from MPICH
404  - mpich_ring: ring algorithm from MPICh - performs differently from the  one from STAR-MPI
405
406 MPI_Bcast
407 ^^^^^^^^^
408
409  - default: naive one, by default
410  - ompi: use openmpi selector for the bcast operations
411  - mpich: use mpich selector for the bcast operations
412  - mvapich2: use mvapich2 selector for the bcast operations
413  - impi: use intel mpi selector for the bcast operations
414  - automatic (experimental): use an automatic self-benchmarking algorithm
415  - arrival_pattern_aware: root exchanges with the first process to arrive
416  - arrival_pattern_aware_wait: same with slight variation
417  - binomial_tree: binomial tree exchange
418  - flattree: flat tree exchange
419  - flattree_pipeline: flat tree exchange, message split into 8192 bytes pieces
420  - NTSB: Non-topology-specific pipelined binary tree with 8192 bytes pieces
421  - NTSL: Non-topology-specific pipelined linear with 8192 bytes pieces
422  - NTSL_Isend: Non-topology-specific pipelined linear with 8192 bytes pieces, asynchronous communications
423  - scatter_LR_allgather: scatter followed by logical ring allgather
424  - scatter_rdb_allgather: scatter followed by recursive doubling allgather
425  - arrival_scatter: arrival pattern aware scatter-allgather
426  - SMP_binary: binary tree algorithm with 8 cores/SMP
427  - SMP_binomial: binomial tree algorithm with 8 cores/SMP
428  - SMP_linear: linear algorithm with 8 cores/SMP
429  - ompi_split_bintree: binary tree algorithm from OpenMPI, with message split in 8192 bytes pieces
430  - ompi_pipeline: pipeline algorithm from OpenMPI, with message split in 128KB pieces
431  - mvapich2_inter_node: Inter node default mvapich worker
432  - mvapich2_intra_node: Intra node default mvapich worker
433  - mvapich2_knomial_intra_node:  k-nomial intra node default mvapich worker. default factor is 4.
434
435 Automatic Evaluation
436 ^^^^^^^^^^^^^^^^^^^^
437
438 .. warning:: This is still very experimental.
439
440 An automatic version is available for each collective (or even as a selector). This specific
441 version will loop over all other implemented algorithm for this particular collective, and apply
442 them while benchmarking the time taken for each process. It will then output the quickest for
443 each process, and the global quickest. This is still unstable, and a few algorithms which need
444 specific number of nodes may crash.
445
446 Adding an algorithm
447 ^^^^^^^^^^^^^^^^^^^
448
449 To add a new algorithm, one should check in the src/smpi/colls folder
450 how other algorithms are coded. Using plain MPI code inside Simgrid
451 can't be done, so algorithms have to be changed to use smpi version of
452 the calls instead (MPI_Send will become smpi_mpi_send). Some functions
453 may have different signatures than their MPI counterpart, please check
454 the other algorithms or contact us using the `>SimGrid
455 developers mailing list <http://lists.gforge.inria.fr/mailman/listinfo/simgrid-devel>`_.
456
457 Example: adding a "pair" version of the Alltoall collective.
458
459  - Implement it in a file called alltoall-pair.c in the src/smpi/colls folder. This file should include colls_private.hpp.
460
461  - The name of the new algorithm function should be smpi_coll_tuned_alltoall_pair, with the same signature as MPI_Alltoall.
462
463  - Once the adaptation to SMPI code is done, add a reference to the file ("src/smpi/colls/alltoall-pair.c") in the SMPI_SRC part of the DefinePackages.cmake file inside buildtools/cmake, to allow the file to be built and distributed.
464
465  - To register the new version of the algorithm, simply add a line to the corresponding macro in src/smpi/colls/cools.h ( add a "COLL_APPLY(action, COLL_ALLTOALL_SIG, pair)" to the COLL_ALLTOALLS macro ). The algorithm should now be compiled and be selected when using --cfg=smpi/alltoall:pair at runtime.
466
467  - To add a test for the algorithm inside Simgrid's test suite, juste add the new algorithm name in the ALLTOALL_COLL list found inside teshsuite/smpi/CMakeLists.txt . When running ctest, a test for the new algorithm should be generated and executed. If it does not pass, please check your code or contact us.
468
469  - Please submit your patch for inclusion in SMPI, for example through a pull request on GitHub or directly per email.
470
471
472 Tracing of Internal Communications
473 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
474
475 By default, the collective operations are traced as a unique operation
476 because tracing all point-to-point communications composing them could
477 result in overloaded, hard to interpret traces. If you want to debug
478 and compare collective algorithms, you should set the
479 ``tracing/smpi/internals`` configuration item to 1 instead of 0.
480
481 Here are examples of two alltoall collective algorithms runs on 16 nodes,
482 the first one with a ring algorithm, the second with a pairwise one.
483
484 .. image:: /img/smpi_simgrid_alltoall_ring_16.png
485    :align: center
486
487 Alltoall on 16 Nodes with the Ring Algorithm.
488
489 .. image:: /img/smpi_simgrid_alltoall_pair_16.png
490    :align: center
491
492 Alltoall on 16 Nodes with the Pairwise Algorithm.
493
494 -------------------------
495 What can run within SMPI?
496 -------------------------
497
498 You can run unmodified MPI applications (both C/C++ and Fortran) within
499 SMPI, provided that you only use MPI calls that we implemented. Global
500 variables should be handled correctly on Linux systems.
501
502 ....................
503 MPI coverage of SMPI
504 ....................
505
506 Our coverage of the interface is very decent, but still incomplete;
507 Given the size of the MPI standard, we may well never manage to
508 implement absolutely all existing primitives. Currently, we have
509 almost no support for I/O primitives, but we still pass a very large
510 amount of the MPICH coverage tests.
511
512 The full list of not yet implemented functions is documented in the
513 file `include/smpi/smpi.h
514 <https://framagit.org/simgrid/simgrid/tree/master/include/smpi/smpi.h>`_
515 in your version of SimGrid, between two lines containing the ``FIXME``
516 marker. If you really miss a feature, please get in touch with us: we
517 can guide you though the SimGrid code to help you implementing it, and
518 we'd be glad to integrate your contribution to the main project.
519
520 .. _SMPI_what_globals:
521
522 .................................
523 Privatization of global variables
524 .................................
525
526 Concerning the globals, the problem comes from the fact that usually,
527 MPI processes run as real UNIX processes while they are all folded
528 into threads of a unique system process in SMPI. Global variables are
529 usually private to each MPI process while they become shared between
530 the processes in SMPI.  The problem and some potential solutions are
531 discussed in this article: `Automatic Handling of Global Variables for
532 Multi-threaded MPI Programs
533 <http://charm.cs.illinois.edu/newPapers/11-23/paper.pdf>` (note that
534 this article does not deal with SMPI but with a competing solution
535 called AMPI that suffers of the same issue).  This point used to be
536 problematic in SimGrid, but the problem should now be handled
537 automatically on Linux.
538
539 Older versions of SimGrid came with a script that automatically
540 privatized the globals through static analysis of the source code. But
541 our implementation was not robust enough to be used in production, so
542 it was removed at some point. Currently, SMPI comes with two
543 privatization mechanisms that you can :ref:`select at runtime
544 <cfg=smpi/privatization>`.  The dlopen approach is used by
545 default as it is much faster and still very robust.  The mmap approach
546 is an older approach that proves to be slower.
547
548 With the **mmap approach**, SMPI duplicates and dynamically switch the
549 ``.data`` and ``.bss`` segments of the ELF process when switching the
550 MPI ranks. This allows each ranks to have its own copy of the global
551 variables.  No copy actually occurs as this mechanism uses ``mmap()``
552 for efficiency. This mechanism is considered to be very robust on all
553 systems supporting ``mmap()`` (Linux and most BSDs). Its performance
554 is questionable since each context switch between MPI ranks induces
555 several syscalls to change the ``mmap`` that redirects the ``.data``
556 and ``.bss`` segments to the copies of the new rank. The code will
557 also be copied several times in memory, inducing a slight increase of
558 memory occupation.
559
560 Another limitation is that SMPI only accounts for global variables
561 defined in the executable. If the processes use external global
562 variables from dynamic libraries, they won't be switched
563 correctly. The easiest way to solve this is to statically link against
564 the library with these globals. This way, each MPI rank will get its
565 own copy of these libraries. Of course you should never statically
566 link against the SimGrid library itself.
567
568 With the **dlopen approach**, SMPI loads several copies of the same
569 executable in memory as if it were a library, so that the global
570 variables get naturally duplicated. It first requires the executable
571 to be compiled as a relocatable binary, which is less common for
572 programs than for libraries. But most distributions are now compiled
573 this way for security reason as it allows one to randomize the address
574 space layout. It should thus be safe to compile most (any?) program
575 this way.  The second trick is that the dynamic linker refuses to link
576 the exact same file several times, be it a library or a relocatable
577 executable. It makes perfectly sense in the general case, but we need
578 to circumvent this rule of thumb in our case. To that extend, the
579 binary is copied in a temporary file before being re-linked against.
580 ``dlmopen()`` cannot be used as it only allows 256 contextes, and as it
581 would also duplicate simgrid itself.
582
583 This approach greatly speeds up the context switching, down to about
584 40 CPU cycles with our raw contextes, instead of requesting several
585 syscalls with the ``mmap()`` approach. Another advantage is that it
586 permits one to run the SMPI contexts in parallel, which is obviously not
587 possible with the ``mmap()`` approach. It was tricky to implement, but
588 we are not aware of any flaws, so smpirun activates it by default.
589
590 In the future, it may be possible to further reduce the memory and
591 disk consumption. It seems that we could `punch holes
592 <https://lwn.net/Articles/415889/>`_ in the files before dl-loading
593 them to remove the code and constants, and mmap these area onto a
594 unique copy. If done correctly, this would reduce the disk- and
595 memory- usage to the bare minimum, and would also reduce the pressure
596 on the CPU instruction cache. See the `relevant bug
597 <https://github.com/simgrid/simgrid/issues/137>`_ on github for
598 implementation leads.\n
599
600 Also, currently, only the binary is copied and dlopen-ed for each MPI
601 rank. We could probably extend this to external dependencies, but for
602 now, any external dependencies must be statically linked into your
603 application. As usual, simgrid itself shall never be statically linked
604 in your app. You don't want to give a copy of SimGrid to each MPI rank:
605 that's ways too much for them to deal with.
606
607 .. todo: speak of smpi/privatize-libs here
608
609 ----------------------------------------------
610 Adapting your MPI code for further scalability
611 ----------------------------------------------
612
613 As detailed in the `reference article
614 <http://hal.inria.fr/hal-01415484>`_, you may want to adapt your code
615 to improve the simulation performance. But these tricks may seriously
616 hinder the result quality (or even prevent the app to run) if used
617 wrongly. We assume that if you want to simulate an HPC application,
618 you know what you are doing. Don't prove us wrong!
619
620 ..............................
621 Reducing your memory footprint
622 ..............................
623
624 If you get short on memory (the whole app is executed on a single node when
625 simulated), you should have a look at the SMPI_SHARED_MALLOC and
626 SMPI_SHARED_FREE macros. It allows one to share memory areas between processes: The
627 purpose of these macro is that the same line malloc on each process will point
628 to the exact same memory area. So if you have a malloc of 2M and you have 16
629 processes, this macro will change your memory consumption from 2M*16 to 2M
630 only. Only one block for all processes.
631
632 If your program is ok with a block containing garbage value because all
633 processes write and read to the same place without any kind of coordination,
634 then this macro can dramatically shrink your memory consumption. For example,
635 that will be very beneficial to a matrix multiplication code, as all blocks will
636 be stored on the same area. Of course, the resulting computations will useless,
637 but you can still study the application behavior this way.
638
639 Naturally, this won't work if your code is data-dependent. For example, a Jacobi
640 iterative computation depends on the result computed by the code to detect
641 convergence conditions, so turning them into garbage by sharing the same memory
642 area between processes does not seem very wise. You cannot use the
643 SMPI_SHARED_MALLOC macro in this case, sorry.
644
645 This feature is demoed by the example file
646 `examples/smpi/NAS/dt.c <https://framagit.org/simgrid/simgrid/tree/master/examples/smpi/NAS/dt.c>`_
647
648 .. _SMPI_use_faster:
649
650 .........................
651 Toward Faster Simulations
652 .........................
653
654 If your application is too slow, try using SMPI_SAMPLE_LOCAL,
655 SMPI_SAMPLE_GLOBAL and friends to indicate which computation loops can
656 be sampled. Some of the loop iterations will be executed to measure
657 their duration, and this duration will be used for the subsequent
658 iterations. These samples are done per processor with
659 SMPI_SAMPLE_LOCAL, and shared between all processors with
660 SMPI_SAMPLE_GLOBAL. Of course, none of this will work if the execution
661 time of your loop iteration are not stable.
662
663 This feature is demoed by the example file
664 `examples/smpi/NAS/ep.c <https://framagit.org/simgrid/simgrid/tree/master/examples/smpi/NAS/ep.c>`_
665
666 .............................
667 Ensuring Accurate Simulations
668 .............................
669
670 Out of the box, SimGrid may give you fairly accurate results, but
671 there is a plenty of factors that could go wrong and make your results
672 inaccurate or even plainly wrong. Actually, you can only get accurate
673 results of a nicely built model, including both the system hardware
674 and your application. Such models are hard to pass over and reuse in
675 other settings, because elements that are not relevant to an
676 application (say, the latency of point-to-point communications,
677 collective operation implementation details or CPU-network
678 interaction) may be irrelevant to another application. The dream of
679 the perfect model, encompassing every aspects is only a chimera, as
680 the only perfect model of the reality is the reality. If you go for
681 simulation, then you have to ignore some irrelevant aspects of the
682 reality, but which aspects are irrelevant is actually
683 application-dependent...
684
685 The only way to assess whether your settings provide accurate results
686 is to double-check these results. If possible, you should first run
687 the same experiment in simulation and in real life, gathering as much
688 information as you can. Try to understand the discrepancies in the
689 results that you observe between both settings (visualization can be
690 precious for that). Then, try to modify your model (of the platform,
691 of the collective operations) to reduce the most preeminent differences.
692
693 If the discrepancies come from the computing time, try adapting the
694 ``smpi/host-speed``: reduce it if your simulation runs faster than in
695 reality. If the error come from the communication, then you need to
696 fiddle with your platform file.
697
698 Be inventive in your modeling. Don't be afraid if the names given by
699 SimGrid does not match the real names: we got very good results by
700 modeling multicore/GPU machines with a set of separate hosts
701 interconnected with very fast networks (but don't trust your model
702 because it has the right names in the right place either).
703
704 Finally, you may want to check `this article
705 <https://hal.inria.fr/hal-00907887>`_ on the classical pitfalls in
706 modeling distributed systems.
707
708 -------------------------
709 Troubleshooting with SMPI
710 -------------------------
711
712 .................................
713 ./configure refuses to use smpicc
714 .................................
715
716 If your ``./configure`` reports that the compiler is not
717 functional or that you are cross-compiling, try to define the
718 ``SMPI_PRETEND_CC`` environment variable before running the
719 configuration.
720
721 .. code-block:: shell
722
723    SMPI_PRETEND_CC=1 ./configure # here come the configure parameters
724    make
725
726 Indeed, the programs compiled with ``smpicc`` cannot be executed
727 without ``smpirun`` (they are shared libraries and do weird things on
728 startup), while configure wants to test them directly.  With
729 ``SMPI_PRETEND_CC`` smpicc does not compile as shared, and the SMPI
730 initialization stops and returns 0 before doing anything that would
731 fail without ``smpirun``.
732
733 .. warning::
734
735   Make sure that SMPI_PRETEND_CC is only set when calling ./configure,
736   not during the actual execution, or any program compiled with smpicc
737   will stop before starting.
738
739 ..............................................
740 ./configure does not pick smpicc as a compiler
741 ..............................................
742
743 In addition to the previous answers, some projects also need to be
744 explicitly told what compiler to use, as follows:
745
746 .. code-block:: shell
747
748    SMPI_PRETEND_CC=1 ./configure CC=smpicc # here come the other configure parameters
749    make
750
751 Maybe your configure is using another variable, such as ``cc`` (in
752 lower case) or similar. Just check the logs.
753
754 .....................................
755 error: unknown type name 'useconds_t'
756 .....................................
757
758 Try to add ``-D_GNU_SOURCE`` to your compilation line to get ride
759 of that error.
760
761 The reason is that SMPI provides its own version of ``usleep(3)``
762 to override it and to block in the simulation world, not in the real
763 one. It needs the ``useconds_t`` type for that, which is declared
764 only if you declare ``_GNU_SOURCE`` before including
765 ``unistd.h``. If your project includes that header file before
766 SMPI, then you need to ensure that you pass the right configuration
767 defines as advised above.
768
769
770
771 .. _SMPI_offline:
772
773 -----------------------------
774 Trace Replay and Offline SMPI
775 -----------------------------
776
777 Although SMPI is often used for :ref:`online simulation
778 <SMPI_online>`, where the application is executed for real, you can
779 also go for offline simulation through trace replay.
780
781 SimGrid uses time-independent traces, in which each actor is given a
782 script of the actions to do sequentially. These trace files can
783 actually be captured with the online version of SMPI, as follows:
784
785 .. code-block:: shell
786
787    $ smpirun -trace-ti --cfg=tracing/filename:LU.A.32 -np 32 -platform ../cluster_backbone.xml bin/lu.A.32
788
789 The produced trace is composed of a file ``LU.A.32`` and a folder
790 ``LU.A.32_files``. The file names don't match with the MPI ranks, but
791 that's expected.
792
793 To replay this with SMPI, you need to first compile the provided
794 ``smpi_replay.cpp`` file, that comes from
795 `simgrid/examples/smpi/replay
796 <https://framagit.org/simgrid/simgrid/tree/master/examples/smpi/replay>`_.
797
798 .. code-block:: shell
799
800    $ smpicxx ../replay.cpp -O3 -o ../smpi_replay
801
802 Afterward, you can replay your trace in SMPI as follows:
803
804    $ smpirun -np 32 -platform ../cluster_torus.xml -ext smpi_replay ../smpi_replay LU.A.32
805
806 All the outputs are gone, as the application is not really simulated
807 here. Its trace is simply replayed. But if you visualize the live
808 simulation and the replay, you will see that the behavior is
809 unchanged. The simulation does not run much faster on this very
810 example, but this becomes very interesting when your application
811 is computationally hungry.