optimize chkp after ldb
[charm.git] / doc / ampi / manual.tex
1 \documentclass[10pt]{article}
2 \usepackage{../pplmanual,pst-node}
3 \input{../pplmanual}
4
5 \title{Adaptive MPI Manual}
6 \version{1.0}
7 \credits{
8 AMPI has been developed by Milind Bhandarkar with inputs from Gengbin Zheng and
9 Orion Lawlor. The derived data types (DDT) library, which AMPI uses for the
10 derived data types support, has been developed by Neelam Saboo. The current 
11 version of AMPI is maintained by Chao Huang.
12 }
13
14 \begin{document}
15 \maketitle
16
17 \section{Introduction}
18
19 This manual describes Adaptive MPI~(\ampi{}), which is an implementation of a
20 significant subset\footnote{Currently, 110 MPI-1.1 Standard functions have 
21 been implemented.} of MPI-1.1 Standard over \charmpp{}. \charmpp{} is a
22 \CC{}-based parallel programming library being developed by Prof. L. V. Kal\'{e} 
23 and his students back from 1992 until now at University of Illinois.
24
25 We first describe our philosophy behind this work (why we do what we do).
26 Later we give a brief introduction to \charmpp{} and rationale for \ampi{}
27 (tools of the trade). We then describe \ampi{} in detail. Finally we summarize the
28 changes required for original MPI codes to get them working with \ampi{}
29 (current state of our work). Appendices contain the gory details of installing
30 \ampi{}, building and running \ampi{} programs.
31
32 \subsection{Overview}
33
34 Developing parallel Computational Science and Engineering (CSE) applications is
35 a complex task. One has to implement the right physics, develop or choose and
36 code appropriate numerical methods, decide and implement the proper input and
37 output data formats, perform visualizations, and be concerned with correctness
38 and efficiency of the programs. It becomes even more complex for multi-physics
39 coupled simulations such as the solid propellant rocket simulation application. In addition, many applications
40  are dynamic and adaptively refined so load imbalance is a major challenge.
41 Our philosophy is to lessen the burden of the application developers by
42 providing advanced programming paradigms and versatile runtime systems that can
43 handle many common programming and performance concerns automatically and let the application
44 programmers focus on the actual application content.
45
46 Many of these concerns can be addressed using processor virtualization and 
47 over-decomposition philosophy of \charmpp{}. Thus, the developer only sees 
48 virtual processors and lets the runtime system deal with underlying physical 
49 processors. This is implemented in \ampi{} by mapping MPI ranks to \charmpp{} user-level
50  threads as illustrated in Figure\ref{fig_virt}. As an immediate and simple benefit, the programmer can use as 
51 many virtual processors ("MPI ranks") as the problem can be easily decomposed
52  to them. For example, suppose the problem domain has $n*2^n$ parts that can be
53   easily distributed but programming for general number of MPI processes is burdensome, 
54   then the developer can have $n*2^n$ virtual processors on any number of physical ones using \ampi{}.
55   
56 \begin{figure}[h]
57 \centering
58 \includegraphics[width=4.6in]{figs/virtualization.png}
59 \caption{MPI processes are implemented as user-level threads in \ampi{}}
60 \label{fig_virt}
61 \end{figure}
62
63 \ampi{}'s execution model consists of multiple user-level threads per process and,
64 typically, there is one process per physical processor. \charmpp{} scheduler coordinates
65 execution of these threads (also called Virtual Processors or VPs) and controls execution as shown in Figure \ref{fig_ratio}. These
66 VPs can also migrate between processors because of load balancing or other reasons.
67 The number of VPs per processor specifies the virtualization ratio (degree of over-decomposition). For example, in Figure \ref{fig_ratio} virtualization ratio is four (there are four VPs per each processor). Figure \ref{fig_prac} show how the problem domain is over-decomposed in \ampi{}'s VPs as opposed to other MPI implementations.
68
69 \begin{figure}[h]
70 \centering
71 \includegraphics[width=1.8in]{figs/ratio.png}
72 \caption{VPs are managed by \charmpp{} scheduler}
73 \label{fig_ratio}
74 \end{figure}
75
76 \begin{figure}[h]
77 \centering
78 \includegraphics[width=4.6in]{figs/prac.png}
79 \caption{Problem domain is over-decomposed to more VPs}
80 \label{fig_prac}
81 \end{figure}
82
83 Another benefit of virtualization is communication and computation overlap which 
84 is automatically achieved without programming effort. Techniques such as software 
85 pipelining require significant programming 
86 effort to achieve this goal and improve performance. However, one can use \ampi{} to 
87 have more virtual processors than physical processors to overlap communication and 
88 computation. Each time a VP is blocked for communication, \charmpp{} scheduler
89  picks the next VP among those that are ready to execute. In this manner, while
90  some of the VPs of a physical processor are 
91 waiting for a message to arrive, others can continue their execution. Thus, performance 
92 will be improved without any change to the source code.
93
94 A potential benefit is that of better cache utilization. With over-decomposition, a smaller subdomain is accessed by a VP repeatedly in different function calls before getting blocked by communication and switching to another VP. That smaller subdomain may fit into cache if over-decomposition is enough. This concept is illustrated in Figure \ref{fig_cache} where each \ampi{} subdomain (such as 12) is smaller than corresponding MPI subdomain (such as 3) and may fit into cache memory. Thus, there is a potential performance improvement without changing the source code.
95
96 \begin{figure}[h]
97 \centering
98 \includegraphics[width=4.6in]{figs/cache.png}
99 \caption{Smaller subdomains may fit into cache and result in better performance}
100 \label{fig_cache}
101 \end{figure}
102
103 One important concern is that of load imbalance. New generation parallel applications are 
104 dynamically varying, meaning that processors' load is shifting during execution. In a dynamic simulation application
105 such as rocket simulation, burning  solid fuel, sub-scaling for a certain part
106 of the mesh, crack propagation, particle flows all contribute to load
107 imbalance. Centralized load balancing strategy built into an application is
108 impractical since each individual modules are developed almost independently by
109 various developers. In addition, embedding a load balancing strategy in the code 
110 complicates it and programming effort increases significantly. Thus, the runtime 
111 system support for load balancing becomes even more critical. Figure \ref{fig_migrate} shows migration of a VP because of load imbalance. For instance, this domain may correspond to a weather forecast model where there is a tornado in top-left side, which requires more computation to simulate. \ampi{} will then migrate VP 13 to balance the division of work across processors and improve performance. Note that incorporating this sort of load balancing inside the application code may take a lot of effort and complicates the code.
112
113 \begin{figure}[h]
114 \centering
115 \includegraphics[width=4.6in]{figs/migrate.png}
116 \caption{\ampi{} migrates VPs across processors for load balancing}
117 \label{fig_migrate}
118 \end{figure}
119
120 There are different load balancing strategies built into \charmpp{} that can be 
121 selected. Among those, some may fit better for an application depending on its 
122 characteristics. Moreover, one can write a new load balancer, best suited for an 
123 application, by the simple API provided inside \charmpp{} infrastructure. Our approach is
124 based on actual measurement of load information at runtime, and on migrating
125 computations from heavily loaded to lightly loaded processors.
126
127 For this approach to be effective, we need the computation to be split into
128 pieces many more in number than available processors. This allows us to
129 flexibly map and re-map these computational pieces to available processors.
130 This approach is usually called ``multi-domain decomposition''.
131
132 \charmpp{}, which we use as a runtime system layer for the work described here,
133 simplifies our approach. It embeds an elaborate performance tracing mechanism,
134 a suite of plug-in load balancing strategies, infrastructure for defining and
135 migrating computational load, and is interoperable with other programming
136 paradigms.
137
138 \subsection{Terminology}
139
140 \begin{description}
141
142 \item[Module] A module refers to either a complete program or a library with an
143 orchestrator subroutine\footnote{Like many software engineering terms, this
144 term is overused, and unfortunately clashes with Fortran 90 module that denotes
145 a program unit. We specifically refer to the later as ``Fortran 90 module'' to
146 avoid confusion.} . An orchestrator subroutine specifies the main control flow
147 of the module by calling various subroutines from the associated library and
148 does not usually have much state associated with it.
149
150 \item[Thread] A thread is a lightweight process that owns a stack and machine
151 registers including program counter, but shares code and data with other
152 threads within the same address space. If the underlying operating system
153 recognizes a thread, it is known as kernel thread, otherwise it is known as
154 user-thread. A context-switch between threads refers to suspending one thread's
155 execution and transferring control to another thread. Kernel threads typically
156 have higher context switching costs than user-threads because of operating
157 system overheads. The policy implemented by the underlying system for
158 transferring control between threads is known as thread scheduling policy.
159 Scheduling policy for kernel threads is determined by the operating system, and
160 is often more inflexible than user-threads. Scheduling policy is said to be
161 non-preemptive if a context-switch occurs only when the currently running
162 thread willingly asks to be suspended, otherwise it is said to be preemptive.
163 \ampi{} threads are non-preemptive user-level threads.
164
165 \item[Chunk] A chunk is a combination of a user-level thread and the data it
166 manipulates. When a program is converted from MPI to \ampi{}, we convert an MPI
167 process into a chunk. This conversion is referred to as chunkification.
168
169 \item[Object] An object is just a blob of memory on which certain computations
170 can be performed. The memory is referred to as an object's state, and the set
171 of computations that can be performed on the object is called the interface of
172 the object.
173
174 \end{description}
175
176 \section{\charmpp{}}
177
178 \charmpp{} is an object-oriented parallel programming library for \CC{}.  It
179 differs from traditional message passing programming libraries (such as MPI) in
180 that \charmpp{} is ``message-driven''. Message-driven parallel programs do not
181 block the processor waiting for a message to be received.  Instead, each
182 message carries with itself a computation that the processor performs on
183 arrival of that message. The underlying runtime system of \charmpp{} is called
184 \converse{}, which implements a ``scheduler'' that chooses which message to
185 schedule next (message-scheduling in \charmpp{} involves locating the object
186 for which the message is intended, and executing the computation specified in
187 the incoming message on that object). A parallel object in \charmpp{} is a
188 \CC{} object on which a certain computations can be asked to performed from
189 remote processors.
190
191 \charmpp{} programs exhibit latency tolerance since the scheduler always picks
192 up the next available message rather than waiting for a particular message to
193 arrive.  They also tend to be modular, because of their object-based nature.
194 Most importantly, \charmpp{} programs can be \emph{dynamically load balanced},
195 because the messages are directed at objects and not at processors; thus
196 allowing the runtime system to migrate the objects from heavily loaded
197 processors to lightly loaded processors. It is this feature of \charmpp{} that
198 we utilize for \ampi{}.
199
200 Since many CSE applications are originally written using MPI, one would have to
201 do a complete rewrite if they were to be converted to \charmpp{} to take
202 advantage of dynamic load balancing and other \charmpp{} benefits. This is indeed impractical. However,
203 \converse{} -- the runtime system of \charmpp{} -- came to our rescue here,
204 since it supports interoperability between different parallel programming
205 paradigms such as parallel objects and threads. Using this feature, we
206 developed \ampi{}, an implementation of a significant subset of MPI-1.1
207 standard over \charmpp{}.  \ampi{} is described in the next section.
208
209 \section{AMPI}
210
211 \ampi{} utilizes the dynamic load balancing and other capabilities of \charmpp{} by
212 associating a ``user-level'' thread with each \charmpp{} migratable object.
213 User's code runs inside this thread, so that it can issue blocking receive
214 calls similar to MPI, and still present the underlying scheduler an opportunity
215 to schedule other computations on the same processor. The runtime system keeps
216 track of computation loads of each thread as well as communication graph
217 between \ampi{} threads, and can migrate these threads in order to balance the
218 overall load while simultaneously minimizing communication overhead. 
219
220 \subsection{AMPI Status}
221
222 Currently all the MPI-1.1 Standard functions are supported in \ampi{}, with a
223 collection of our extentions explained in detail in this manual. One-sided
224 communication calls in MPI-2 are implemented, but they are not taking advantage
225 of RMA features yet. Also ROMIO\footnote{http://www-unix.mcs.anl.gov/romio/} 
226 has been integrated to support parallel I/O features. Link with {\tt -lampiromio}
227 to take advantage of this library.
228
229 Following MPI-1.1 basic datatypes are supported in \ampi{}. (Some are not 
230 available in Fortran binding. Refer to MPI-1.1 Standard for details.)
231 \begin{alltt}
232 MPI_DATATYPE_NULL  MPI_BYTE            MPI_UNSIGNED_LONG MPI_LONG_DOUBLE_INT
233 MPI_DOUBLE         MPI_PACKED          MPI_LONG_DOUBLE   MPI_2FLOAT
234 MPI_INT            MPI_SHORT           MPI_FLOAT_INT     MPI_2DOUBLE
235 MPI_FLOAT          MPI_LONG            MPI_DOUBLE_INT    MPI_LB
236 MPI_COMPLEX        MPI_UNSIGNED_CHAR   MPI_LONG_INT      MPI_UB
237 MPI_LOGICAL        MPI_UNSIGNED_SHORT  MPI_2INT
238 MPI_CHAR           MPI_UNSIGNED        MPI_SHORT_INT
239 \end{alltt}
240
241 Following MPI-1.1 reduction operations are supported in \ampi{}.
242
243 \begin{alltt}
244 MPI_MAX   MPI_MIN   MPI_SUM   MPI_PROD  MPI_MAXLOC  MPI_MINLOC
245 MPI_LAND  MPI_LOR   MPI_LXOR  MPI_BAND  MPI_BOR     MPI_BXOR
246 \end{alltt}
247
248 Following are AMPI extension calls, which will be explained in detail in this
249 manual.
250 \begin{alltt}
251 MPI_Migrate     MPI_Checkpoint  MPI_Restart     MPI_Register    MPI_Get_userdata
252 MPI_Ialltoall   MPI_Iallgather  MPI_Iallreduce  MPI_Ireduce     MPI_IGet
253 \end{alltt}
254
255
256 \subsection{Name for Main Program}
257
258 To convert an existing program to use AMPI, the main function or program may need to be renamed. The changes should be made as follows:
259
260 \subsubsection{Fortran}
261
262 You must declare the main program as a subroutine called ``MPI\_MAIN''. Do not declare the main subroutine as a \textit{program} because it will never be called by the AMPI runtime.
263
264 \begin{alltt}
265
266 program pgm -> subroutine MPI_Main
267         ...                                   ...
268 end program -> end subroutine
269 \end{alltt}
270
271 \subsubsection{C or C++}
272
273 The main function can be left as is, if \texttt{mpi.h} is included before the main function. This header file has a preprocessor macro that renames main, and the renamed version is called by the AMPI runtime by each thread.
274
275
276 \subsection{Global Variable Privatization}
277
278 For the before-mentioned benefits to be effective, one needs to map multiple
279 user-level threads onto each processor. 
280 Traditional MPI programs assume that the
281 entire processor is allocated to themselves, and that only one thread of
282 control exists within the process's address space. So, they may use global and static variables in the program.
283 However, global and static variables are problematic for multi-threaded environments such as \ampi{} or OpenMP.
284 This is because there is a single instance of those variables so they will be 
285 shared among different threads in the single address space and a wrong result may be produced by the program.
286 Figure \ref{fig_global} shows an example of a multi-threaded application with 
287 two threads in a single process. $var$ is a global or static variable in this 
288 example. Thread 1 assigns a value to it, then it gets blocked for communication 
289 and another thread can continue. Thereby, thread 2 is scheduled next and 
290 accesses $var$ which is wrong. Semantics of this program needs separate 
291 instances of $var$ for each of the threads. Thats where the need arises
292 to make some transformations to the original MPI program in order to run
293 correctly with \ampi{}.
294
295 \begin{figure}[h]
296 \centering
297 \includegraphics[width=4.6in]{figs/global.png}
298 \caption{Global or static variables are an issue for \ampi{}}
299 \label{fig_global}
300 \end{figure}
301
302 The basic transformation needed to port the MPI program to \ampi{} is
303 privatization of global variables.\footnote{Typical Fortran MPI programs
304 contain three types of global variables.
305
306 \begin{enumerate}
307
308 \item Global variables that are ``read-only''. These are either
309 \emph{parameters} that are set at compile-time. Or other variables that are
310 read as input or set at the beginning of the program and do not change during
311 execution. It is not necessary to privatize such variables.
312
313 \item Global variables that are used as temporary buffers. These are variables
314 that are used temporarily to store values to be accessible across subroutines.
315 These variables have a characteristic that there is no blocking call such as
316 \texttt{MPI\_recv} between the time the variable is set and the time it is ever
317 used. It is not necessary to privatize such variables either. 
318
319 \item True global variables. These are used across subroutines that contain
320 blocking receives and therefore the possibility of a context switch between the
321 definition and use of the variable. These variables need to be privatized.
322
323 \end{enumerate}
324 }
325 With the MPI process model, each MPI node can keep a copy of its own
326 ``permanent variables'' -- variables that are accessible from more than one
327 subroutines without passing them as arguments.  Module variables, ``saved''
328 subroutine local variables, and common blocks in Fortran 90 belong to this
329 category. If such a program is executed without privatization on \ampi{}, all
330 the \ampi{} threads that reside on one processor will access the same copy of
331 such variables, which is clearly not the desired semantics.  To ensure correct
332 execution of the original source program, it is necessary to make such
333 variables ``private'' to individual threads. We are two choices: automatic 
334 global swapping and manual code modification.
335
336 \subsubsection{Automatic Globals Swapping}
337 Thanks to the ELF Object Format, we have successfully automated the procedure 
338 of switching the set of user global variables when switching thread contexts.
339 Executable and Linkable Format (ELF) is a common standard file format for Object Files in Unix-like operating systems.
340 ELF maintains a Global Offset Table (GOT) for globals so it is possible to
341 switch GOT contents at thread context-switch by the runtime system.
342
343
344 The only thing that the user needs to do is to set flag {\tt -swapglobals}
345 at compile and link time (e.g. ``ampicc Ðo prog prog.c -swapglobals"). It does not need 
346 any change to the source code and works with any language (C, C++, Fortran, etc).
347 However, it does not handle static variables and has a context switching overhead that grows with the number of global variables.
348 Currently, this feature only works on x86 and x86\_64
349  (e.g. amd64) platforms that fully support ELF. Thus, it may not work on PPC or
350   Itanium, or on some microkernels such as Catamount. When this feature does
351    not work for you,
352 you can try other ways of handling global or static variables, which are detailed in the
353 following sections.
354
355 \subsubsection{Manual Change}
356 We have employed a strategy of argument passing to do this privatization
357 transformation. That is, the global variables are bunched together in a
358 single user-defined type, which is allocated by each thread dynamically. Then a
359 pointer to this type is passed from subroutine to subroutine as an argument.
360 Since the subroutine arguments are passed on a stack, which is not shared
361 across all threads, each subroutine, when executing within a thread operates on
362 a private copy of the global variables. 
363
364 This scheme is demonstrated in the following examples. The original Fortran 90 
365 code contains a module \texttt{shareddata}. This module is used in the main 
366 program and a subroutine \texttt{subA}.
367
368 \begin{alltt}
369 !FORTRAN EXAMPLE
370 MODULE shareddata
371   INTEGER :: myrank
372   DOUBLE PRECISION :: xyz(100)
373 END MODULE
374
375 SUBROUTINE MPI_MAIN
376   USE shareddata
377   include 'mpif.h'
378   INTEGER :: i, ierr
379   CALL MPI_Init(ierr)
380   CALL MPI_Comm_rank(MPI_COMM_WORLD, myrank, ierr)
381   DO i = 1, 100
382     xyz(i) =  i + myrank
383   END DO
384   CALL subA
385   CALL MPI_Finalize(ierr)
386 END PROGRAM
387
388 SUBROUTINE subA
389   USE shareddata
390   INTEGER :: i
391   DO i = 1, 100
392     xyz(i) = xyz(i) + 1.0
393   END DO
394 END SUBROUTINE
395
396 //C Example
397 #include <mpi.h>
398
399 int myrank;
400 double xyz[100];
401
402 void subA();
403 int main(int argc, char** argv)\{
404   int i;
405   MPI_Init(&argc, &argv);
406   MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
407   for(i=0;i<100;i++)
408     xyz[i] = i + myrank;
409   subA();
410   MPI_Finalize();
411 \}
412
413 void subA()\{
414   int i;
415   for(i=0;i<100;i++)
416     xyz[i] = xyz[i] + 1.0;
417 \}
418 \end{alltt}
419
420 \ampi{} executes the main subroutine inside a user-level thread as a subroutine. 
421  
422 Now we transform this program using the argument passing strategy. We first group the
423 shared data into a user-defined type.
424
425 \begin{alltt}
426 !FORTRAN EXAMPLE
427 MODULE shareddata
428   \emph{TYPE chunk}
429     INTEGER :: myrank
430     DOUBLE PRECISION :: xyz(100)
431   \emph{END TYPE}
432 END MODULE
433
434 //C Example
435 struct shareddata\{
436   int myrank;
437   double xyz[100];
438 \};
439 \end{alltt}
440
441 Now we modify the main subroutine to dynamically allocate this data and change the
442 references to them. Subroutine \texttt{subA} is then modified to take this data
443 as argument. 
444
445 \begin{alltt}
446 !FORTRAN EXAMPLE
447 SUBROUTINE MPI_Main
448   USE shareddata
449   USE AMPI
450   INTEGER :: i, ierr
451   \emph{TYPE(chunk), pointer :: c}
452   CALL MPI_Init(ierr)
453   \emph{ALLOCATE(c)}
454   CALL MPI_Comm_rank(MPI_COMM_WORLD, c\%myrank, ierr)
455   DO i = 1, 100
456     \emph{c\%xyz(i) =  i + c\%myrank}
457   END DO
458   CALL subA(c)
459   CALL MPI_Finalize(ierr)
460 END SUBROUTINE
461
462 SUBROUTINE subA(c)
463   USE shareddata
464   \emph{TYPE(chunk) :: c}
465   INTEGER :: i
466   DO i = 1, 100
467     \emph{c\%xyz(i) = c\%xyz(i) + 1.0}
468   END DO
469 END SUBROUTINE
470
471 //C Example
472 void MPI_Main\{
473   int i,ierr;
474   struct shareddata *c;
475   ierr = MPI_Init();
476   c = (struct shareddata*)malloc(sizeof(struct shareddata));
477   ierr = MPI_Comm_rank(MPI_COMM_WORLD, c.myrank);
478   for(i=0;i<100;i++)
479     c.xyz[i] = i + c.myrank;
480   subA(c);
481   ierr = MPI_Finalize();
482 \}
483
484 void subA(struct shareddata *c)\{
485   int i;
486   for(i=0;i<100;i++)
487     c.xyz[i] = c.xyz[i] + 1.0;
488 \}
489 \end{alltt}
490
491 With these changes, the above program can be made thread-safe. Note that it is
492 not really necessary to dynamically allocate \texttt{chunk}. One could have
493 declared it as a local variable in subroutine \texttt{MPI\_Main}.  (Or for a
494 small example such as this, one could have just removed the \texttt{shareddata}
495 module, and instead declared both variables \texttt{xyz} and \texttt{myrank} as
496 local variables). This is indeed a good idea if shared data are small in size.
497 For large shared data, it would be better to do heap allocation because in
498 \ampi{}, the stack sizes are fixed at the beginning (can be specified from the
499 command line) and stacks do not grow dynamically.
500
501 \subsubsection{Source-to-source Transformation}
502 Another approach is to do the changes described in the previous 
503 scheme automatically. It means that we can use a tool to transform 
504 the source code to move global or static variables in an object and pass them around.
505 This approach is portable across systems and compilers and may also 
506 improve locality and hence cache utilization. It also does not have the 
507 context-switch overhead of swapping globals. However, it requires a new 
508 implementation of the tool for each language. Currently, there is a tool called \emph{Photran}\footnote{http://www.eclipse.org/photran}
509 for refactoring Fortran codes that can do this transformation. It is Eclipse-based and works by 
510 constructing Abstract Syntax Trees (ASTs) of the program.
511
512 \subsubsection{TLS-Globals}
513 Thread Local Store (TLS) was originally employed in kernel threads to localize variables and thread safety.
514 It can be used by annotating global/static variables with \emph{\_\_thread} in the source code.
515 Thus, those variables will have one instance per extant thread. This keyword is not an official
516 extension of the C language, however compiler writers are encouraged to
517 implement this feature. Currently, the ELF file format supports Thread Local
518 Storage.
519
520 It handles both global and static variables and has no context-switching
521  overhead. Context-switching is just changing the TLS segment register
522  to point to the thread's local copy. However, although it is popular, it  
523 is not supported by all compilers. Currently, \charmpp{} supports it for x86/x86\_64 platforms. 
524 A modified \emph{gfortran} is also available to use this feature.
525 To use TLS-Globals, one has to add \emph{\_\_thread} before all the global variables. For the example
526 above, the following changes to the code handles the global variables:
527 \begin{alltt}
528 __thread int myrank;
529 __thread double xyz[100];
530 \end{alltt}
531
532 The runtime system also should know that TLS-Globals is used at compile time:
533
534 \begin{alltt}
535 ampiCC -o example example.C -tlsglobals
536 \end{alltt}
537 Table \ref{tab:portability} shows portability of different schemes.
538
539 \begin{table*}[!t]
540 \begin{center}
541 \begin{tabular}{|c||c|c|c|c|c|c|c|c|c|}
542 \hline
543 Privatization
544 Scheme     & X86 & IA64 & Opteron & Mac OS X & IBM SP & SUN & BG/P & Cray/XT & Windows \\
545                    \hline
546                    \hline
547                    Transformation  & Yes  & Yes   & Yes     & Yes     & Yes  & Yes  & Yes & Yes & Yes  \\
548                            \hline
549                            GOT-Globals  & Yes  & Yes  & Yes     & No       & No    & Maybe  & No  & No  & No \\
550                                    \hline
551                                    TLS-Globals  &  Yes & Maybe  & Yes     & No    & Maybe & Maybe & No  & Yes & Maybe  \\
552                                            \hline
553                                            \end{tabular}
554                                            \caption{Portability of current implementations of three privatization schemes.
555                                                    ``Yes'' means we have implemented this technique.
556                                                            ``Maybe'' indicates there are no theoretical problems, but no implementation exists.
557                                                            ``No'' indicates the technique is impossible on this platform.}
558                                                            \label{tab:portability}
559                                                            \vspace{-1.0cm}
560                                                            \end{center}
561                                                            \end{table*}
562 \subsection{Extensions for Migrations}
563
564 For MPI chunks to migrate, we have added a few calls to \ampi{}. These include
565 ability to register thread-specific data with the run-time system, to pack all
566 the thread's data, and to express willingness to migrate.
567
568 \subsubsection{Registering Chunk data}
569
570 When the \ampi{} runtime system decides that load imbalance exists within the
571 application, it will invoke one of its internal load balancing strategies,
572 which determines the new mapping of \ampi{} chunks so as to balance the load.
573 Then \ampi{} runtime has to pack up the chunk's state and move it to its new
574 home processor. \ampi{} packs up any internal data in use by the chunk,
575 including the thread's stack in use. This means that the local variables
576 declared in subroutines in a chunk, which are created on stack, are
577 automatically packed up by the \ampi{} runtime system. However, it has no way
578 of knowing what other data are in use by the chunk. Thus upon starting
579 execution, a chunk needs to notify the system about the data that it is going
580 to use (apart from local variables.) Even with the data registration, \ampi{}
581 cannot determine what size the data is, or whether the registered data contains
582 pointers to other places in memory. For this purpose, a packing subroutine also
583 needs to be provided to the \ampi{} runtime system along with registered data.
584 (See next section for writing packing subroutines.) The call provided by
585 \ampi{} for doing this is \texttt{MPI\_Register}. This function takes two
586 arguments: A data item to be transported alongwith the chunk, and the pack
587 subroutine, and returns an integer denoting the registration identifier. In
588 C/\CC{} programs, it may be necessary to use this return value after migration
589 completes and control returns to the chunk, using function
590 \texttt{MPI\_Get\_userdata}. Therefore, the return value should be stored in a
591 local variable.
592
593 \subsubsection{Migration}
594
595 The \ampi{} runtime system could detect load imbalance by itself and invoke the
596 load balancing strategy. However, since the application code is going to
597 pack/unpack the chunk's data, writing the pack subroutine will be complicated
598 if migrations occur at a stage unknown to the application. For example, if the
599 system decides to migrate a chunk while it is in initialization stage (say,
600 reading input files), application code will have to keep track of how much data
601 it has read, what files are open etc. Typically, since initialization occurs
602 only once in the beginning, load imbalance at that stage would not matter much.
603 Therefore, we want the demand to perform load balance check to be initiated by
604 the application.
605
606 \ampi{} provides a subroutine \texttt{MPI\_Migrate} for this purpose. Each
607 chunk periodically calls \texttt{MPI\_Migrate}. Typical CSE applications are
608 iterative and perform multiple time-steps. One should call
609 \texttt{MPI\_Migrate} in each chunk at the end of some fixed number of
610 timesteps. The frequency of \texttt{MPI\_Migrate} should be determined by a
611 tradeoff between conflicting factors such as the load balancing overhead, and
612 performance degradation caused by load imbalance. In some other applications,
613 where application suspects that load imbalance may have occurred, as in the
614 case of adaptive mesh refinement; it would be more effective if it performs a
615 couple of timesteps before telling the system to re-map chunks. This will give
616 the \ampi{} runtime system some time to collect the new load and communication
617 statistics upon which it bases its migration decisions. Note that
618 \texttt{MPI\_Migrate} does NOT tell the system to migrate the chunk, but
619 merely tells the system to check the load balance after all the chunks call
620 \texttt{MPI\_Migrate}. To migrate the chunk or not is decided only by the
621 system's load balancing strategy.
622
623 \subsubsection{Packing/Unpacking Thread Data}
624
625 Once the \ampi{} runtime system decides which chunks to send to which
626 processors, it calls the specified pack subroutine for that chunk, with the
627 chunk-specific data that was registered with the system using
628 \texttt{MPI\_Register}. This section explains how a subroutine should be
629 written for performing pack/unpack.
630
631 There are three steps for transporting the chunk's data to other processor.
632 First, the system calls a subroutine to get the size of the buffer required to
633 pack the chunk's data. This is called the ``sizing'' step. In the next step,
634 which is called immediately afterward on the source processor, the system
635 allocates the required buffer and calls the subroutine to pack the chunk's data
636 into that buffer. This is called the ``packing'' step. This packed data is then
637 sent as a message to the destination processor, where first a chunk is created
638 (along with the thread) and a subroutine is called to unpack the chunk's data
639 from the buffer. This is called the ``unpacking'' step.
640
641 Though the above description mentions three subroutines called by the \ampi{}
642 runtime system, it is possible to actually write a single subroutine that will
643 perform all the three tasks. This is achieved using something we call a
644 ``pupper''. A pupper is an external subroutine that is passed to the chunk's
645 pack-unpack-sizing subroutine, and this subroutine, when called in different
646 phases performs different tasks. An example will make this clear:
647
648 Suppose the chunk data is defined as a user-defined type in Fortran 90:
649
650 \begin{alltt}
651 !FORTRAN EXAMPLE
652 MODULE chunkmod
653   TYPE, PUBLIC :: chunk
654       INTEGER , parameter :: nx=4, ny=4, tchunks=16
655       REAL(KIND=8) t(22,22)
656       INTEGER xidx, yidx
657       REAL(KIND=8), dimension(400):: bxm, bxp, bym, byp
658   END TYPE chunk
659 END MODULE
660
661 //C Example
662 struct chunk\{
663   double t;
664   int xidx, yidx;
665   double bxm,bxp,bym,byp;
666 \};
667 \end{alltt}
668
669 Then the pack-unpack subroutine \texttt{chunkpup} for this chunk module is
670 written as:
671
672 \begin{alltt}
673 !FORTRAN EXAMPLE
674 SUBROUTINE chunkpup(p, c)
675   USE pupmod
676   USE chunkmod
677   IMPLICIT NONE
678   INTEGER :: p
679   TYPE(chunk) :: c
680
681   call pup(p, c\%t)
682   call pup(p, c\%xidx)
683   call pup(p, c\%yidx)
684   call pup(p, c\%bxm)
685   call pup(p, c\%bxp)
686   call pup(p, c\%bym)
687   call pup(p, c\%byp)
688 end subroutine
689
690 //C Example
691 void chunkpup(pup_er p, struct chunk c)\{
692   pup_double(p,c.t);
693   pup_int(p,c.xidx);
694   pup_int(p,c.yidx);
695   pup_double(p,c.bxm);
696   pup_double(p,c.bxp);
697   pup_double(p,c.bym);
698   pup_double(p,c.byp);
699 \}
700 \end{alltt}
701
702 There are several things to note in this example. First, the same subroutine
703 \texttt{pup} (declared in module \texttt{pupmod}) is called to size/pack/unpack
704 any type of data. This is possible because of procedure overloading possible in
705 Fortran 90. Second is the integer argument \texttt{p}. It is this argument that
706 specifies whether this invocation of subroutine \texttt{chunkpup} is sizing,
707 packing or unpacking. Third, the integer parameters declared in the type
708 \texttt{chunk} need not be packed or unpacked since they are guaranteed to be
709 constants and thus available on any processor.
710
711 A few other functions are provided in module \texttt{pupmod}. These functions
712 provide more control over the packing/unpacking process. Suppose one modifies
713 the \texttt{chunk} type to include allocatable data or pointers that are
714 allocated dynamically at runtime. In this case, when the chunk is packed, these
715 allocated data structures should be deallocated after copying them to buffers,
716 and when the chunk is unpacked, these data structures should be allocated
717 before copying them from the buffers.  For this purpose, one needs to know
718 whether the invocation of \texttt{chunkpup} is a packing one or unpacking one.
719 For this purpose, the \texttt{pupmod} module provides functions
720 \verb+fpup_isdeleting+(\verb+fpup_isunpacking+). These functions return logical value
721 \verb+.TRUE.+ if the invocation is for packing (unpacking), and \verb+.FALSE.+
722 otherwise. Following example demonstrates this:
723
724 Suppose the type \texttt{dchunk} is declared as:
725
726 \begin{alltt}
727 !FORTRAN EXAMPLE
728 MODULE dchunkmod
729   TYPE, PUBLIC :: dchunk
730       INTEGER :: asize
731       REAL(KIND=8), pointer :: xarr(:), yarr(:)
732   END TYPE dchunk
733 END MODULE
734
735 //C Example
736 struct dchunk\{
737   int asize;
738   double* xarr, *yarr;
739 \};
740 \end{alltt}
741
742 Then the pack-unpack subroutine is written as:
743
744 \begin{alltt}
745 !FORTRAN EXAMPLE
746 SUBROUTINE dchunkpup(p, c)
747   USE pupmod
748   USE dchunkmod
749   IMPLICIT NONE
750   INTEGER :: p
751   TYPE(dchunk) :: c
752
753   pup(p, c\%asize)
754   \emph{
755   IF (fpup_isunpacking(p)) THEN       !! if invocation is for unpacking
756     allocate(c\%xarr(asize))
757     ALLOCATE(c\%yarr(asize))
758   ENDIF
759   }
760   pup(p, c\%xarr)
761   pup(p, c\%yarr)
762   \emph{
763   IF (fpup_isdeleting(p)) THEN        !! if invocation is for packing
764     DEALLOCATE(c\%xarr(asize))
765     DEALLOCATE(c\%yarr(asize))
766   ENDIF
767   }
768
769 END SUBROUTINE
770
771 //C Example
772 void dchunkpup(pup_er p, struct dchunk c)\{
773   pup_int(p,c.asize);
774   if(pup_isUnpacking(p))\{
775     c.xarr = (double *)malloc(sizeof(double)*c.asize);
776     c.yarr = (double *)malloc(sizeof(double)*c.asize);
777   \}
778   pup_doubles(p,c.xarr,c.asize);
779   pup_doubles(p,c.yarr,c.asize);
780   if(pup_isPacking(p))\{
781     free(c.xarr);
782     free(c.yarr);
783   \}
784 \}
785 \end{alltt}
786
787 One more function \verb+fpup_issizing+ is also available in module \texttt{pupmod}
788 that returns \verb+.TRUE.+ when the invocation is a sizing one. In practice one
789 almost never needs to use it.
790
791 \subsection{Extensions for Checkpointing}
792
793 The pack-unpack subroutines written for migrations make sure that the current
794 state of the program is correctly packed (serialized) so that it can be
795 restarted on a different processor. Using the \emph{same} subroutines, it
796 is also possible to save the state of the program to disk, so that if the 
797 program were to crash abruptly, or if the allocated time for the program
798 expires before completing execution, the program can be restarted from the
799 previously checkpointed state. Thus, the pack-unpack subroutines act as the 
800 key facility for checkpointing in addition to their usual role for migration.
801
802 A subroutine for checkpoint purpose has been added to AMPI:
803 \texttt{void MPI\_Checkpoint(char *dirname);}
804 This subroutine takes a directory name as its argument. It is a collective 
805 function, meaning every virtual processor in the program needs to call this 
806 subroutine and specify the same directory name. (Typically, in an
807 iterative AMPI program, the iteration number, converted to a character string,
808 can serve as a checkpoint directory name.) This directory is created, and the
809 entire state of the program is checkpointed to this directory.  One can restart
810 the program from the checkpointed state by specifying \texttt{"+restart
811 dirname"} on the command-line. This capability is powered by the \charmpp{} 
812 runtime system. For more information about \charmpp{} checkpoint/restart
813 mechanism please refer to \charmpp{} manual. 
814
815 \subsection{Extensions for Memory Efficiency}
816
817 MPI functions usually require the user to preallocate the data buffers needed before the
818 functions being called. For unblocking communication primitives, sometimes the user would
819 like to do lazy memory allocation until the data actually arrives, which gives the
820 oppotunities to write more memory efficient programs.     
821 We provide a set of AMPI functions as an extension to the standard MPI-2 one-sided calls,
822 where we provide a split phase MPI\_Get called MPI\_IGet. MPI\_IGet preserves the similar
823 semantics as MPI\_Get except that no user buffer is provided to hold incoming data.
824 MPI\_IGet\_Wait will block until the requested data arrives and runtime system takes
825 care to allocate space, do appropriate unpacking based on data type, and return.
826 MPI\_IGet\_Free lets the runtime system free the resources being used for this get request
827 including the data buffer. And MPI\_IGet\_Data is the utility program that returns the
828 actual data.     
829  
830
831 \begin{alltt}
832
833 int MPI_IGet(MPI_Aint orgdisp, int orgcnt, MPI_Datatype orgtype, int rank,
834              MPI_Aint targdisp, int targcnt, MPI_Datatype targtype, MPI_Win win,
835              MPI_Request *request);
836
837 int MPI_IGet_Wait(MPI_Request *request, MPI_Status *status, MPI_Win win);
838
839 int MPI_IGet_Free(MPI_Request *request, MPI_Status *status, MPI_Win win);
840
841 char* MPI_IGet_Data(MPI_Status status);
842
843 \end{alltt}
844
845
846
847 \subsection{Extensions for Interoperability}
848
849 Interoperability between different modules is essential for coding coupled
850 simulations.  In this extension to \ampi{}, each MPI application module runs
851 within its own group of user-level threads distributed over the physical
852 parallel machine.  In order to let \ampi{} know which chunks are to be created,
853 and in what order, a top level registration routine needs to be written. A
854 real-world example will make this clear. We have an MPI code for fluids and
855 another MPI code for solids, both with their main programs, then we first
856 transform each individual code to run correctly under \ampi{} as standalone
857 codes. This involves the usual ``chunkification'' transformation so that
858 multiple chunks from the application can run on the same processor without
859 overwriting each other's data. This also involves making the main program into
860 a subroutine and naming it \texttt{MPI\_Main}.
861
862 Thus now, we have two \texttt{MPI\_Main}s, one for the fluids code and one for
863 the solids code. We now make these codes co-exist within the same executable,
864 by first renaming these \texttt{MPI\_Main}s as \texttt{Fluids\_Main} and
865 \texttt{Solids\_Main}\footnote{Currently, we assume that the interface code,
866 which does mapping and interpolation among the boundary values of Fluids and
867 Solids domain, is integrated with one of Fluids and Solids.} writing a
868 subroutine called \texttt{MPI\_Setup}.
869
870 \begin{alltt}
871 !FORTRAN EXAMPLE
872 SUBROUTINE MPI_Setup
873   USE ampi
874   CALL MPI_Register_main(Solids_Main)
875   CALL MPI_Register_main(Fluids_Main)
876 END SUBROUTINE
877
878 //C Example
879 void MPI_Setup()\{
880   MPI_Register_main(Solids_Main);
881   MPI_Register_main(Fluids_Main);
882 \}
883 \end{alltt}
884
885 This subroutine is called from the internal initialization routines of \ampi{}
886 and tells \ampi{} how many number of distinct chunk types (modules) exist, and
887 which orchestrator subroutines they execute.
888
889 The number of chunks to create for each chunk type is specified on the command
890 line when an \ampi{} program is run. Appendix B explains how \ampi{} programs
891 are run, and how to specify the number of chunks (\verb|+vp| option). In the
892 above case, suppose one wants to create 128 chunks of Solids and 64 chunks of
893 Fluids on 32 physical processors, one would specify those with multiple
894 \verb|+vp| options on the command line as:
895
896 \begin{alltt}
897 > charmrun gen1.x +p 32 +vp 128 +vp 64
898 \end{alltt}
899
900 This will ensure that multiple chunk types representing different complete
901 applications can co-exist within the same executable. They can also continue to
902 communicate among their own chunk-types using the same \ampi{} function calls
903 to send and receive with communicator argument as \texttt{MPI\_COMM\_WORLD}.
904 But this would be completely useless if these individual applications cannot
905 communicate with each other, which is essential for building efficient coupled
906 codes.  For this purpose, we have extended the \ampi{} functionality to allow
907 multiple ``\texttt{COMM\_WORLD}s''; one for each application. These \emph{world
908 communicators} form a ``communicator universe'': an array of communicators
909 aptly called \emph{MPI\_COMM\_UNIVERSE}. This array of communicators is 
910 indexed [1 . . . \texttt{MPI\_MAX\_COMM}]. In the current implementation,
911 \texttt{MPI\_MAX\_COMM} is 8, that is, maximum of 8 applications can co-exist
912 within the same executable.
913
914 The order of these \texttt{COMM\_WORLD}s within \texttt{MPI\_COMM\_UNIVERSE}
915 is determined by the order in which individual applications are registered in
916 \texttt{MPI\_Setup}.
917
918 Thus, in the above example, the communicator for the Solids module would be
919 \texttt{MPI\_COMM\_UNIVERSE(1)} and communicator for Fluids module would be
920 \texttt{MPI\_COMM\_UNIVERSE(2)}.
921
922 Now any chunk within one application can communicate with any chunk in the
923 other application using the familiar send or receive \ampi{} calls by
924 specifying the appropriate communicator and the chunk number within that
925 communicator in the call. For example if a Solids chunk number 36 wants to send
926 data to chunk number 47 within the Fluids module, it calls:
927
928 \begin{alltt}
929 !FORTRAN EXAMPLE
930 INTEGER , PARAMETER :: Fluids_Comm = 2
931 CALL MPI_Send(InitialTime, 1, MPI_Double_Precision, tag, 
932               \emph{47, MPI_Comm_Universe(Fluids_Comm)}, ierr)
933
934 //C Example
935 int Fluids_Comm = 2;
936 ierr = MPI_Send(InitialTime, 1, MPI_DOUBLE, tag,
937                 \emph{47, MPI_Comm_Universe(Fluids_Comm)});
938 \end{alltt}
939
940 The Fluids chunk has to issue a corresponding receive call to receive this
941 data:
942
943 \begin{alltt}
944 !FORTRAN EXAMPLE
945 INTEGER , PARAMETER :: Solids_Comm = 1
946 CALL MPI_Recv(InitialTime, 1, MPI_Double_Precision, tag, 
947               \emph{36, MPI_Comm_Universe(Solids_Comm)}, stat, ierr)
948
949 //C Example
950 int Solids_Comm = 1;
951 ierr = MPI_Recv(InitialTime, 1, MPI_DOUBLE, tag,
952                 \emph{36, MPI_Comm_Universe(Solids_Comm)}, &stat);
953 \end{alltt}
954
955 \subsection{Extensions for Sequential Re-run of a Parallel Node}
956 In some scenarios, a sequential re-run of a parallel node is desired. One
957 example is instruction-level accurate architecture simulations, in which case
958 the user may wish to repeat the execution of a node in a parallel run in the
959 sequential simulator. AMPI provides support for such needs by logging the change
960 in the MPI environment on a certain processors. To activate the feature, build 
961 AMPI module with variable ``AMPIMSGLOG'' defined, like the following command in
962 charm directory. (Linking with zlib ``-lz'' might be required with this, for
963 generating compressed log file.)
964
965 \begin{alltt}
966 > ./build AMPI net-linux -DAMPIMSGLOG
967 \end{alltt}
968
969 The feature is used in two phases: writing (logging) the environment and
970 repeating the run. The first logging phase is invoked by a parallel run of the
971 AMPI program with some additional command line options. 
972
973 \begin{alltt}
974 > ./charmrun ./pgm +p4 +vp4 +msgLogWrite +msgLogRank 2 +msgLogFilename "msg2.log"
975 \end{alltt}
976
977 In the above example, a parallel run with 4 processors and 4 VPs will be
978 executed, and the changes in the MPI environment of processor 2 (also VP 2,
979 starting from 0) will get logged into diskfile "msg2.log". 
980
981 Unlike the first run, the re-run is a sequential program, so it is not invoked
982 by charmrun (and omitting charmrun options like +p4 and +vp4), and additional
983 comamnd line options are required as well. 
984
985 \begin{alltt}
986 > ./pgm +msgLogRead +msgLogRank 2 +msgLogFilename "msg2.log"
987 \end{alltt}
988
989 \subsection{Communication Optimizations for AMPI}
990 AMPI is powered by the \charmpp{} communication optimization support now!
991 Currently the user needs to specify the communication pattern by command
992 line option. In the future this can be done automatically by the system.
993
994 Currently there are four strategies available: USE\_DIRECT, USE\_MESH,
995 USE\_HYPERCUBE and USE\_GRID. USE\_DIRECT sends the message directly. 
996 USE\_MESH imposes a 2d Mesh virtual topology on the processors so each 
997 processor sends messages to its neighbors in its row and column of the 
998 mesh which forward the messages to their correct destinations. USE\_HYPERCUBE 
999 and USE\_GRID impose a hypercube and a 3d Grid topologies on the processors. 
1000 USE\_HYPERCUBE will do best for very small messages and small number of 
1001 processors, 3d has better performance for slightly higher message sizes 
1002 and then Mesh starts performing best. The programmer is encouraged to try 
1003 out all the strategies. (Stolen from the CommLib manual by Sameer :)
1004
1005 For more details please refer to the CommLib paper \footnote{L. V. Kale and 
1006 Sameer Kumar and Krishnan Vardarajan, 2002. 
1007 http://finesse.cs.uiuc.edu/papers/CommLib.pdf}. 
1008
1009 Specifying the strategy is as simple as a command line option +strategy. For
1010 example:
1011 \begin{alltt}
1012 > ./charmrun +p64 alltoall +vp64 1000 100 +strategy USE\_MESH
1013 \end{alltt}
1014 tells the system to use MESH strategy for CommLib. By default USE\_DIRECT is
1015 used.
1016
1017 \subsection{User Defined Initial Mapping}
1018                                                                                 
1019 You can define the initial mapping of virtual processors (vp) to physical 
1020 processors (p) as a runtime option. You can choose from predefined initial 
1021 mappings or define your own mappings. Following predefined mappings are 
1022 available:
1023                                                                                 
1024 \begin{description}
1025
1026 \item[Round Robin]
1027                                                                                 
1028 This mapping scheme, maps virtual processor to physical processor in round-robin
1029 fashion, i.e. if there are 8 virtual processors and 2 physical processors then
1030 virtual processors indexed 0,2,4,6 will be mapped to physical processor 0 and 
1031 virtual processors indexed 1,3,5,7 will be mapped to physical processor 1. 
1032
1033 \begin{alltt}
1034 > ./charmrun ./hello +p2 +vp8 +mapping RR\_MAP
1035 \end{alltt}
1036                                                                                 
1037 \item[Block Mapping]
1038                                                                                 
1039 This mapping scheme, maps virtual processors to physical processor in chunks, 
1040 i.e. if there are 8 virtual processors and 2 physical processors then virtual 
1041 processors indexed 0,1,2,3 will be mapped to physical processor 0 and virtual 
1042 processors indexed 4,5,6,7 will be mapped to physical processor 1.
1043                                                                                 
1044 \begin{alltt}
1045 > ./charmrun ./hello +p2 +vp8 +mapping BLOCK\_MAP
1046 \end{alltt}
1047                                                                                 
1048 \item[Proportional Mapping]
1049                                                                                 
1050 This scheme takes the processing capability of physical processors into account
1051 for mapping virtual processors to physical processors, i.e. if there are 2 
1052 processors with different processing power, then number of virtual processors 
1053 mapped to processors will be in proportion to their processing power.
1054                                                                                 
1055 \begin{alltt}
1056 > ./charmrun ./hello +p2 +vp8 +mapping PROP\_MAP
1057 > ./charmrun ./hello +p2 +vp8
1058 \end{alltt}
1059
1060 \end{description}
1061
1062 If you want to define your own mapping scheme, please contact us for help.
1063
1064 \subsection{Compiling AMPI Programs}
1065
1066 \charmpp{} provides a cross-platform compile-and-link script called \charmc{}
1067 to compile C, \CC{}, Fortran, \charmpp{} and \ampi{} programs.  This script
1068 resides in the \texttt{bin} subdirectory in the \charmpp{} installation
1069 directory. The main purpose of this script is to deal with the differences of
1070 various compiler names and command-line options across various machines on
1071 which \charmpp{} runs. While, \charmc{} handles C and \CC{} compiler
1072 differences most of the time, the support for Fortran 90 is new, and may have
1073 bugs. But \charmpp{} developers are aware of this problem and are working to
1074 fix them. Even in its alpha stage of Fortran 90 support, \charmc{} still
1075 handles many of the compiler differences across many machines, and it is
1076 recommended that \charmc{} be used to compile and linking \ampi{} programs. One
1077 major advantage of using \charmc{} is that one does not have to specify which
1078 libraries are to be linked for ensuring that \CC{} and Fortran 90 codes are
1079 linked correctly together. Appropriate libraries required for linking such
1080 modules together are known to \charmc{} for various machines.
1081
1082 In spite of the platform-neutral syntax of \charmc{}, one may have to specify
1083 some platform-specific options for compiling and building \ampi{} codes.
1084 Fortunately, if \charmc{} does not recognize any particular options on its
1085 command line, it promptly passes it to all the individual compilers and linkers
1086 it invokes to compile the program.
1087
1088 \appendix
1089
1090 \section{Installing AMPI}
1091
1092 \ampi{} is included in the source distribution of \charmpp{}. 
1093 To get the latest sources from PPL, visit:
1094         http://charm.cs.uiuc.edu/
1095
1096 and follow the download link.
1097 Now one has to build \charmpp{} and \ampi{} from source.
1098
1099 The build script for \charmpp{} is called \texttt{build}. The syntax for this
1100 script is:
1101
1102 \begin{alltt}
1103 > build <target> <version> <opts>
1104 \end{alltt}
1105
1106 For building \ampi{} (which also includes building \charmpp{} and other
1107 libraries needed by \ampi{}), specify \verb+<target>+ to be \verb+AMPI+. And
1108 \verb+<opts>+ are command line options passed to the \verb+charmc+ compile
1109 script.  Common compile time options such as \texttt{-g, -O, -Ipath, -Lpath,
1110 -llib} are accepted. 
1111
1112 To build a debugging version of \ampi{}, use the option: ``\texttt{-g}''. 
1113 To build a production version of \ampi{}, use the options: ``\texttt{-O 
1114 -DCMK\_OPTIMIZE=1}''.
1115
1116 \verb+<version>+ depends on the machine, operating system, and the underlying
1117 communication library one wants to use for running \ampi{} programs.
1118 See the charm/README file for details on picking the proper version.
1119 Following is an example of how to build AMPI under linux and ethernet
1120 environment, with debugging info produced:
1121
1122 \begin{alltt}
1123 > build AMPI net-linux -g
1124 \end{alltt}
1125
1126 \section{Building and Running AMPI Programs}
1127 \subsection{Building}
1128 \charmpp{} provides a compiler called charmc in your charm/bin/ directory. 
1129 You can use this compiler to build your AMPI program the same way as other
1130 compilers like cc. Especially, to build an AMPI program, a command line 
1131 option \emph{-language ampi} should be applied. All the command line 
1132 flags that you would use for other compilers can be used with charmc the 
1133 same way. For example:
1134
1135 \begin{alltt}
1136 > charmc -language ampi -c pgm.c -O3
1137 > charmc -language ampi -o pgm pgm.o -lm -O3 
1138 \end{alltt}
1139
1140 Shortcuts to the AMPI compiler are provided. If you have added charm/bin 
1141 into your \$PATH environment variable, simply type \emph{mpicc, mpiCC, 
1142 mpif77,} and \emph{mpif90} as provided by other MPI implementations.
1143
1144 \begin{alltt}
1145 > mpicc -c pgm.c -g
1146 \end{alltt}
1147
1148 \subsection{Running}
1149 \charmpp{} distribution contains a script called \texttt{charmrun} that makes
1150 the job of running \ampi{} programs portable and easier across all parallel
1151 machines supported by \charmpp{}. \texttt{charmrun} is copied to a directory
1152 where an \ampi{} prgram is built using \charmc{}. It takes a command line
1153 parameter specifying number of processors, and the name of the program followed
1154 by \ampi{} options (such as number of chunks to create, and the stack size of
1155 every chunk) and the program arguments. A typical invocation of \ampi{} program
1156 \texttt{pgm} with \texttt{charmrun} is:
1157
1158 \begin{alltt}
1159 > charmrun pgm +p16 +vp32 +tcharm_stacksize 3276800
1160 \end{alltt}
1161
1162 Here, the \ampi{} program \texttt{pgm} is run on 16 physical processors with
1163 32 chunks (which will be mapped 2 per processor initially), where each
1164 user-level thread associated with a chunk has the stack size of 3,276,800 bytes.
1165
1166 \end{document}