doc: clean up syntax highlighting
[charm.git] / doc / ampi / manual.rst
1 ===================
2 Adaptive MPI (AMPI)
3 ===================
4
5 .. contents::
6    :depth: 3
7
8
9 Introduction
10 ============
11
12 This manual describes Adaptive MPI (AMPI), which is an implementation of
13 the MPI standard [1]_ on top of Charm++. AMPI acts as a regular MPI
14 implementation (akin to MPICH, OpenMPI, MVAPICH, etc.) with several
15 built-in extensions that allow MPI developers to take advantage of
16 Charm++’s dynamic runtime system, which provides support for process
17 virtualization, overlap of communication and computation, load
18 balancing, and fault tolerance with zero to minimal changes to existing
19 MPI codes.
20
21 In this manual, we first describe the philosophy behind Adaptive MPI,
22 then give a brief introduction to Charm++ and rationale for AMPI. We
23 then describe AMPI in detail. Finally we summarize the changes required
24 for existing MPI codes to run with AMPI. Appendices contain the details
25 of installing AMPI, and building and running AMPI programs.
26
27 Overview
28 --------
29
30 Developing parallel Computational Science and Engineering (CSE)
31 applications is a complex task. One has to implement the right physics,
32 develop or choose and code appropriate numerical methods, decide and
33 implement the proper input and output data formats, perform
34 visualizations, and be concerned with correctness and efficiency of the
35 programs. It becomes even more complex for multi-physics coupled
36 simulations, many of which are dynamic and adaptively refined so that
37 load imbalance becomes a major challenge. In addition to imbalance
38 caused by dynamic program behavior, hardware factors such as latencies,
39 variability, and failures must be tolerated by applications. Our
40 philosophy is to lessen the burden of application developers by
41 providing advanced programming paradigms and versatile runtime systems
42 that can handle many common programming and performance concerns
43 automatically and let application programmers focus on the actual
44 application content.
45
46 Many of these concerns can be addressed using the processor
47 virtualization and over-decomposition philosophy of Charm++. Thus, the
48 developer only sees virtual processors and lets the runtime system deal
49 with underlying physical processors. This is implemented in AMPI by
50 mapping MPI ranks to Charm++ user-level threads as illustrated in Figure
51 :numref:`fig_virt`. As an immediate and simple benefit, the
52 programmer can use as many virtual processors ("MPI ranks") as the
53 problem can be easily decomposed to. For example, suppose the problem
54 domain has :math:`n*2^n` parts that can be easily distributed but
55 programming for general number of MPI processes is burdensome, then the
56 developer can have :math:`n*2^n` virtual processors on any number of
57 physical ones using AMPI.
58
59 .. _fig_virt:
60 .. figure:: figs/virtualization.png
61    :width: 4.6in
62
63    MPI ranks are implemented as user-level threads in AMPI rather than
64    Operating System processes.
65
66
67
68 AMPI’s execution model consists of multiple user-level threads per
69 Processing Element (PE). The Charm++ scheduler coordinates execution of
70 these user-level threads (also called Virtual Processors or VPs) and
71 controls execution. These VPs can also migrate between PEs for the
72 purpose of load balancing or other reasons. The number of VPs per PE
73 specifies the virtualization ratio (degree of over-decomposition). For
74 example, in Figure :numref:`fig_virt` the virtualization ratio
75 is :math:`3.5` (there are four VPs on PE 0 and three VPs on PE 1).
76 Figure :numref:`fig_prac` shows how the problem domain can be
77 over-decomposed in AMPI’s VPs as opposed to other MPI implementations.
78
79 .. _fig_prac:
80 .. figure:: figs/prac.png
81    :width: 4.6in
82
83    The problem domain is over-decomposed to more VPs than PEs.
84
85
86
87 Another benefit of virtualization is communication and computation
88 overlap, which is automatically realized in AMPI without programming
89 effort. Techniques such as software pipelining require significant
90 programming effort to achieve this goal and improve performance.
91 However, one can use AMPI to have more virtual processors than physical
92 processors to overlap communication and computation. Each time a VP is
93 blocked for communication, the Charm++ scheduler picks the next VP among
94 those that are ready to execute. In this manner, while some of the VPs
95 of a physical processor are waiting for a message to arrive, others can
96 continue their execution. Thus, performance improves without any changes
97 to the application source code.
98
99 Another potential benefit is that of better cache utilization. With
100 over-decomposition, a smaller subdomain is accessed by a VP repeatedly
101 in different function calls before getting blocked by communication and
102 switching to another VP. That smaller subdomain may fit into cache if
103 over-decomposition is enough. This concept is illustrated in Figure
104 :numref:`fig_virt` where each AMPI rank’s subdomain is smaller
105 than the corresponding MPI subdomain and so may fit into cache memory.
106 Thus, there is a potential performance improvement without changing the
107 source code.
108
109 One important concern is that of load imbalance. New generation parallel
110 applications are dynamically varying, meaning that processors’ load is
111 shifting during execution. In a dynamic simulation application such as
112 rocket simulation, burning solid fuel, sub-scaling for a certain part of
113 the mesh, crack propagation, particle flows all contribute to load
114 imbalance. A centralized load balancing strategy built into an
115 application is impractical since each individual module is developed
116 mostly independently by various developers. In addition, embedding a
117 load balancing strategy in the code complicates it greatly, and
118 programming effort increases significantly. The runtime system is
119 uniquely positioned to deal with load imbalance. Figure
120 :numref:`fig_migrate` shows the runtime system migrating a VP
121 after detecting load imbalance. This domain may correspond to a weather
122 forecast model where there is a storm cell in the top-left quadrant,
123 which requires more computation to simulate. AMPI will then migrate VP 1
124 to balance the division of work across processors and improve
125 performance. Note that incorporating this sort of load balancing inside
126 the application code may take a lot of effort and complicate the code.
127
128 .. _fig_migrate:
129 .. figure:: figs/migrate.png
130    :width: 4.6in
131
132    AMPI can migrate VPs across processes for load balancing.
133
134
135
136 There are many different load balancing strategies built into Charm++
137 that can be selected by an AMPI application developer. Among those, some
138 may fit better for a particular application depending on its
139 characteristics. Moreover, one can write a new load balancer, best
140 suited for an application, by the simple API provided inside Charm++
141 infrastructure. Our approach is based on actual measurement of load
142 information at runtime, and on migrating computations from heavily
143 loaded to lightly loaded processors.
144
145 For this approach to be effective, we need the computation to be split
146 into pieces many more in number than available processors. This allows
147 us to flexibly map and re-map these computational pieces to available
148 processors. This approach is usually called "multi-domain
149 decomposition".
150
151 Charm++, which we use as a runtime system layer for the work described
152 here, simplifies our approach. It embeds an elaborate performance
153 tracing mechanism, a suite of plug-in load balancing strategies,
154 infrastructure for defining and migrating computational load, and is
155 interoperable with other programming paradigms.
156
157 Charm++
158 =======
159
160 Charm++ is an object-oriented parallel programming library for C. It
161 differs from traditional message passing programming libraries (such as
162 MPI) in that Charm++ is "message-driven". Message-driven parallel
163 programs do not block the processor waiting for a message to be
164 received. Instead, each message carries with itself a computation that
165 the processor performs on arrival of that message. The underlying
166 runtime system of Charm++ is called Converse, which implements a
167 "scheduler" that chooses which message to schedule next
168 (message-scheduling in Charm++ involves locating the object for which
169 the message is intended, and executing the computation specified in the
170 incoming message on that object). A parallel object in Charm++ is a C
171 object on which a certain computations can be asked to be performed from
172 remote processors.
173
174 Charm++ programs exhibit latency tolerance since the scheduler always
175 picks up the next available message rather than waiting for a particular
176 message to arrive. They also tend to be modular, because of their
177 object-based nature. Most importantly, Charm++ programs can be
178 *dynamically load balanced*, because the messages are directed at
179 objects and not at processors; thus allowing the runtime system to
180 migrate the objects from heavily loaded processors to lightly loaded
181 processors.
182
183 Since many CSE applications are originally written using MPI, one would
184 have to rewrite existing code if they were to be converted to Charm++ to
185 take advantage of dynamic load balancing and other Charm++ features.
186 This is indeed impractical. However, Converse - the runtime system of
187 Charm++ - supports interoperability between different parallel
188 programming paradigms such as parallel objects and threads. Using this
189 feature, we developed AMPI, which is described in more detail in the
190 next section.
191
192 AMPI
193 ====
194
195 AMPI utilizes the dynamic load balancing and other capabilities of
196 Charm++ by associating a "user-level" thread with each Charm++
197 migratable object. User’s code runs inside this thread, so that it can
198 issue blocking receive calls similar to MPI, and still present the
199 underlying scheduler an opportunity to schedule other computations on
200 the same processor. The runtime system keeps track of the computational
201 loads of each thread as well as the communication graph between AMPI
202 threads, and can migrate these threads in order to balance the overall
203 load while simultaneously minimizing communication overhead.
204
205 AMPI Compliance to MPI Standards
206 --------------------------------
207
208 Currently AMPI supports the MPI-2.2 standard, with preliminary support
209 for most MPI-3.1 features and a collection of extensions explained in
210 detail in this manual. One-sided communication calls in MPI-2 and MPI-3
211 are implemented, but they do not yet take advantage of RMA features.
212 Non-blocking collectives have been defined in AMPI since before
213 MPI-3.0’s adoption of them. Also ROMIO [2]_ has been integrated into
214 AMPI to support parallel I/O features.
215
216 AMPI Extensions to MPI Standards
217 --------------------------------
218
219 The following are AMPI extensions to the MPI standard, which will be
220 explained in detail in this manual. All AMPI extensions to the MPI
221 standard are prefixed with ``AMPI_`` rather than ``MPI_``. All
222 extensions are available in C, C++, and Fortran, with the exception of
223 ``AMPI_Command_argument_count`` and ``AMPI_Get_command_argument`` which
224 are only available in Fortran.
225
226 .. code-block:: none
227
228    AMPI_Migrate          AMPI_Register_pup            AMPI_Get_pup_data
229    AMPI_Migrate_to_pe    AMPI_Set_migratable          AMPI_Evacuate
230    AMPI_Load_set_value   AMPI_Load_start_measure      AMPI_Load_stop_measure
231    AMPI_Iget             AMPI_Iget_wait               AMPI_Iget_data
232    AMPI_Iget_free        AMPI_Type_is_contiguous      AMPI_Register_main
233    AMPI_Yield            AMPI_Suspend                 AMPI_Resume
234    AMPI_Alltoall_medium  AMPI_Alltoall_long
235    AMPI_Register_just_migrated         AMPI_Register_about_to_migrate
236    AMPI_Command_argument_count         AMPI_Get_command_argument
237
238 AMPI provides a set of built-in attributes on all communicators and
239 windows to find the number of the worker thread, process, or host that a
240 rank is currently running on, as well as the total number of worker
241 threads, processes, and hosts in the job. We define a worker thread to
242 be a thread on which one of more AMPI ranks are scheduled. We define a
243 process here as an operating system process, which may contain one or
244 more worker threads. The built-in attributes are ``AMPI_MY_WTH``,
245 ``AMPI_MY_PROCESS``, ``AMPI_NUM_WTHS``, and ``AMPI_NUM_PROCESSES``.
246 These attributes are accessible from any rank by calling
247 ``MPI_Comm_get_attr``, such as:
248
249 .. code-block:: fortran
250
251    ! Fortran:
252    integer :: my_wth, flag, ierr
253    call MPI_Comm_get_attr(MPI_COMM_WORLD, AMPI_MY_WTH, my_wth, flag, ierr)
254
255
256 .. code-block:: c++
257
258    // C/C++:
259    int my_wth, flag;
260    MPI_Comm_get_attr(MPI_COMM_WORLD, AMPI_MY_WTH, &my_wth, &flag);
261
262 AMPI also provides extra communicator types that users can pass to
263 ``MPI_Comm_split_type``: ``AMPI_COMM_TYPE_HOST`` for splitting a
264 communicator into disjoint sets of ranks that share the same physical
265 host, ``AMPI_COMM_TYPE_PROCESS`` for splitting a communicator into
266 disjoint sets of ranks that share the same operating system process, and
267 ``AMPI_COMM_TYPE_WTH``, for splitting a communicator into disjoint sets
268 of ranks that share the same worker thread.
269
270 For parsing Fortran command line arguments, AMPI Fortran programs should
271 use our extension APIs, which are similar to Fortran 2003’s standard
272 APIs. For example:
273
274 .. code-block:: fortran
275
276    integer :: i, argc, ierr
277    integer, parameter :: arg_len = 128
278    character(len=arg_len), dimension(:), allocatable :: raw_arguments
279
280    call AMPI_Command_argument_count(argc)
281    allocate(raw_arguments(argc))
282    do i = 1, size(raw_arguments)
283        call AMPI_Get_command_argument(i, raw_arguments(i), arg_len, ierr)
284    end do
285
286 Name for Main Program
287 ---------------------
288
289 To convert an existing program to use AMPI, the main function or program
290 may need to be renamed. The changes should be made as follows:
291
292 Fortran
293 ~~~~~~~
294
295 You must declare the main program as a subroutine called "MPI_MAIN". Do
296 not declare the main subroutine as a *program* because it will never be
297 called by the AMPI runtime.
298
299 .. code-block:: fortran
300
301    program pgm -> subroutine MPI_Main
302        ...                       ...
303    end program -> end subroutine
304
305 C or C++
306 ~~~~~~~~
307
308 The main function can be left as is, if ``mpi.h`` is included before the
309 main function. This header file has a preprocessor macro that renames
310 main, and the renamed version is called by the AMPI runtime by each
311 thread.
312
313 Global Variable Privatization
314 -----------------------------
315
316 For the before-mentioned benefits to be effective, one needs to map
317 multiple user-level threads onto each processor. Traditional MPI
318 programs assume that the entire processor is allocated to themselves,
319 and that only one thread of control exists within the process’s address
320 space. So, they may safely use global and static variables in the
321 program. However, global and static variables are problematic for
322 multi-threaded environments such as AMPI or OpenMP. This is because
323 there is a single instance of those variables so they will be shared
324 among different threads in the single address space, so if programmers
325 are not careful a wrong result may be produced by the program. Figure
326 :numref:`fig_global` shows an example of a multi-threaded
327 application with two threads in a single process. :math:`var` is a
328 global or static variable in this example. Thread 1 assigns a value to
329 it, then it gets blocked for communication and another thread can
330 continue. Thereby, thread 2 is scheduled next and accesses :math:`var`
331 which is wrong. The semantics of this program needs separate instances
332 of :math:`var` for each of the threads. That is where the need arises to
333 make some transformations to the original MPI program in order to run
334 correctly with AMPI. Note, this is the only change necessary to run an
335 MPI program with AMPI, that the program be thread-safe and have no
336 global or static variables whose values differ across different MPI
337 ranks. Also note that global variables that are constant or are only
338 written to once to the same value across all ranks during initialization
339 are already thread-safe.
340
341 .. _fig_global:
342 .. figure:: figs/global.png
343    :width: 4.6in
344
345    Mutable global or static variables are an issue for AMPI
346
347
348
349 The basic transformation needed to port the MPI program to AMPI is
350 privatization of global variables. With the MPI process model, each MPI
351 node can keep a copy of its own "permanent variables" - variables that
352 are accessible from more than one subroutines without passing them as
353 arguments. Module variables, "saved" subroutine local variables, and
354 common blocks in Fortran90 belong to this category. If such a program is
355 executed without privatization on AMPI, all the AMPI threads that reside
356 in the same process will access the same copy of such variables, which
357 is clearly not the desired semantics. To ensure correct execution of the
358 original source program, it is necessary to make such variables
359 "private" to individual threads. We provide three choices with varying
360 degrees of developer effort required and varying degrees of portability:
361 manual encapsulation of global state, a thread-local storage based
362 automated mechanism, and global offset table based automated mechanism.
363
364 Automatic Thread-Local Storage Swapping
365 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
366
367 Thread Local Store (TLS) was originally employed in kernel threads to
368 localize variables to threads and provide thread safety. It can be used
369 by annotating global/static variable declarations in C with
370 *thread_local*, in C with *__thread* or C11 with *thread_local* or
371 *_Thread_local*, and in Fortran with OpenMP’s *threadprivate*
372 attribute. OpenMP is required for using tlsglobals in Fortran code since
373 Fortran has no other method of using TLS. The *__thread* keyword is not
374 an official extension of the C language, though compiler writers are
375 encouraged to implement this feature.
376
377 It handles both global and static variables and has no context-switching
378 overhead. AMPI provides runtime support for privatizing thread-local
379 variables to user-level threads by changing the TLS segment register
380 when context switching between user-level threads. The runtime overhead
381 is that of changing a single pointer per user-level thread context
382 switch. Currently, Charm++ supports it for x86/x86_64 platforms when
383 using GNU compilers.
384
385 .. code-block:: c++
386
387    // C/C++ example:
388    int myrank;
389    double xyz[100];
390
391 .. code-block:: fortran
392
393    ! Fortran example:
394    integer :: myrank
395    real*8, dimension(100) :: xyz
396
397 For the example above, the following changes to the code handle the
398 global variables:
399
400 .. code-block:: c++
401
402    // C++ example:
403    thread_local int myrank;
404    thread_local double xyz[100];
405
406    // C example:
407    __thread int myrank;
408    __thread double xyz[100];
409
410 .. code-block:: fortran
411
412    ! Fortran example:
413    integer :: myrank
414    real*8, dimension(100) :: xyz
415    !$omp threadprivate(myrank)
416    !$omp threadprivate(xyz)
417
418 The runtime system also should know that TLS-Globals is used at both
419 compile and link time:
420
421 .. code-block:: bash
422
423    $ ampicxx -o example example.C -tlsglobals
424
425 Automatic Global Offset Table Swapping
426 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
427
428 Thanks to the ELF Object Format, we have successfully automated the
429 procedure of switching the set of user global variables when switching
430 thread contexts. Executable and Linkable Format (ELF) is a common
431 standard file format for Object Files in Unix-like operating systems.
432 ELF maintains a Global Offset Table (GOT) for globals so it is possible
433 to switch GOT contents at thread context-switch by the runtime system.
434
435 The only thing that the user needs to do is pass the flag
436 ``-swapglobals`` at both compile and link time (e.g. "ampicc -o prog
437 prog.c -swapglobals"). This method does not require any changes to the
438 source code and works with any language (C, C++, Fortran, etc). However,
439 it does not handle static variables, has a context switching overhead
440 that grows with the number of global variables, and is incompatible with
441 SMP builds of AMPI, where multiple virtual ranks can execute
442 simultaneously on different scheduler threads within an OS process.
443 Currently, this feature only works on x86 and x86_64 platforms that
444 fully support ELF, and it requires ld version 2.23 or older, or else a
445 patched version of ld 2.24+ that we provide here:
446 https://charm.cs.illinois.edu/gerrit/gitweb?p=libbfd-patches.git;a=tree;f=swapglobals
447
448 Manual Change
449 ~~~~~~~~~~~~~
450
451 We have employed a strategy of argument passing to do this privatization
452 transformation. That is, the global variables are bunched together in a
453 single user-defined type, which is allocated by each thread dynamically
454 or on the stack. Then a pointer to this type is passed from subroutine
455 to subroutine as an argument. Since the subroutine arguments are passed
456 on the stack, which is not shared across all threads, each subroutine
457 when executing within a thread operates on a private copy of the global
458 variables.
459
460 This scheme is demonstrated in the following examples. The original
461 Fortran90 code contains a module ``shareddata``. This module is used in
462 the ``MPI_MAIN`` subroutine and a subroutine ``subA``. Note that
463 ``PROGRAM PGM`` was renamed to ``SUBROUTINE MPI_MAIN`` and ``END PROGRAM``
464 was renamed to ``END SUBROUTINE``.
465
466 .. code-block:: fortran
467
468    !FORTRAN EXAMPLE
469    MODULE shareddata
470      INTEGER :: myrank
471      DOUBLE PRECISION :: xyz(100)
472    END MODULE
473
474    SUBROUTINE MPI_MAIN                               ! Previously PROGRAM PGM
475      USE shareddata
476      include 'mpif.h'
477      INTEGER :: i, ierr
478      CALL MPI_Init(ierr)
479      CALL MPI_Comm_rank(MPI_COMM_WORLD, myrank, ierr)
480      DO i = 1, 100
481        xyz(i) =  i + myrank
482      END DO
483      CALL subA
484      CALL MPI_Finalize(ierr)
485    END SUBROUTINE                                    ! Previously END PROGRAM
486
487    SUBROUTINE subA
488      USE shareddata
489      INTEGER :: i
490      DO i = 1, 100
491        xyz(i) = xyz(i) + 1.0
492      END DO
493    END SUBROUTINE
494
495 .. code-block:: c++
496
497    //C Example
498    #include <mpi.h>
499
500    int myrank;
501    double xyz[100];
502
503    void subA();
504    int main(int argc, char** argv){
505      int i;
506      MPI_Init(&argc, &argv);
507      MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
508      for(i=0;i<100;i++)
509        xyz[i] = i + myrank;
510      subA();
511      MPI_Finalize();
512    }
513
514    void subA(){
515      int i;
516      for(i=0;i<100;i++)
517        xyz[i] = xyz[i] + 1.0;
518    }
519
520 AMPI executes the main subroutine inside a user-level thread as a
521 subroutine.
522
523 Now we transform this program using the argument passing strategy. We
524 first group the shared data into a user-defined type.
525
526 .. code-block:: fortran
527
528    !FORTRAN EXAMPLE
529    MODULE shareddata
530      TYPE chunk ! modified
531        INTEGER :: myrank
532        DOUBLE PRECISION :: xyz(100)
533      END TYPE ! modified
534    END MODULE
535
536 .. code-block:: c++
537
538    //C Example
539    struct shareddata{
540      int myrank;
541      double xyz[100];
542    };
543
544 Now we modify the main subroutine to dynamically allocate this data and
545 change the references to them. Subroutine ``subA`` is then modified to
546 take this data as argument.
547
548 .. code-block:: fortran
549
550    !FORTRAN EXAMPLE
551    SUBROUTINE MPI_Main
552      USE shareddata
553      USE AMPI
554      INTEGER :: i, ierr
555      TYPE(chunk), pointer :: c ! modified
556      CALL MPI_Init(ierr)
557      ALLOCATE(c) ! modified
558      CALL MPI_Comm_rank(MPI_COMM_WORLD, c%myrank, ierr)
559      DO i = 1, 100
560        c%xyz(i) =  i + c%myrank ! modified
561      END DO
562      CALL subA(c)
563      CALL MPI_Finalize(ierr)
564    END SUBROUTINE
565
566    SUBROUTINE subA(c)
567      USE shareddata
568      TYPE(chunk) :: c ! modified
569      INTEGER :: i
570      DO i = 1, 100
571        c%xyz(i) = c%xyz(i) + 1.0 ! modified
572      END DO
573    END SUBROUTINE
574
575 .. code-block:: c++
576
577    //C Example
578    void MPI_Main{
579      int i,ierr;
580      struct shareddata *c;
581      ierr = MPI_Init();
582      c = (struct shareddata*)malloc(sizeof(struct shareddata));
583      ierr = MPI_Comm_rank(MPI_COMM_WORLD, c.myrank);
584      for(i=0;i<100;i++)
585        c.xyz[i] = i + c.myrank;
586      subA(c);
587      ierr = MPI_Finalize();
588    }
589
590    void subA(struct shareddata *c){
591      int i;
592      for(i=0;i<100;i++)
593        c.xyz[i] = c.xyz[i] + 1.0;
594    }
595
596 With these changes, the above program can be made thread-safe. Note that
597 it is not really necessary to dynamically allocate ``chunk``. One could
598 have declared it as a local variable in subroutine ``MPI_Main``. (Or for
599 a small example such as this, one could have just removed the
600 ``shareddata`` module, and instead declared both variables ``xyz`` and
601 ``myrank`` as local variables). This is indeed a good idea if shared
602 data are small in size. For large shared data, it would be better to do
603 heap allocation because in AMPI, the stack sizes are fixed at the
604 beginning (and can be specified from the command line) and stacks do not
605 grow dynamically.
606
607 Source-to-source Transformation
608 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
609
610 Another approach is to do the changes described in the previous scheme
611 automatically. It means that we can use a tool to transform the source
612 code to move global or static variables in an object and pass them
613 around. This approach is portable across systems and compilers and may
614 also improve locality and hence cache utilization. It also does not have
615 the context-switch overhead of swapping globals. We have multiple tools
616 for automating these transformations for different languages. Currently,
617 there is a tool called *Photran*\  [3]_ for refactoring Fortran codes
618 that can do this transformation. It is Eclipse-based and works by
619 constructing Abstract Syntax Trees (ASTs) of the program. We also have a
620 tool built on top of the *ROSE compiler*\  [4]_ that works for C/C++ and
621 Fortran programs that is available upon request. It emits patches for
622 all files containing global variables which can then be applied to the
623 source code.
624
625 Table :numref:`tab:portability` shows portability of
626 different schemes.
627
628 .. _tab:portability:
629 .. table:: Portability of current implementations of three privatization schemes. "Yes" means we have implemented this technique. "Maybe" indicates there are no theoretical problems, but no implementation exists. "No" indicates the technique is impossible on this platform.
630
631    ==================== === ====== ====== ==== ======= ===== =====
632    Privatization Scheme x86 x86_64 Mac OS BG/Q Windows PPC   ARM7
633    ==================== === ====== ====== ==== ======= ===== =====
634    Transformation       Yes Yes    Yes    Yes  Yes     Yes   Yes
635    GOT-Globals          Yes Yes    No     No   No      Yes   Yes
636    TLS-Globals          Yes Yes    Yes    No   Maybe   Maybe Maybe
637    ==================== === ====== ====== ==== ======= ===== =====
638
639 Extensions for Migrations
640 -------------------------
641
642 AMPI provides fully automated support for migrating MPI ranks between
643 nodes of a system without any application-specific code at all. We do so
644 using a memory allocator, Isomalloc, that allocates memory per
645 user-level thread to globally unique virtual memory addresses. This
646 means that every worker thread in the system reserves slices of virtual
647 memory for all user-level threads, allowing transparent migration of
648 stacks and pointers into memory (Isomalloc requires 64-bit virtual
649 memory addresses and support from the operating system for mapping
650 memory to arbitrary virtual addresses). Applications only need to link
651 with Isomalloc to enable automatic migratability, using *-memory
652 isomalloc*.
653
654 For systems that do not support Isomalloc and for users that wish to
655 have more fine-grain control over which application data structures will
656 be copied at migration time, we have added a few calls to AMPI. These
657 include the ability to register thread-specific data with the run-time
658 system, to pack and unpack all of the thread’s data, and to express
659 willingness to migrate.
660
661 Registering User Data
662 ~~~~~~~~~~~~~~~~~~~~~
663
664 When the AMPI runtime system decides that load imbalance exists within
665 the application, it will invoke one of its internal load balancing
666 strategies, which determines the new mapping of AMPI ranks so as to
667 balance the load. Then the AMPI runtime packs up the rank’s state and
668 moves it to its new home processor. AMPI packs up any internal data in
669 use by the rank, including the thread’s stack in use. This means that
670 the local variables declared in subroutines in a rank, which are created
671 on stack, are automatically packed up by the AMPI runtime system.
672 However, it has no way of knowing what other data are in use by the
673 rank. Thus upon starting execution, a rank needs to notify the system
674 about the data that it is going to use (apart from local variables).
675 Even with the data registration, AMPI cannot determine what size the
676 data is, or whether the registered data contains pointers to other
677 places in memory. For this purpose, a packing subroutine also needs to
678 be provided to the AMPI runtime system along with registered data. (See
679 next section for writing packing subroutines.) The call provided by AMPI
680 for doing this is ``AMPI_Register_pup``. This function takes three
681 arguments: a data item to be transported along with the rank, the pack
682 subroutine, and a pointer to an integer which denotes the registration
683 identifier. In C/C++ programs, it may be necessary to use this integer
684 value after migration completes and control returns to the rank with the
685 function ``AMPI_Get_pup_data``.
686
687 Migration
688 ~~~~~~~~~
689
690 The AMPI runtime system could detect load imbalance by itself and invoke
691 the load balancing strategy. However, since the application code is
692 going to pack/unpack the rank’s data, writing the pack subroutine will
693 be complicated if migrations occur at a stage unknown to the
694 application. For example, if the system decides to migrate a rank while
695 it is in initialization stage (say, reading input files), application
696 code will have to keep track of how much data it has read, what files
697 are open etc. Typically, since initialization occurs only once in the
698 beginning, load imbalance at that stage would not matter much.
699 Therefore, we want the demand to perform load balance check to be
700 initiated by the application.
701
702 AMPI provides a subroutine ``AMPI_Migrate(MPI_Info hints);`` for this
703 purpose. Each rank periodically calls ``AMPI_Migrate``. Typical CSE
704 applications are iterative and perform multiple time-steps. One should
705 call ``AMPI_Migrate`` in each rank at the end of some fixed number of
706 timesteps. The frequency of ``AMPI_Migrate`` should be determined by a
707 tradeoff between conflicting factors such as the load balancing
708 overhead, and performance degradation caused by load imbalance. In some
709 other applications, where application suspects that load imbalance may
710 have occurred, as in the case of adaptive mesh refinement; it would be
711 more effective if it performs a couple of timesteps before telling the
712 system to re-map ranks. This will give the AMPI runtime system some time
713 to collect the new load and communication statistics upon which it bases
714 its migration decisions. Note that ``AMPI_Migrate`` does NOT tell the
715 system to migrate the rank, but merely tells the system to check the
716 load balance after all the ranks call ``AMPI_Migrate``. To migrate the
717 rank or not is decided only by the system’s load balancing strategy.
718
719 Essentially, a call to ``AMPI_Migrate`` signifies to the runtime system
720 that the application has reached a point at which it is safe to
721 serialize the local state. Knowing this, the runtime system can act in
722 several ways.
723
724 The MPI_Info object taken as a parameter by ``AMPI_Migrate`` gives users
725 a way to influence the runtime system’s decision-making and behavior.
726 AMPI provides two built-in MPI_Info objects for this, called
727 ``AMPI_INFO_LB_SYNC`` and ``AMPI_INFO_LB_ASYNC``. Synchronous load
728 balancing assumes that the application is already at a synchronization
729 point. Asynchronous load balancing does not assume this.
730
731 Calling ``AMPI_Migrate`` on a rank with pending send requests (i.e. from
732 MPI_Isend) is currently not supported, therefore users should always
733 wait on any outstanding send requests before calling ``AMPI_Migrate``.
734
735 .. code-block:: c++
736
737    // Main time-stepping loop
738    for (int iter=0; iter < max_iters; iter++) {
739
740      // Time step work ...
741
742      if (iter % lb_freq == 0)
743        AMPI_Migrate(AMPI_INFO_LB_SYNC);
744    }
745
746 Note that migrating ranks around the cores and nodes of a system can
747 change which ranks share physical resources, such as memory. A
748 consequence of this is that communicators created via
749 ``MPI_Comm_split_type`` are invalidated by calls to ``AMPI_Migrate``
750 that result in migration which breaks the semantics of that communicator
751 type. The only valid routine to call on such communicators is
752 ``MPI_Comm_free``.
753
754 We also provide callbacks that user code can register with the runtime
755 system to be invoked just before and right after migration:
756 ``AMPI_Register_about_to_migrate`` and ``AMPI_Register_just_migrated``
757 respectively. Note that the callbacks are only invoked on those ranks
758 that are about to actually migrate or have just actually migrated.
759
760 AMPI provide routines for starting and stopping load measurements, and
761 for users to explicitly set the load value of a rank using the
762 following: ``AMPI_Load_start_measure``, ``AMPI_Load_stop_measure``,
763 ``AMPI_Load_reset_measure``, and ``AMPI_Load_set_value``. And since AMPI
764 builds on top of Charm++, users can experiment with the suite of load
765 balancing strategies included with Charm++, as well as write their own
766 strategies based on user-level information and heuristics.
767
768 Packing/Unpacking Thread Data
769 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
770
771 Once the AMPI runtime system decides which ranks to send to which
772 processors, it calls the specified pack subroutine for that rank, with
773 the rank-specific data that was registered with the system using
774 ``AMPI_Register_pup``. If an AMPI application uses Isomalloc, then the
775 system will define the Pack/Unpack routines for the user. This section
776 explains how a subroutine should be written for performing explicit
777 pack/unpack.
778
779 There are three steps for transporting the rank’s data to another
780 processor. First, the system calls a subroutine to get the size of the
781 buffer required to pack the rank’s data. This is called the "sizing"
782 step. In the next step, which is called immediately afterward on the
783 source processor, the system allocates the required buffer and calls the
784 subroutine to pack the rank’s data into that buffer. This is called the
785 "packing" step. This packed data is then sent as a message to the
786 destination processor, where first a rank is created (along with the
787 thread) and a subroutine is called to unpack the rank’s data from the
788 buffer. This is called the "unpacking" step.
789
790 Though the above description mentions three subroutines called by the
791 AMPI runtime system, it is possible to actually write a single
792 subroutine that will perform all the three tasks. This is achieved using
793 something we call a "pupper". A pupper is an external subroutine that is
794 passed to the rank’s pack-unpack-sizing subroutine, and this subroutine,
795 when called in different phases performs different tasks. An example
796 will make this clear:
797
798 Suppose the user data, chunk, is defined as a derived type in Fortran90:
799
800 .. code-block:: fortran
801
802    !FORTRAN EXAMPLE
803    MODULE chunkmod
804      INTEGER, parameter :: nx=4, ny=4, tchunks=16
805      TYPE, PUBLIC :: chunk
806          REAL(KIND=8) t(22,22)
807          INTEGER xidx, yidx
808          REAL(KIND=8), dimension(400):: bxm, bxp, bym, byp
809      END TYPE chunk
810    END MODULE
811
812 .. code-block:: c++
813
814    //C Example
815    struct chunk{
816      double t;
817      int xidx, yidx;
818      double bxm,bxp,bym,byp;
819    };
820
821 Then the pack-unpack subroutine ``chunkpup`` for this chunk module is
822 written as:
823
824 .. code-block:: fortran
825
826    !FORTRAN EXAMPLE
827    SUBROUTINE chunkpup(p, c)
828      USE pupmod
829      USE chunkmod
830      IMPLICIT NONE
831      INTEGER :: p
832      TYPE(chunk) :: c
833
834      call pup(p, c%t)
835      call pup(p, c%xidx)
836      call pup(p, c%yidx)
837      call pup(p, c%bxm)
838      call pup(p, c%bxp)
839      call pup(p, c%bym)
840      call pup(p, c%byp)
841    end subroutine
842
843 .. code-block:: c++
844
845    //C Example
846    void chunkpup(pup_er p, struct chunk c){
847      pup_double(p,c.t);
848      pup_int(p,c.xidx);
849      pup_int(p,c.yidx);
850      pup_double(p,c.bxm);
851      pup_double(p,c.bxp);
852      pup_double(p,c.bym);
853      pup_double(p,c.byp);
854    }
855
856 There are several things to note in this example. First, the same
857 subroutine ``pup`` (declared in module ``pupmod``) is called to
858 size/pack/unpack any type of data. This is possible because of procedure
859 overloading possible in Fortran90. Second is the integer argument ``p``.
860 It is this argument that specifies whether this invocation of subroutine
861 ``chunkpup`` is sizing, packing or unpacking. Third, the integer
862 parameters declared in the type ``chunk`` need not be packed or unpacked
863 since they are guaranteed to be constants and thus available on any
864 processor.
865
866 A few other functions are provided in module ``pupmod``. These functions
867 provide more control over the packing/unpacking process. Suppose one
868 modifies the ``chunk`` type to include allocatable data or pointers that
869 are allocated dynamically at runtime. In this case, when chunk is
870 packed, these allocated data structures should be deallocated after
871 copying them to buffers, and when chunk is unpacked, these data
872 structures should be allocated before copying them from the buffers. For
873 this purpose, one needs to know whether the invocation of ``chunkpup``
874 is a packing one or unpacking one. For this purpose, the ``pupmod``
875 module provides functions ``fpup_isdeleting``\ (``fpup_isunpacking``).
876 These functions return logical value ``.TRUE.`` if the invocation is for
877 packing (unpacking), and ``.FALSE.`` otherwise. The following example
878 demonstrates this:
879
880 Suppose the type ``dchunk`` is declared as:
881
882 .. code-block:: fortran
883
884    !FORTRAN EXAMPLE
885    MODULE dchunkmod
886      TYPE, PUBLIC :: dchunk
887          INTEGER :: asize
888          REAL(KIND=8), pointer :: xarr(:), yarr(:)
889      END TYPE dchunk
890    END MODULE
891
892 .. code-block:: c++
893
894    //C Example
895    struct dchunk{
896      int asize;
897      double* xarr, *yarr;
898    };
899
900 Then the pack-unpack subroutine is written as:
901
902 .. code-block:: fortran
903
904    !FORTRAN EXAMPLE
905    SUBROUTINE dchunkpup(p, c)
906      USE pupmod
907      USE dchunkmod
908      IMPLICIT NONE
909      INTEGER :: p
910      TYPE(dchunk) :: c
911
912      pup(p, c%asize)
913
914      IF (fpup_isunpacking(p)) THEN       !! if invocation is for unpacking
915        allocate(c%xarr(c%asize))
916        ALLOCATE(c%yarr(c%asize))
917      ENDIF
918
919      pup(p, c%xarr)
920      pup(p, c%yarr)
921
922      IF (fpup_isdeleting(p)) THEN        !! if invocation is for packing
923        DEALLOCATE(c%xarr)
924        DEALLOCATE(c%yarr)
925      ENDIF
926
927
928    END SUBROUTINE
929
930 .. code-block:: c++
931
932    //C Example
933    void dchunkpup(pup_er p, struct dchunk c){
934      pup_int(p,c.asize);
935      if(pup_isUnpacking(p)){
936        c.xarr = (double *)malloc(sizeof(double)*c.asize);
937        c.yarr = (double *)malloc(sizeof(double)*c.asize);
938      }
939      pup_doubles(p,c.xarr,c.asize);
940      pup_doubles(p,c.yarr,c.asize);
941      if(pup_isPacking(p)){
942        free(c.xarr);
943        free(c.yarr);
944      }
945    }
946
947 One more function ``fpup_issizing`` is also available in module
948 ``pupmod`` that returns ``.TRUE.`` when the invocation is a sizing one.
949 In practice one almost never needs to use it.
950
951 Charm++ also provides higher-level PUP routines for C++ STL data
952 structures and Fortran90 data types. The STL PUP routines will deduce
953 the size of the structure automatically, so that the size of the data
954 does not have to be passed in to the PUP routine. This facilitates
955 writing PUP routines for large pre-existing codebases. To use it, simply
956 include pup_stl.h in the user code. For modern Fortran with pointers and
957 allocatable data types, AMPI provides a similarly automated PUP
958 interface called apup. User code can include pupmod and then call apup()
959 on any array (pointer or allocatable, multi-dimensional) of built-in
960 types (character, short, int, long, real, double, complex, double
961 complex, logical) and the runtime will deduce the size and shape of the
962 array, including unassociated and NULL pointers. Here is the dchunk
963 example from earlier, written to use the apup interface:
964
965 .. code-block:: fortran
966
967    !FORTRAN EXAMPLE
968    SUBROUTINE dchunkpup(p, c)
969      USE pupmod
970      USE dchunkmod
971      IMPLICIT NONE
972      INTEGER :: p
973      TYPE(dchunk) :: c
974
975      !! no need for asize
976      !! no isunpacking allocation necessary
977
978      apup(p, c%xarr)
979      apup(p, c%yarr)
980
981      !! no isdeleting deallocation necessary
982
983    END SUBROUTINE
984
985 Calling ``MPI_`` routines or accessing global variables that have been
986 privatized by use of tlsglobals or swapglobals from inside a user PUP
987 routine is currently not allowed in AMPI. Users can store MPI-related
988 information like communicator rank and size in data structures to be be
989 packed and unpacked before they are needed inside a PUP routine.
990
991 Extensions for Checkpointing
992 ----------------------------
993
994 The pack-unpack subroutines written for migrations make sure that the
995 current state of the program is correctly packed (serialized) so that it
996 can be restarted on a different processor. Using the *same* subroutines,
997 it is also possible to save the state of the program to disk, so that if
998 the program were to crash abruptly, or if the allocated time for the
999 program expires before completing execution, the program can be
1000 restarted from the previously checkpointed state. Thus, the pack-unpack
1001 subroutines act as the key facility for checkpointing in addition to
1002 their usual role for migration. Just as in load balancing, no
1003 application specific code is required when using Isomalloc: the AMPI
1004 runtime takes care of all the details involved in migrating data.
1005
1006 To perform a checkpoint in an AMPI program, all you have to do is make a
1007 call to ``int AMPI_Migrate(MPI_Info hints)`` with an ``MPI_Info`` object
1008 that specifies how you would like to checkpoint. Checkpointing can be
1009 thought of as migrating AMPI ranks to storage. Users set the
1010 checkpointing policy on an ``MPI_Info`` object’s ``"ampi_checkpoint"``
1011 key to one of the following values: ``"to_file=directory_name"`` or
1012 ``"false"``. To perform checkpointing in memory a built-in MPI_Info
1013 object called ``AMPI_INFO_CHKPT_IN_MEMORY`` is provided.
1014
1015 Checkpointing to file tells the runtime system to save checkpoints in a
1016 given directory. (Typically, in an iterative program, the iteration
1017 number, converted to a character string, can serve as a checkpoint
1018 directory name.) This directory is created, and the entire state of the
1019 program is checkpointed to this directory. One can restart the program
1020 from the checkpointed state (using the same, more, or fewer physical
1021 processors than were checkpointed with) by specifying
1022 ``"+restart directory_name"`` on the command-line.
1023
1024 Checkpointing in memory allows applications to transparently tolerate
1025 failures online. The checkpointing scheme used here is a double
1026 in-memory checkpoint, in which virtual processors exchange checkpoints
1027 pairwise across nodes in each other’s memory such that if one node
1028 fails, that failed node’s AMPI ranks can be restarted by its buddy once
1029 the failure is detected by the runtime system. As long as no two buddy
1030 nodes fail in the same checkpointing interval, the system can restart
1031 online without intervention from the user (provided the job scheduler
1032 does not revoke its allocation). Any load imbalance resulting from the
1033 restart can then be managed by the runtime system. Use of this scheme is
1034 illustrated in the code snippet below.
1035
1036 .. code-block:: c++
1037
1038    // Main time-stepping loop
1039    for (int iter=0; iter < max_iters; iter++) {
1040
1041      // Time step work ...
1042
1043      if (iter % chkpt_freq == 0)
1044        AMPI_Migrate(AMPI_INFO_CHKPT_IN_MEMORY);
1045    }
1046
1047 A value of ``"false"`` results in no checkpoint being done that step.
1048 Note that ``AMPI_Migrate`` is a collective function, meaning every
1049 virtual processor in the program needs to call this subroutine with the
1050 same MPI_Info object. The checkpointing capabilities of AMPI are powered
1051 by the Charm++ runtime system. For more information about
1052 checkpoint/restart mechanisms please refer to the Charm++
1053 manual: :numref:`sec:checkpoint`.
1054
1055 Extensions for Memory Efficiency
1056 --------------------------------
1057
1058 MPI functions usually require the user to preallocate the data buffers
1059 needed before the functions being called. For unblocking communication
1060 primitives, sometimes the user would like to do lazy memory allocation
1061 until the data actually arrives, which gives the opportunities to write
1062 more memory efficient programs. We provide a set of AMPI functions as an
1063 extension to the standard MPI-2 one-sided calls, where we provide a
1064 split phase ``MPI_Get`` called ``AMPI_Iget``. ``AMPI_Iget`` preserves
1065 the similar semantics as ``MPI_Get`` except that no user buffer is
1066 provided to hold incoming data. ``AMPI_Iget_wait`` will block until the
1067 requested data arrives and runtime system takes care to allocate space,
1068 do appropriate unpacking based on data type, and return.
1069 ``AMPI_Iget_free`` lets the runtime system free the resources being used
1070 for this get request including the data buffer. Finally,
1071 ``AMPI_Iget_data`` is the routine used to access the data.
1072
1073 .. code-block:: c++
1074
1075
1076    int AMPI_Iget(MPI_Aint orgdisp, int orgcnt, MPI_Datatype orgtype, int rank,
1077                  MPI_Aint targdisp, int targcnt, MPI_Datatype targtype, MPI_Win win,
1078                  MPI_Request *request);
1079
1080    int AMPI_Iget_wait(MPI_Request *request, MPI_Status *status, MPI_Win win);
1081
1082    int AMPI_Iget_free(MPI_Request *request, MPI_Status *status, MPI_Win win);
1083
1084    int AMPI_Iget_data(void *data, MPI_Status status);
1085
1086 Extensions for Interoperability
1087 -------------------------------
1088
1089 Interoperability between different modules is essential for coding
1090 coupled simulations. In this extension to AMPI, each MPI application
1091 module runs within its own group of user-level threads distributed over
1092 the physical parallel machine. In order to let AMPI know which ranks are
1093 to be created, and in what order, a top level registration routine needs
1094 to be written. A real-world example will make this clear. We have an MPI
1095 code for fluids and another MPI code for solids, both with their main
1096 programs, then we first transform each individual code to run correctly
1097 under AMPI as standalone codes. Aside from the global and static
1098 variable privatization transformations needed, this also involves making
1099 the main program into a subroutine and naming it ``MPI_Main``.
1100
1101 Thus now, we have two ``MPI_Main``\ s, one for the fluids code and one
1102 for the solids code. We now make these codes co-exist within the same
1103 executable, by first renaming these ``MPI_Main``\ s as ``Fluids_Main``
1104 and ``Solids_Main``\  [5]_ writing a subroutine called ``MPI_Setup``.
1105
1106 .. code-block:: fortran
1107
1108    !FORTRAN EXAMPLE
1109    SUBROUTINE MPI_Setup
1110      USE ampi
1111      CALL AMPI_Register_main(Solids_Main)
1112      CALL AMPI_Register_main(Fluids_Main)
1113    END SUBROUTINE
1114
1115 .. code-block:: c++
1116
1117    //C Example
1118    void MPI_Setup(){
1119      AMPI_Register_main(Solids_Main);
1120      AMPI_Register_main(Fluids_Main);
1121    }
1122
1123 This subroutine is called from the internal initialization routines of
1124 AMPI and tells AMPI how many numbers of distinct modules exist, and
1125 which orchestrator subroutines they execute.
1126
1127 The number of ranks to create for each module is specified on the
1128 command line when an AMPI program is run. Appendix B explains how AMPI
1129 programs are run, and how to specify the number of ranks (``+vp``
1130 option). In the above case, suppose one wants to create 128 ranks of
1131 Solids and 64 ranks of Fluids on 32 physical processors, one would
1132 specify those with multiple ``+vp`` options on the command line as:
1133
1134 .. code-block:: bash
1135
1136    $ ./charmrun gen1.x +p 32 +vp 128 +vp 64
1137
1138 This will ensure that multiple modules representing different complete
1139 applications can co-exist within the same executable. They can also
1140 continue to communicate among their own ranks using the same AMPI
1141 function calls to send and receive with communicator argument as
1142 ``MPI_COMM_WORLD``. But this would be completely useless if these
1143 individual applications cannot communicate with each other, which is
1144 essential for building efficient coupled codes. For this purpose, we
1145 have extended the AMPI functionality to allow multiple
1146 "``COMM_WORLD``\ s"; one for each application. These *world
1147 communicators* form a "communicator universe" an array of communicators
1148 aptly called *MPI_COMM_UNIVERSE*. This array of communicators is indexed
1149 [1 . . . ``MPI_MAX_COMM``]. In the current implementation,
1150 ``MPI_MAX_COMM`` is 8, that is, maximum of 8 applications can co-exist
1151 within the same executable.
1152
1153 The order of these ``COMM_WORLD``\ s within ``MPI_COMM_UNIVERSE`` is
1154 determined by the order in which individual applications are registered
1155 in ``MPI_Setup``.
1156
1157 Thus, in the above example, the communicator for the Solids module would
1158 be ``MPI_COMM_UNIVERSE(1)`` and communicator for Fluids module would be
1159 ``MPI_COMM_UNIVERSE(2)``.
1160
1161 Now any rank within one application can communicate with any rank in the
1162 other application using the familiar send or receive AMPI calls by
1163 specifying the appropriate communicator and the rank number within that
1164 communicator in the call. For example if a Solids rank number 36 wants
1165 to send data to rank number 47 within the Fluids module, it calls:
1166
1167 .. code-block:: fortran
1168
1169    !FORTRAN EXAMPLE
1170    INTEGER , PARAMETER :: Fluids_Comm = 2
1171    CALL MPI_Send(InitialTime, 1, MPI_Double_Precision, tag,
1172                  47, MPI_Comm_Universe(Fluids_Comm), ierr)
1173
1174 .. code-block:: c++
1175
1176    //C Example
1177    int Fluids_Comm = 2;
1178    ierr = MPI_Send(InitialTime, 1, MPI_DOUBLE, tag,
1179                    47, MPI_Comm_Universe(Fluids_Comm));
1180
1181 The Fluids rank has to issue a corresponding receive call to receive
1182 this data:
1183
1184 .. code-block:: fortran
1185
1186    !FORTRAN EXAMPLE
1187    INTEGER , PARAMETER :: Solids_Comm = 1
1188    CALL MPI_Recv(InitialTime, 1, MPI_Double_Precision, tag,
1189                  36, MPI_Comm_Universe(Solids_Comm), stat, ierr)
1190
1191 .. code-block:: c++
1192
1193    //C Example
1194    int Solids_Comm = 1;
1195    ierr = MPI_Recv(InitialTime, 1, MPI_DOUBLE, tag,
1196                    36, MPI_Comm_Universe(Solids_Comm), &stat);
1197
1198 Charm++ Interoperability
1199 ------------------------
1200
1201 There is preliminary support for interoperating AMPI programs with Charm++
1202 programs. This allows users to launch an AMPI program with an arbitrary number
1203 of virtual processes in the same executable as a Charm++ program that contains
1204 arbitrary collections of chares, with both AMPI ranks and chares being co-scheduled
1205 by the runtime system. We also provide an entry method ``void injectMsg(int n, char buf[n])``
1206 for chares to communicate with AMPI ranks. An example program can be found in
1207 ``examples/charm++/AMPI-interop``.
1208
1209 Extensions for Sequential Re-run of a Parallel Node
1210 ---------------------------------------------------
1211
1212 In some scenarios, a sequential re-run of a parallel node is desired.
1213 One example is instruction-level accurate architecture simulations, in
1214 which case the user may wish to repeat the execution of a node in a
1215 parallel run in the sequential simulator. AMPI provides support for such
1216 needs by logging the change in the MPI environment on a certain
1217 processors. To activate the feature, build AMPI module with variable
1218 "AMPIMSGLOG" defined, like the following command in charm directory.
1219 (Linking with zlib "-lz" might be required with this, for generating
1220 compressed log file.)
1221
1222 .. code-block:: bash
1223
1224    $ ./build AMPI netlrts-linux-x86_64 -DAMPIMSGLOG
1225
1226 The feature is used in two phases: writing (logging) the environment and
1227 repeating the run. The first logging phase is invoked by a parallel run
1228 of the AMPI program with some additional command line options.
1229
1230 .. code-block:: bash
1231
1232    $ ./charmrun ./pgm +p4 +vp4 +msgLogWrite +msgLogRank 2 +msgLogFilename "msg2.log"
1233
1234 In the above example, a parallel run with 4 worker threads and 4 AMPI
1235 ranks will be executed, and the changes in the MPI environment of worker
1236 thread 2 (also rank 2, starting from 0) will get logged into diskfile
1237 "msg2.log".
1238
1239 Unlike the first run, the re-run is a sequential program, so it is not
1240 invoked by charmrun (and omitting charmrun options like +p4 and +vp4),
1241 and additional command line options are required as well.
1242
1243 .. code-block:: bash
1244
1245    $ ./pgm +msgLogRead +msgLogRank 2 +msgLogFilename "msg2.log"
1246
1247 User Defined Initial Mapping
1248 ----------------------------
1249
1250 You can define the initial mapping of virtual processors (vp) to
1251 physical processors (p) as a runtime option. You can choose from
1252 predefined initial mappings or define your own mappings. The following
1253 predefined mappings are available:
1254
1255 Round Robin
1256    This mapping scheme maps virtual processor to physical processor in
1257    round-robin fashion, i.e. if there are 8 virtual processors and 2
1258    physical processors then virtual processors indexed 0,2,4,6 will be
1259    mapped to physical processor 0 and virtual processors indexed 1,3,5,7
1260    will be mapped to physical processor 1.
1261
1262    .. code-block:: bash
1263
1264       $ ./charmrun ./hello +p2 +vp8 +mapping RR_MAP
1265
1266 Block Mapping
1267    This mapping scheme maps virtual processors to physical processor in
1268    ranks, i.e. if there are 8 virtual processors and 2 physical
1269    processors then virtual processors indexed 0,1,2,3 will be mapped to
1270    physical processor 0 and virtual processors indexed 4,5,6,7 will be
1271    mapped to physical processor 1.
1272
1273    .. code-block:: bash
1274
1275       $ ./charmrun ./hello +p2 +vp8 +mapping BLOCK_MAP
1276
1277 Proportional Mapping
1278    This scheme takes the processing capability of physical processors
1279    into account for mapping virtual processors to physical processors,
1280    i.e. if there are 2 processors running at different frequencies, then
1281    the number of virtual processors mapped to processors will be in
1282    proportion to their processing power. To make the load balancing
1283    framework aware of the heterogeneity of the system, the flag
1284    *+LBTestPESpeed* should also be used.
1285
1286    .. code-block:: bash
1287
1288       $ ./charmrun ./hello +p2 +vp8 +mapping PROP_MAP
1289       $ ./charmrun ./hello +p2 +vp8 +mapping PROP_MAP +balancer GreedyLB +LBTestPESpeed
1290
1291 If you want to define your own mapping scheme, please contact us for
1292 assistance.
1293
1294 Performance Visualization
1295 -------------------------
1296
1297 AMPI users can take advantage of Charm++’s tracing framework and
1298 associated performance visualization tool, Projections. Projections
1299 provides a number of different views of performance data that help users
1300 diagnose performance issues. Along with the traditional Timeline view,
1301 Projections also offers visualizations of load imbalance and
1302 communication-related data.
1303
1304 In order to generate tracing logs from an application to view in
1305 Projections, link with ``ampicc -tracemode projections``.
1306
1307 AMPI defines the following extensions for tracing support:
1308
1309 .. code-block:: none
1310
1311    AMPI_Trace_begin                      AMPI_Trace_end
1312
1313 When using the *Timeline* view in Projections, AMPI users can visualize
1314 what each VP on each processor is doing (what MPI method it is running
1315 or blocked in) by clicking the *View* tab and then selecting *Show
1316 Nested Bracketed User Events* from the drop down menu. See the
1317 Projections manual for information on performance analysis and
1318 visualization.
1319
1320 AMPI users can also use any tracing libraries or tools that rely on
1321 MPI’s PMPI profiling interface, though such tools may not be aware of
1322 AMPI process virtualization.
1323
1324 Compiling AMPI Programs
1325 -----------------------
1326
1327 AMPI provides a cross-platform compile-and-link script called *ampicc*
1328 to compile C, C++, and Fortran AMPI programs. This script resides in the
1329 ``bin`` subdirectory in the Charm++ installation directory. The main
1330 purpose of this script is to deal with the differences of various
1331 compiler names and command-line options across various machines on which
1332 AMPI runs. It is recommended that the AMPI compiler scripts be used to
1333 compile and link AMPI programs. One major advantage of using these is
1334 that one does not have to specify which libraries are to be linked for
1335 ensuring that C++ and Fortran90 codes are linked together correctly.
1336 Appropriate libraries required for linking such modules together are
1337 known to *ampicc* for various machines.
1338
1339 In spite of the platform-neutral syntax of *ampicc*, one may have to
1340 specify some platform-specific options for compiling and building AMPI
1341 codes. Fortunately, if *ampicc* does not recognize any particular
1342 options on its command line, it promptly passes it to all the individual
1343 compilers and linkers it invokes to compile the program. See the
1344 appendix for more details on building and running AMPI programs.
1345
1346 .. _adaptive-mpi-ampi-codes:
1347
1348 AMPI Example Applications
1349 -------------------------
1350
1351 | This section contains a list of applications that have been written or
1352   adapted to work with AMPI. Most applications are available on git:
1353 | ``git clone ssh://charm.cs.illinois.edu:9418/benchmarks/ampi-benchmarks``.
1354
1355 Most benchmarks can be compiled with the provided top-level Makefile:
1356
1357 .. code-block:: bash
1358
1359        $ git clone ssh://charm.cs.illinois.edu:9418/benchmarks/ampi-benchmarks
1360        $ cd ampi-benchmarks
1361        $ make -f Makefile.ampi
1362
1363 Mantevo project v3.0
1364 ~~~~~~~~~~~~~~~~~~~~
1365
1366 Set of mini-apps from the Mantevo project. Download at
1367 https://mantevo.org/download/.
1368
1369 MiniFE
1370 ^^^^^^
1371
1372 -  Mantevo mini-app for unstructured implicit Finite Element
1373    computations.
1374
1375 -  No changes necessary to source to run on AMPI. Modify file
1376    ``makefile.ampi`` and change variable ``AMPIDIR`` to point to your
1377    Charm++ directory, execute ``make -f makefile.ampi`` to build the
1378    program.
1379
1380 -  Refer to the ``README`` file on how to run the program. For example:
1381    ``./charmrun +p4 ./miniFE.x nx=30 ny=30 nz=30 +vp32``
1382
1383 MiniMD v2.0
1384 ^^^^^^^^^^^
1385
1386 -  Mantevo mini-app for particle interaction in a Lennard-Jones system,
1387    as in the LAMMPS MD code.
1388
1389 -  No changes necessary to source code. Modify file ``Makefile.ampi``
1390    and change variable ``AMPIDIR`` to point to your Charm++ directory,
1391    execute ``make ampi`` to build the program.
1392
1393 -  Refer to the ``README`` file on how to run the program. For example:
1394    ``./charmrun +p4 ./miniMD_ampi +vp32``
1395
1396 CoMD v1.1
1397 ^^^^^^^^^
1398
1399 -  Mantevo mini-app for molecular dynamics codes:
1400    https://github.com/exmatex/CoMD
1401
1402 -  To AMPI-ize it, we had to remove calls to not thread-safe
1403    ``getopt()``. Support for dynamic load balancing has been added in
1404    the main loop and the command line options. It will run on all
1405    platforms.
1406
1407 -  Just update the Makefile to point to AMPI compilers and run with the
1408    provided run scripts.
1409
1410 MiniXYCE v1.0
1411 ^^^^^^^^^^^^^
1412
1413 -  Mantevo mini-app for discrete analog circuit simulation, version 1.0,
1414    with serial, MPI, OpenMP, and MPI+OpenMP versions.
1415
1416 -  No changes besides Makefile necessary to run with virtualization. To
1417    build, do ``cp common/generate_info_header miniXyce_ref/.``, modify
1418    the CC path in ``miniXyce_ref/`` and run ``make``. Run scripts are in
1419    ``test/``.
1420
1421 -  Example run command:
1422    ``./charmrun +p3 ./miniXyce.x +vp3 -circuit ../tests/cir1.net -t_start 1e-6 -pf params.txt``
1423
1424 HPCCG v1.0
1425 ^^^^^^^^^^
1426
1427 -  Mantevo mini-app for sparse iterative solves using the Conjugate
1428    Gradient method for a problem similar to that of MiniFE.
1429
1430 -  No changes necessary except to set compilers in ``Makefile`` to the
1431    AMPI compilers.
1432
1433 -  Run with a command such as:
1434    ``./charmrun +p2 ./test_HPCCG 20 30 10 +vp16``
1435
1436 MiniAMR v1.0
1437 ^^^^^^^^^^^^
1438
1439 -  miniAMR applies a stencil calculation on a unit cube computational
1440    domain, which is refined over time.
1441
1442 -  No changes if using swap-globals. Explicitly extern global variables
1443    if using TLS.
1444
1445 Not yet AMPI-zed (reason):
1446 ^^^^^^^^^^^^^^^^^^^^^^^^^^
1447
1448 MiniAero v1.0 (build issues), MiniGhost v1.0.1 (globals), MiniSMAC2D
1449 v2.0 (globals), TeaLeaf v1.0 (globals), CloverLeaf v1.1 (globals),
1450 CloverLeaf3D v1.0 (globals).
1451
1452 LLNL ASC Proxy Apps
1453 ~~~~~~~~~~~~~~~~~~~
1454
1455 LULESH v2.0
1456 ^^^^^^^^^^^
1457
1458 -  LLNL Unstructured Lagrangian-Eulerian Shock Hydrodynamics proxy app:
1459    https://codesign.llnl.gov/lulesh.php
1460
1461 -  Charm++, MPI, MPI+OpenMP, Liszt, Loci, Chapel versions all exist for
1462    comparison.
1463
1464 -  Manually privatized version of LULESH 2.0, plus a version with PUP
1465    routines in subdirectory ``pup_lulesh202/``.
1466
1467 AMG 2013
1468 ^^^^^^^^
1469
1470 -  LLNL ASC proxy app: Algebraic Multi-Grid solver for linear systems
1471    arising from unstructured meshes:
1472    https://codesign.llnl.gov/amg2013.php
1473
1474 -  AMG is based on HYPRE, both from LLNL. The only change necessary to
1475    get AMG running on AMPI with virtualization is to remove calls to
1476    HYPRE’s timing interface, which is not thread-safe.
1477
1478 -  To build, point the CC variable in Makefile.include to your AMPI CC
1479    wrapper script and ``make``. Executable is ``test/amg2013``.
1480
1481 Lassen v1.0
1482 ^^^^^^^^^^^
1483
1484 -  LLNL ASC mini-app for wave-tracking applications with dynamic load
1485    imbalance. Reference versions are serial, MPI, Charm++, and
1486    MPI/Charm++ interop: https://codesign.llnl.gov/lassen.php
1487
1488 -  No changes necessary to enable AMPI virtualization. Requires some
1489    C++11 support. Set ``AMPIDIR`` in Makefile and ``make``. Run with:
1490    ``./charmrun +p4 ./lassen_mpi +vp8 default 2 2 2 50 50 50``
1491
1492 Kripke v1.1
1493 ^^^^^^^^^^^
1494
1495 -  LLNL ASC proxy app for ARDRA, a full Sn deterministic particle
1496    transport application: https://codesign.llnl.gov/kripke.php
1497
1498 -  Charm++, MPI, MPI+OpenMP, MPI+RAJA, MPI+CUDA, MPI+OCCA versions exist
1499    for comparison.
1500
1501 -  Kripke requires no changes between MPI and AMPI since it has no
1502    global/static variables. It uses cmake so edit the cmake toolchain
1503    files in ``cmake/toolchain/`` to point to the AMPI compilers, and
1504    build in a build directory:
1505
1506    .. code-block:: bash
1507
1508       $ mkdir build; cd build;
1509       $ cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain/linux-gcc-ampi.cmake
1510       -DENABLE_OPENMP=OFF
1511       $ make
1512
1513    Run with:
1514
1515    .. code-block:: bash
1516
1517       $ ./charmrun +p8 ./src/tools/kripke +vp8 --zones 64,64,64 --procs 2,2,2 --nest ZDG
1518
1519 MCB v1.0.3 (2013)
1520 ^^^^^^^^^^^^^^^^^
1521
1522 -  LLNL ASC proxy app for Monte Carlo particle transport codes:
1523    https://codesign.llnl.gov/mcb.php
1524
1525 -  MPI+OpenMP reference version.
1526
1527 -  Run with:
1528
1529    .. code-block:: bash
1530
1531       $ OMP_NUM_THREADS=1 ./charmrun +p4 ./../src/MCBenchmark.exe --weakScaling
1532        --distributedSource --nCores=1 --numParticles=20000 --multiSigma --nThreadCore=1 +vp16
1533
1534 .. _not-yet-ampi-zed-reason-1:
1535
1536 Not yet AMPI-zed (reason)
1537 ^^^^^^^^^^^^^^^^^^^^^^^^^
1538
1539 : UMT 2013 (global variables).
1540
1541 Other Applications
1542 ~~~~~~~~~~~~~~~~~~
1543
1544 MILC 7.0
1545 ^^^^^^^^
1546
1547 -  MILC is a code to study quantum chromodynamics (QCD) physics.
1548    http://www.nersc.gov/users/computational-systems/cori/nersc-8-procurement/trinity-nersc-8-rfp/nersc-8-trinity-benchmarks/milc/
1549
1550 -  Moved ``MPI_Init_thread`` call to ``main()``, added ``__thread`` to
1551    all global/static variable declarations. Runs on AMPI with
1552    virtualization when using -tlsglobals.
1553
1554 -  Build: edit ``ks_imp_ds/Makefile`` to use AMPI compiler wrappers, run
1555    ``make su3_rmd`` in ``ks_imp_ds/``
1556
1557 -  Run with: ``./su3_rmd +vp8 ../benchmark_n8/single_node/n8_single.in``
1558
1559 SNAP v1.01 (C version)
1560 ^^^^^^^^^^^^^^^^^^^^^^
1561
1562 -  LANL proxy app for PARTISN, an Sn deterministic particle transport
1563    application: https://github.com/losalamos/SNAP
1564
1565 -  SNAP is an update to Sweep3D. It simulates the same thing as Kripke,
1566    but with a different decomposition and slight algorithmic
1567    differences. It uses a 1- or 2-dimensional decomposition and the KBA
1568    algorithm to perform parallel sweeps over the 3-dimensional problem
1569    space. It contains all of the memory, computation, and network
1570    performance characteristics of a real particle transport code.
1571
1572 -  Original SNAP code is Fortran90-MPI-OpenMP, but this is a
1573    C-MPI-OpenMP version of it provided along with the original version.
1574    The Fortran90 version will require global variable privatization,
1575    while the C version works out of the box on all platforms.
1576
1577 -  Edit the Makefile for AMPI compiler paths and run with:
1578    ``./charmrun +p4 ./snap +vp4 --fi center_src/fin01 --fo center_src/fout01``
1579
1580 Sweep3D
1581 ^^^^^^^
1582
1583 -  Sweep3D is a *particle transport* program that analyzes the flux of
1584    particles along a space. It solves a three-dimensional particle
1585    transport problem.
1586
1587 -  This mini-app has been deprecated, and replaced at LANL by SNAP
1588    (above).
1589
1590 -  Build/Run Instructions:
1591
1592    -  Modify the ``makefile`` and change variable CHARMC to point to
1593       your Charm++ compiler command, execute ``make mpi`` to build the
1594       program.
1595
1596    -  Modify file ``input`` to set the different parameters. Refer to
1597       file ``README`` on how to change those parameters. Run with:
1598       ``./charmrun ./sweep3d.mpi +p8 +vp16``
1599
1600 PENNANT v0.8
1601 ^^^^^^^^^^^^
1602
1603 -  Unstructured mesh Rad-Hydro mini-app for a full application at LANL
1604    called FLAG. https://github.com/losalamos/PENNANT
1605
1606 -  Written in C++, only global/static variables that need to be
1607    privatized are mype and numpe. Done manually.
1608
1609 -  Legion, Regent, MPI, MPI+OpenMP, MPI+CUDA versions of PENNANT exist
1610    for comparison.
1611
1612 -  For PENNANT-v0.8, point CC in Makefile to AMPICC and just ’make’. Run
1613    with the provided input files, such as:
1614    ``./charmrun +p2 ./build/pennant +vp8 test/noh/noh.pnt``
1615
1616 Benchmarks
1617 ~~~~~~~~~~
1618
1619 Jacobi-2D (Fortran)
1620 ^^^^^^^^^^^^^^^^^^^
1621
1622 -  Jacobi-2D with 1D decomposition. Problem size and number of
1623    iterations are defined in the source code. Manually privatized.
1624
1625 Jacobi-3D (C)
1626 ^^^^^^^^^^^^^
1627
1628 -  Jacobi-3D with 3D decomposition. Manually privatized. Includes
1629    multiple versions: Isomalloc, PUP, FT, LB, Isend/Irecv, Iput/Iget.
1630
1631 NAS Parallel Benchmarks (NPB 3.3)
1632 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1633
1634 -  A collection of kernels used in different scientific applications.
1635    They are mainly implementations of various linear algebra methods.
1636    http://www.nas.nasa.gov/Resources/Software/npb.html
1637
1638 -  Build/Run Instructions:
1639
1640    -  Modify file ``config/make.def`` to make variable ``CHAMRDIR``
1641       point to the right Charm++ directory.
1642
1643    -  Use ``make <benchmark> NPROCS=<P> CLASS=<C>`` to build a
1644       particular benchmark. The values for ``<benchmark>`` are (bt, cg,
1645       dt, ep, ft, is, lu, mg, sp), ``<P>`` is the number of ranks and
1646       ``<C>`` is the class or the problem size (to be chosen from
1647       A,B,C,D or E). Some benchmarks may have restrictions on values of
1648       ``<P>`` and ``<C>``. For instance, to make CG benchmark with 256
1649       ranks and class C, we will use the following command:
1650       ``make cg NPROCS=256``
1651
1652    -  The resulting executable file will be generated in the respective
1653       directory for the benchmark. In the previous example, a file
1654       *cg.256.C* will appear in the *CG* and ``bin/`` directories. To
1655       run the particular benchmark, you must follow the standard
1656       procedure of running AMPI programs:
1657       ``./charmrun ./cg.C.256 +p64 +vp256 ++nodelist nodelist +isomalloc_sync``
1658
1659 NAS PB Multi-Zone Version (NPB-MZ 3.3)
1660 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1661
1662 -  A multi-zone version of BT, SP and LU NPB benchmarks. The multi-zone
1663    intentionally divides the space unevenly among ranks and causes load
1664    imbalance. The original goal of multi-zone versions was to offer an
1665    test case for hybrid MPI+OpenMP programming, where the load imbalance
1666    can be dealt with by increasing the number of threads in those ranks
1667    with more computation.
1668    http://www.nas.nasa.gov/Resources/Software/npb.html
1669
1670 -  The BT-MZ program shows the heaviest load imbalance.
1671
1672 -  Build/Run Instructions:
1673
1674    -  Modify file ``config/make.def`` to make variable ``CHAMRDIR``
1675       point to the right Charm++ build.
1676
1677    -  Use the format ``make <benchmark> NPROCS=<P> CLASS=<C>`` to build
1678       a particular benchmark. The values for ``<benchmark>`` are (bt-mz,
1679       lu-mz, sp-mz), ``<P>`` is the number of ranks and ``<C>`` is the
1680       class or the problem size (to be chosen from A,B,C,D or E). Some
1681       benchmarks may have restrictions on values of ``<P>`` and ``<C>``.
1682       For instance, to make the BT-MZ benchmark with 256 ranks and class
1683       C, you can use the following command:
1684       ``make bt-mz NPROCS=256 CLASS=C``
1685
1686    -  The resulting executable file will be generated in the *bin/*
1687       directory. In the previous example, a file *bt-mz.256.C* will be
1688       created in the ``bin`` directory. To run the particular benchmark,
1689       you must follow the standard procedure of running AMPI programs:
1690       ``./charmrun ./bt-mz.C.256 +p64 +vp256 ++nodelist nodelist +isomalloc_sync``
1691
1692 HPCG v3.0
1693 ^^^^^^^^^
1694
1695 -  High Performance Conjugate Gradient benchmark, version 3.0. Companion
1696    metric to Linpack, with many vendor-optimized implementations
1697    available: http://hpcg-benchmark.org/
1698
1699 -  No AMPI-ization needed. To build, modify ``setup/Make.AMPI`` for
1700    compiler paths, do
1701    ``mkdir build && cd build && configure ../setup/Make.AMPI && make``.
1702    To run, do ``./charmrun +p16 ./bin/xhpcg +vp64``
1703
1704 Intel Parallel Research Kernels (PRK) v2.16
1705 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1706
1707 -  A variety of kernels (Branch, DGEMM, Nstream, Random, Reduce, Sparse,
1708    Stencil, Synch_global, Synch_p2p, and Transpose) implemented for a
1709    variety of runtimes (SERIAL, OpenMP, MPI-1, MPI-RMA, MPI-SHM,
1710    MPI+OpenMP, SHMEM, FG_MPI, UPC, Grappa, Charm++, and AMPI).
1711    https://github.com/ParRes/Kernels
1712
1713 -  For AMPI tests, set ``CHARMTOP`` and run: ``make allampi``. There are
1714    run scripts included.
1715
1716 OSU Microbenchmarks
1717 ^^^^^^^^^^^^^^^^^^^
1718
1719 MPI collectives performance testing suite.
1720 https://charm.cs.illinois.edu/gerrit/#/admin/projects/benchmarks/osu-collectives-benchmarking
1721
1722 -  Build with: ``./configure CC=~/charm/bin/ampicc && make``
1723
1724 Third Party Open Source Libraries
1725 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1726
1727 HYPRE-2.11.1
1728 ^^^^^^^^^^^^
1729
1730 -  High Performance Preconditioners and solvers library from LLNL.
1731    https://computation.llnl.gov/project/linear_solvers/software.php
1732
1733 -  Hypre-2.11.1 builds on top of AMPI using the configure command:
1734
1735    .. code-block:: bash
1736
1737       $ ./configure --with-MPI \
1738             CC=~/charm/bin/ampicc \
1739             CXX=~/charm/bin/ampicxx \
1740             F77=~/charm/bin/ampif77 \
1741             --with-MPI-include=~/charm/include \
1742             --with-MPI-lib-dirs=~/charm/lib \
1743             --with-MPI-libs=mpi --without-timing --without-print-errors
1744       $ make -j8
1745
1746 -  All HYPRE tests and examples pass tests with virtualization,
1747    migration, etc. except for those that use Hypre’s timing interface,
1748    which uses a global variable internally. So just remove those calls
1749    and do not define ``HYPRE_TIMING`` when compiling a code that uses
1750    Hypre. In the examples directory, you’ll have to set the compilers to
1751    your AMPI compilers explicitly too. In the test directory, you’ll
1752    have to edit the Makefile to 1) Remove ``-DHYPRE_TIMING`` from both
1753    ``CDEFS`` and ``CXXDEFS``, 2) Remove both ``${MPILIBS}`` and
1754    ``${MPIFLAGS}`` from ``MPILIBFLAGS``, and 3) Remove ``${LIBS}`` from
1755    ``LIBFLAGS``. Then run ``make``.
1756
1757 -  To run the ``new_ij`` test, run:
1758    ``./charmrun +p64 ./new_ij -n 128 128 128 -P 4 4 4 -intertype 6 -tol 1e-8 -CF 0 -solver 61 -agg_nl 1 27pt -Pmx 6 -ns 4 -mu 1 -hmis -rlx 13 +vp64``
1759
1760 MFEM-3.2
1761 ^^^^^^^^
1762
1763 -  MFEM is a scalable library for Finite Element Methods developed at
1764    LLNL. http://mfem.org/
1765
1766 -  MFEM-3.2 builds on top of AMPI (and METIS-4.0.3 and HYPRE-2.11.1).
1767    Download MFEM,
1768    `HYPRE <https://computation.llnl.gov/project/linear_solvers/software.php>`__,
1769    and `METIS <http://glaros.dtc.umn.edu/gkhome/fsroot/sw/metis/OLD>`__.
1770    Untar all 3 in the same top-level directory.
1771
1772 -  Build HYPRE-2.11.1 as described above.
1773
1774 -  Build METIS-4.0.3 by doing ``cd metis-4.0.3/ && make``
1775
1776 -  Build MFEM-3.2 serial first by doing ``make serial``
1777
1778 -  Build MFEM-3.2 parallel by doing:
1779
1780    -  First, comment out ``#define HYPRE_TIMING`` in
1781       ``mfem/linalg/hypre.hpp``. Also, you must add a
1782       ``#define hypre_clearTiming()`` at the top of
1783       ``linalg/hypre.cpp``, because Hypre-2.11.1 has a bug where it
1784       doesn’t provide a definition of this function if you don’t define
1785       ``HYPRE_TIMING``.
1786
1787    -  ``make parallel MFEM_USE_MPI=YES MPICXX=~/charm/bin/ampicxx HYPRE_DIR=~/hypre-2.11.1/src/hypre METIS_DIR=~/metis-4.0.3``
1788
1789 -  To run an example, do
1790    ``./charmrun +p4 ./ex15p -m ../data/amr-quad.mesh +vp16``. You may
1791    want to add the runtime options ``-no-vis`` and ``-no-visit`` to
1792    speed things up.
1793
1794 -  All example programs and miniapps pass with virtualization, and
1795    migration if added.
1796
1797 XBraid-1.1
1798 ^^^^^^^^^^
1799
1800 -  XBraid is a scalable library for parallel time integration using
1801    MultiGrid, developed at LLNL.
1802    https://computation.llnl.gov/project/parallel-time-integration/software.php
1803
1804 -  XBraid-1.1 builds on top of AMPI (and its examples/drivers build on
1805    top of MFEM-3.2, HYPRE-2.11.1, and METIS-4.0.3 or METIS-5.1.0).
1806
1807 -  To build XBraid, modify the variables CC, MPICC, and MPICXX in
1808    makefile.inc to point to your AMPI compilers, then do ``make``.
1809
1810 -  To build XBraid’s examples/ and drivers/ modify the paths to MFEM and
1811    HYPRE in their Makefiles and ``make``.
1812
1813 -  To run an example, do
1814    ``./charmrun +p2 ./ex-02 -pgrid 1 1 8 -ml 15 -nt 128 -nx 33 33 -mi 100 +vp8 ++local``.
1815
1816 -  To run a driver, do
1817    ``./charmrun +p4 ./drive-03 -pgrid 2 2 2 2 -nl 32 32 32 -nt 16 -ml 15 +vp16 ++local``
1818
1819 Other AMPI codes
1820 ~~~~~~~~~~~~~~~~
1821
1822 -  FLASH
1823
1824 -  BRAMS (Weather prediction model)
1825
1826 -  CGPOP
1827
1828 -  Fractography3D (Crack Propagation)
1829
1830 -  JetAlloc
1831
1832 -  PlasComCM (XPACC)
1833
1834 -  PlasCom2 (XPACC)
1835
1836 -  Harm3D
1837
1838 Installing AMPI
1839 ===============
1840
1841 AMPI is included in the source distribution of Charm++. To get the
1842 latest sources from PPL, visit: http://charm.cs.illinois.edu/software
1843
1844 and follow the download links. Then build Charm++ and AMPI from source.
1845
1846 The build script for Charm++ is called ``build``. The syntax for this
1847 script is:
1848
1849 .. code-block:: bash
1850
1851    $ build <target> <version> <opts>
1852
1853 For building AMPI (which also includes building Charm++ and other
1854 libraries needed by AMPI), specify ``<target>`` to be ``AMPI``. And
1855 ``<opts>`` are command line options passed to the ``charmc`` compile
1856 script. Common compile time options such as
1857 ``-g, -O, -Ipath, -Lpath, -llib`` are accepted.
1858
1859 To build a debugging version of AMPI, use the option: ``-g``. To build a
1860 production version of AMPI, use the option: ``-with-production``.
1861
1862 ``<version>`` depends on the machine, operating system, and the
1863 underlying communication library one wants to use for running AMPI
1864 programs. See the charm/README file for details on picking the proper
1865 version. Here is an example of how to build a debug version of AMPI in a
1866 linux and ethernet environment:
1867
1868 .. code-block:: bash
1869
1870    $ ./build AMPI netlrts-linux-x86_64 -g
1871
1872 And the following is an example of how to build a production version of
1873 AMPI on a Cray XC system, with MPI-level error checking in AMPI turned
1874 off:
1875
1876 .. code-block:: bash
1877
1878    $ ./build AMPI gni-crayxc --with-production --disable-ampi-error-checking
1879
1880 AMPI can also be built with support for shared memory on any
1881 communication layer by adding "smp" as an option after the build target.
1882 For example, on an Infiniband Linux cluster:
1883
1884 .. code-block:: bash
1885
1886    $ ./build AMPI verbs-linux-x86_64 smp --with-production
1887
1888 AMPI ranks are implemented as user-level threads with a stack size
1889 default of 1MB. If the default is not correct for your program, you can
1890 specify a different default stack size (in bytes) at build time. The
1891 following build command illustrates this for an Intel Omni-Path system:
1892
1893 .. code-block:: bash
1894
1895    $ ./build AMPI ofi-linux-x86_64 --with-production -DTCHARM_STACKSIZE_DEFAULT=16777216
1896
1897 The same can be done for AMPI’s RDMA messaging threshold using
1898 ``AMPI_RDMA_THRESHOLD_DEFAULT`` and, for messages sent within the same
1899 address space (ranks on the same worker thread or ranks on different
1900 worker threads in the same process in SMP builds), using
1901 ``AMPI_SMP_RDMA_THRESHOLD_DEFAULT``. Contiguous messages with sizes
1902 larger than the threshold are sent via RDMA on communication layers that
1903 support this capability. You can also set the environment variables
1904 ``AMPI_RDMA_THRESHOLD`` and ``AMPI_SMP_RDMA_THRESHOLD`` before running a
1905 job to override the default specified at build time.
1906
1907 Building and Running AMPI Programs
1908 ==================================
1909
1910 Building AMPI Programs
1911 ----------------------
1912
1913 AMPI provides a compiler called *ampicc* in your charm/bin/ directory.
1914 You can use this compiler to build your AMPI program the same way as
1915 other compilers like cc. All the command line flags that you would use
1916 for other compilers can be used with the AMPI compilers the same way.
1917 For example:
1918
1919 .. code-block:: bash
1920
1921    $ ampicc -c pgm.c -O3
1922    $ ampif90 -c pgm.f90 -O0 -g
1923    $ ampicc -o pgm pgm.o -lm -O3
1924
1925 To use Isomalloc for transparently migrating user heap data, link with
1926 *-memory isomalloc*. To use a Charm++ load balancer, link a strategy or
1927 a suite of strategies in with *-module <LB>*. For example:
1928
1929 .. code-block:: bash
1930
1931    $ ampicc pgm.c -o pgm -O3 -memory isomalloc -module CommonLBs
1932
1933 Running AMPI programs
1934 ---------------------
1935
1936 AMPI offers two options to execute an AMPI program, ``charmrun`` and
1937 ``ampirun``.
1938
1939 Running with charmrun
1940 ~~~~~~~~~~~~~~~~~~~~~
1941
1942 The Charm++ distribution contains a script called ``charmrun`` that
1943 makes the job of running AMPI programs portable and easier across all
1944 parallel machines supported by Charm++. ``charmrun`` is copied to a
1945 directory where an AMPI program is built using ``ampicc``. It takes a
1946 command line parameter specifying number of processors, and the name of
1947 the program followed by AMPI options (such as number of ranks to create,
1948 and the stack size of every user-level thread) and the program
1949 arguments. A typical invocation of an AMPI program ``pgm`` with
1950 ``charmrun`` is:
1951
1952 .. code-block:: bash
1953
1954    $ ./charmrun +p16 ./pgm +vp64
1955
1956 Here, the AMPI program ``pgm`` is run on 16 physical processors with 64
1957 total virtual ranks (which will be mapped 4 per processor initially).
1958
1959 To run with load balancing, specify a load balancing strategy. If
1960 Address Space Layout Randomization is enabled on your target system, you
1961 may need to add the flag ``+isomalloc_sync`` when running with
1962 migration. You can also specify the size of user-level thread’s stack
1963 using the ``+tcharm_stacksize`` option, which can be used to decrease
1964 the size of the stack that must be migrated, as in the following
1965 example:
1966
1967 .. code-block:: bash
1968
1969    $ ./charmrun +p16 ./pgm +vp128 +tcharm_stacksize 32K +balancer RefineLB
1970
1971 Running with ampirun
1972 ~~~~~~~~~~~~~~~~~~~~
1973
1974 For compliance with the MPI standard and simpler execution, AMPI ships
1975 with the ``ampirun`` script that is similar to ``mpirun`` provided by
1976 other MPI runtimes. As with ``charmrun``, ``ampirun`` is copied
1977 automatically to the program directory when compiling an application
1978 with ``ampicc``.
1979
1980 The basic usage of ampirun is as follows:
1981
1982 .. code-block:: bash
1983
1984    $ ./ampirun -np 16 --host h1,h2,h3,h4 ./pgm
1985
1986 This command will create 16 (non-virtualized) ranks and distribute them
1987 on the hosts h1-h4.
1988
1989 When using the ``-vr`` option, AMPI will create the number of ranks
1990 specified by the ``-np`` parameter as virtual ranks, and will create
1991 only one process per host:
1992
1993 .. code-block:: bash
1994
1995    $ ./ampirun -np 16 --host h1,h2,h3,h4 -vr ./pgm
1996
1997 Other options (such as the load balancing strategy), can be specified in
1998 the same way as for charmrun:
1999
2000 .. code-block:: bash
2001
2002    $ ./ampirun -np 16 ./pgm +balancer RefineLB
2003
2004 Other options
2005 ~~~~~~~~~~~~~
2006
2007 Note that for AMPI programs compiled with gfortran, users may need to
2008 set the following environment variable to see program output to stdout:
2009
2010 .. code-block:: bash
2011
2012    $ export GFORTRAN_UNBUFFERED_ALL=1
2013
2014 .. [1]
2015    Currently, AMPI supports the MPI-2.2 standard, and the MPI-3.1
2016    standard is under active development, though we already support
2017    non-blocking and neighborhood collectives among other MPI-3.1
2018    features.
2019
2020 .. [2]
2021    http://www-unix.mcs.anl.gov/romio/
2022
2023 .. [3]
2024    http://www.eclipse.org/photran
2025
2026 .. [4]
2027    http://rosecompiler.org/
2028
2029 .. [5]
2030    Currently, we assume that the interface code, which does mapping and
2031    interpolation among the boundary values of Fluids and Solids domain,
2032    is integrated with one of Fluids and Solids.