Logo AND Algorithmique Numérique Distribuée

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