Doc: Converting latex to rst 24/3624/20
authorMatthias Diener <mdiener@illinois.edu>
Mon, 17 Dec 2018 00:14:19 +0000 (18:14 -0600)
committerMatthias Diener <mdiener@illinois.edu>
Thu, 10 Jan 2019 20:55:17 +0000 (14:55 -0600)
Rendered as HTML:
https://charm-rtd-test.readthedocs.io/en/latest/

Rendered as PDF:
https://media.readthedocs.org/pdf/charm-rtd-test/latest/charm-rtd-test.pdf

Wiki with more infos:
https://github.com/UIUC-PPL/charm/wiki/RST-manual

Change-Id: I5c1a04cd4d5dc90da4e62c8e49e3d8a19e40ac3b

24 files changed:
doc/ampi/manual.rst [new file with mode: 0644]
doc/armci/manual.rst [new file with mode: 0644]
doc/bignetsim/manual.rst [new file with mode: 0644]
doc/bigsim/manual.rst [new file with mode: 0644]
doc/charisma/manual.rst [new file with mode: 0644]
doc/charj/manual.rst [new file with mode: 0644]
doc/charm++/manual.rst [new file with mode: 0644]
doc/conf.py [new file with mode: 0644]
doc/converse/manual.rst [new file with mode: 0644]
doc/convext/manual.rst [new file with mode: 0644]
doc/debugger/manual.rst [new file with mode: 0644]
doc/f90charm/manual.rst [new file with mode: 0644]
doc/faq/manual.rst [new file with mode: 0644]
doc/fem/manual.rst [new file with mode: 0644]
doc/ifem/manual.rst [new file with mode: 0644]
doc/index.rst [new file with mode: 0644]
doc/jade/manual.rst [new file with mode: 0644]
doc/libraries/manual.rst [new file with mode: 0644]
doc/mblock/manual.rst [new file with mode: 0644]
doc/netfem/manual.rst [new file with mode: 0644]
doc/parfum/manual.rst [new file with mode: 0644]
doc/pose/manual.rst [new file with mode: 0644]
doc/projections/manual.rst [new file with mode: 0644]
doc/tcharm/manual.rst [new file with mode: 0644]

diff --git a/doc/ampi/manual.rst b/doc/ampi/manual.rst
new file mode 100644 (file)
index 0000000..917e6a3
--- /dev/null
@@ -0,0 +1,2008 @@
+===================
+Adaptive MPI Manual
+===================
+
+.. contents::
+   :depth: 3
+
+
+Introduction
+============
+
+This manual describes Adaptive MPI (AMPI), which is an implementation of
+the MPI standard [1]_ on top of Charm++. AMPI acts as a regular MPI
+implementation (akin to MPICH, OpenMPI, MVAPICH, etc.) with several
+built-in extensions that allow MPI developers to take advantage of
+Charm++’s dynamic runtime system, which provides support for process
+virtualization, overlap of communication and computation, load
+balancing, and fault tolerance with zero to minimal changes to existing
+MPI codes.
+
+In this manual, we first describe the philosophy behind Adaptive MPI,
+then give a brief introduction to Charm++ and rationale for AMPI. We
+then describe AMPI in detail. Finally we summarize the changes required
+for existing MPI codes to run with AMPI. Appendices contain the details
+of installing AMPI, and building and running AMPI programs.
+
+Overview
+--------
+
+Developing parallel Computational Science and Engineering (CSE)
+applications is a complex task. One has to implement the right physics,
+develop or choose and code appropriate numerical methods, decide and
+implement the proper input and output data formats, perform
+visualizations, and be concerned with correctness and efficiency of the
+programs. It becomes even more complex for multi-physics coupled
+simulations, many of which are dynamic and adaptively refined so that
+load imbalance becomes a major challenge. In addition to imbalance
+caused by dynamic program behavior, hardware factors such as latencies,
+variability, and failures must be tolerated by applications. Our
+philosophy is to lessen the burden of application developers by
+providing advanced programming paradigms and versatile runtime systems
+that can handle many common programming and performance concerns
+automatically and let application programmers focus on the actual
+application content.
+
+Many of these concerns can be addressed using the processor
+virtualization and over-decomposition philosophy of Charm++. Thus, the
+developer only sees virtual processors and lets the runtime system deal
+with underlying physical processors. This is implemented in AMPI by
+mapping MPI ranks to Charm++ user-level threads as illustrated in Figure
+:numref:`fig_virt`. As an immediate and simple benefit, the
+programmer can use as many virtual processors ("MPI ranks") as the
+problem can be easily decomposed to. For example, suppose the problem
+domain has :math:`n*2^n` parts that can be easily distributed but
+programming for general number of MPI processes is burdensome, then the
+developer can have :math:`n*2^n` virtual processors on any number of
+physical ones using AMPI.
+
+.. _fig_virt:
+.. figure:: figs/virtualization.png
+   :width: 4.6in
+
+   MPI ranks are implemented as user-level threads in AMPI rather than
+   Operating System processes.
+
+
+
+AMPI’s execution model consists of multiple user-level threads per
+Processing Element (PE). The Charm++ scheduler coordinates execution of
+these user-level threads (also called Virtual Processors or VPs) and
+controls execution. These VPs can also migrate between PEs for the
+purpose of load balancing or other reasons. The number of VPs per PE
+specifies the virtualization ratio (degree of over-decomposition). For
+example, in Figure :numref:`fig_virt` the virtualization ratio
+is :math:`3.5` (there are four VPs on PE 0 and three VPs on PE 1).
+Figure :numref:`fig_prac` shows how the problem domain can be
+over-decomposed in AMPI’s VPs as opposed to other MPI implementations.
+
+.. _fig_prac:
+.. figure:: figs/prac.png
+   :width: 4.6in
+
+   The problem domain is over-decomposed to more VPs than PEs.
+
+
+
+Another benefit of virtualization is communication and computation
+overlap, which is automatically realized in AMPI without programming
+effort. Techniques such as software pipelining require significant
+programming effort to achieve this goal and improve performance.
+However, one can use AMPI to have more virtual processors than physical
+processors to overlap communication and computation. Each time a VP is
+blocked for communication, the Charm++ scheduler picks the next VP among
+those that are ready to execute. In this manner, while some of the VPs
+of a physical processor are waiting for a message to arrive, others can
+continue their execution. Thus, performance improves without any changes
+to the application source code.
+
+Another 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
+:numref:`fig_virt` where each AMPI rank’s subdomain is smaller
+than the corresponding MPI subdomain and so may fit into cache memory.
+Thus, there is a potential performance improvement without changing the
+source code.
+
+One important concern is that of load imbalance. New generation parallel
+applications are dynamically varying, meaning that processors’ load is
+shifting during execution. In a dynamic simulation application such as
+rocket simulation, burning solid fuel, sub-scaling for a certain part of
+the mesh, crack propagation, particle flows all contribute to load
+imbalance. A centralized load balancing strategy built into an
+application is impractical since each individual module is developed
+mostly independently by various developers. In addition, embedding a
+load balancing strategy in the code complicates it greatly, and
+programming effort increases significantly. The runtime system is
+uniquely positioned to deal with load imbalance. Figure
+:numref:`fig_migrate` shows the runtime system migrating a VP
+after detecting load imbalance. This domain may correspond to a weather
+forecast model where there is a storm cell in the top-left quadrant,
+which requires more computation to simulate. AMPI will then migrate VP 1
+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 complicate the code.
+
+.. _fig_migrate:
+.. figure:: figs/migrate.png
+   :width: 4.6in
+
+   AMPI can migrate VPs across processes for load balancing.
+
+
+
+There are many different load balancing strategies built into Charm++
+that can be selected by an AMPI application developer. Among those, some
+may fit better for a particular application depending on its
+characteristics. Moreover, one can write a new load balancer, best
+suited for an application, by the simple API provided inside Charm++
+infrastructure. Our approach is based on actual measurement of load
+information at runtime, and on migrating computations from heavily
+loaded to lightly loaded processors.
+
+For this approach to be effective, we need the computation to be split
+into pieces many more in number than available processors. This allows
+us to flexibly map and re-map these computational pieces to available
+processors. This approach is usually called "multi-domain
+decomposition".
+
+Charm++, which we use as a runtime system layer for the work described
+here, simplifies our approach. It embeds an elaborate performance
+tracing mechanism, a suite of plug-in load balancing strategies,
+infrastructure for defining and migrating computational load, and is
+interoperable with other programming paradigms.
+
+Charm++
+=======
+
+Charm++ is an object-oriented parallel programming library for C. It
+differs from traditional message passing programming libraries (such as
+MPI) in that Charm++ is "message-driven". Message-driven parallel
+programs do not block the processor waiting for a message to be
+received. Instead, each message carries with itself a computation that
+the processor performs on arrival of that message. The underlying
+runtime system of Charm++ is called Converse, which implements a
+"scheduler" that chooses which message to schedule next
+(message-scheduling in Charm++ involves locating the object for which
+the message is intended, and executing the computation specified in the
+incoming message on that object). A parallel object in Charm++ is a C
+object on which a certain computations can be asked to be performed from
+remote processors.
+
+Charm++ programs exhibit latency tolerance since the scheduler always
+picks up the next available message rather than waiting for a particular
+message to arrive. They also tend to be modular, because of their
+object-based nature. Most importantly, Charm++ programs can be
+*dynamically load balanced*, because the messages are directed at
+objects and not at processors; thus allowing the runtime system to
+migrate the objects from heavily loaded processors to lightly loaded
+processors.
+
+Since many CSE applications are originally written using MPI, one would
+have to rewrite existing code if they were to be converted to Charm++ to
+take advantage of dynamic load balancing and other Charm++ features.
+This is indeed impractical. However, Converse - the runtime system of
+Charm++ - supports interoperability between different parallel
+programming paradigms such as parallel objects and threads. Using this
+feature, we developed AMPI, which is described in more detail in the
+next section.
+
+AMPI
+====
+
+AMPI utilizes the dynamic load balancing and other capabilities of
+Charm++ by associating a "user-level" thread with each Charm++
+migratable object. User’s code runs inside this thread, so that it can
+issue blocking receive calls similar to MPI, and still present the
+underlying scheduler an opportunity to schedule other computations on
+the same processor. The runtime system keeps track of the computational
+loads of each thread as well as the communication graph between AMPI
+threads, and can migrate these threads in order to balance the overall
+load while simultaneously minimizing communication overhead.
+
+AMPI Compliance to MPI Standards
+--------------------------------
+
+Currently AMPI supports the MPI-2.2 standard, with preliminary support
+for most MPI-3.1 features and a collection of extensions explained in
+detail in this manual. One-sided communication calls in MPI-2 and MPI-3
+are implemented, but they do not yet take advantage of RMA features.
+Non-blocking collectives have been defined in AMPI since before
+MPI-3.0’s adoption of them. Also ROMIO [2]_ has been integrated into
+AMPI to support parallel I/O features.
+
+AMPI Extensions to MPI Standards
+--------------------------------
+
+The following are AMPI extensions to the MPI standard, which will be
+explained in detail in this manual. All AMPI extensions to the MPI
+standard are prefixed with ``AMPI_`` rather than ``MPI_``. All
+extensions are available in C, C++, and Fortran, with the exception of
+``AMPI_Command_argument_count`` and ``AMPI_Get_command_argument`` which
+are only available in Fortran.
+
+::
+
+   AMPI_Migrate          AMPI_Register_pup            AMPI_Get_pup_data
+   AMPI_Migrate_to_pe    AMPI_Set_migratable          AMPI_Evacuate
+   AMPI_Load_set_value   AMPI_Load_start_measure      AMPI_Load_stop_measure
+   AMPI_Iget             AMPI_Iget_wait               AMPI_Iget_data
+   AMPI_Iget_free        AMPI_Type_is_contiguous      AMPI_Register_main
+   AMPI_Yield            AMPI_Suspend                 AMPI_Resume
+   AMPI_Alltoall_medium  AMPI_Alltoall_long
+   AMPI_Register_just_migrated         AMPI_Register_about_to_migrate
+   AMPI_Command_argument_count         AMPI_Get_command_argument
+
+AMPI provides a set of built-in attributes on all communicators and
+windows to find the number of the worker thread, process, or host that a
+rank is currently running on, as well as the total number of worker
+threads, processes, and hosts in the job. We define a worker thread to
+be a thread on which one of more AMPI ranks are scheduled. We define a
+process here as an operating system process, which may contain one or
+more worker threads. The built-in attributes are ``AMPI_MY_WTH``,
+``AMPI_MY_PROCESS``, ``AMPI_NUM_WTHS``, and ``AMPI_NUM_PROCESSES``.
+These attributes are accessible from any rank by calling
+``MPI_Comm_get_attr``, such as:
+
+.. code-block:: fortran
+
+   ! Fortran:
+   integer :: my_wth, flag, ierr
+   call MPI_Comm_get_attr(MPI_COMM_WORLD, AMPI_MY_WTH, my_wth, flag, ierr)
+
+
+::
+
+   // C/C++:
+   int my_wth, flag;
+   MPI_Comm_get_attr(MPI_COMM_WORLD, AMPI_MY_WTH, &my_wth, &flag);
+
+AMPI also provides extra communicator types that users can pass to
+``MPI_Comm_split_type``: ``AMPI_COMM_TYPE_HOST`` for splitting a
+communicator into disjoint sets of ranks that share the same physical
+host, ``AMPI_COMM_TYPE_PROCESS`` for splitting a communicator into
+disjoint sets of ranks that share the same operating system process, and
+``AMPI_COMM_TYPE_WTH``, for splitting a communicator into disjoint sets
+of ranks that share the same worker thread.
+
+For parsing Fortran command line arguments, AMPI Fortran programs should
+use our extension APIs, which are similar to Fortran 2003’s standard
+APIs. For example:
+
+.. code-block:: fortran
+
+   integer :: i, argc, ierr
+   integer, parameter :: arg_len = 128
+   character(len=arg_len), dimension(:), allocatable :: raw_arguments
+
+   call AMPI_Command_argument_count(argc)
+   allocate(raw_arguments(argc))
+   do i = 1, size(raw_arguments)
+       call AMPI_Get_command_argument(i, raw_arguments(i), arg_len, ierr)
+   end do
+
+Name for Main Program
+---------------------
+
+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:
+
+Fortran
+~~~~~~~
+
+You must declare the main program as a subroutine called "MPI_MAIN". Do
+not declare the main subroutine as a *program* because it will never be
+called by the AMPI runtime.
+
+.. code-block:: fortran
+
+   program pgm -> subroutine MPI_Main
+       ...                       ...
+   end program -> end subroutine
+
+C or C++
+~~~~~~~~
+
+The main function can be left as is, if ``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.
+
+Global Variable Privatization
+-----------------------------
+
+For the before-mentioned benefits to be effective, one needs to map
+multiple user-level threads onto each processor. Traditional MPI
+programs assume that the entire processor is allocated to themselves,
+and that only one thread of control exists within the process’s address
+space. So, they may safely use global and static variables in the
+program. However, global and static variables are problematic for
+multi-threaded environments such as AMPI or OpenMP. This is because
+there is a single instance of those variables so they will be shared
+among different threads in the single address space, so if programmers
+are not careful a wrong result may be produced by the program. Figure
+:numref:`fig_global` shows an example of a multi-threaded
+application with two threads in a single process. :math:`var` is a
+global or static variable in this example. Thread 1 assigns a value to
+it, then it gets blocked for communication and another thread can
+continue. Thereby, thread 2 is scheduled next and accesses :math:`var`
+which is wrong. The semantics of this program needs separate instances
+of :math:`var` for each of the threads. That is where the need arises to
+make some transformations to the original MPI program in order to run
+correctly with AMPI. Note, this is the only change necessary to run an
+MPI program with AMPI, that the program be thread-safe and have no
+global or static variables whose values differ across different MPI
+ranks. Also note that global variables that are constant or are only
+written to once to the same value across all ranks during initialization
+are already thread-safe.
+
+.. _fig_global:
+.. figure:: figs/global.png
+   :width: 4.6in
+
+   Mutable global or static variables are an issue for AMPI
+
+
+
+The basic transformation needed to port the MPI program to AMPI is
+privatization of global variables. With the MPI process model, each MPI
+node can keep a copy of its own "permanent variables" - variables that
+are accessible from more than one subroutines without passing them as
+arguments. Module variables, "saved" subroutine local variables, and
+common blocks in Fortran90 belong to this category. If such a program is
+executed without privatization on AMPI, all the AMPI threads that reside
+in the same process will access the same copy of such variables, which
+is clearly not the desired semantics. To ensure correct execution of the
+original source program, it is necessary to make such variables
+"private" to individual threads. We provide three choices with varying
+degrees of developer effort required and varying degrees of portability:
+manual encapsulation of global state, a thread-local storage based
+automated mechanism, and global offset table based automated mechanism.
+
+Automatic Thread-Local Storage Swapping
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Thread Local Store (TLS) was originally employed in kernel threads to
+localize variables to threads and provide thread safety. It can be used
+by annotating global/static variable declarations in C with
+*thread_local*, in C with *__thread* or C11 with *thread_local* or
+*_Thread_local*, and in Fortran with OpenMP’s *threadprivate*
+attribute. OpenMP is required for using tlsglobals in Fortran code since
+Fortran has no other method of using TLS. The *__thread* keyword is not
+an official extension of the C language, though compiler writers are
+encouraged to implement this feature. Currently, the ELF object file
+format supports Thread Local Storage.
+
+It handles both global and static variables and has no context-switching
+overhead. AMPI provides runtime support for privatizing thread-local
+variables to user-level threads by changing the TLS segment register
+when context switching between user-level threads. The runtime overhead
+is that of changing a single pointer per user-level thread context
+switch. Currently, Charm++ supports it for x86/x86_64 platforms when
+using GNU compilers.
+
+For the example above, the following changes to the code handle the
+global variables:
+
+::
+
+   // C++ example:
+   thread_local int myrank;
+   thread_local double xyz[100];
+
+   // C example:
+   __thread int myrank;
+   __thread double xyz[100];
+
+.. code-block:: fortran
+
+   ! Fortran example:
+   integer :: myrank
+   real*8, dimension(100) :: xyz
+   !$omp threadprivate(myrank)
+   !$omp threadprivate(xyz)
+
+The runtime system also should know that TLS-Globals is used at both
+compile and link time:
+
+.. code-block:: bash
+
+   ampicxx -o example example.C -tlsglobals
+
+Automatic Global Offset Table Swapping
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Thanks to the ELF Object Format, we have successfully automated the
+procedure of switching the set of user global variables when switching
+thread contexts. Executable and Linkable Format (ELF) is a common
+standard file format for Object Files in Unix-like operating systems.
+ELF maintains a Global Offset Table (GOT) for globals so it is possible
+to switch GOT contents at thread context-switch by the runtime system.
+
+The only thing that the user needs to do is pass the flag
+``-swapglobals`` at both compile and link time (e.g. "ampicc -o prog
+prog.c -swapglobals"). This method does not require any changes to the
+source code and works with any language (C, C++, Fortran, etc). However,
+it does not handle static variables, has a context switching overhead
+that grows with the number of global variables, and is incompatible with
+SMP builds of AMPI, where multiple virtual ranks can execute
+simultaneously on different scheduler threads within an OS process.
+Currently, this feature only works on x86 and x86_64 platforms that
+fully support ELF, and it requires ld version 2.23 or older, or else a
+patched version of ld 2.24+ that we provide here:
+https://charm.cs.illinois.edu/gerrit/gitweb?p=libbfd-patches.git;a=tree;f=swapglobals
+
+Manual Change
+~~~~~~~~~~~~~
+
+We have employed a strategy of argument passing to do this privatization
+transformation. That is, the global variables are bunched together in a
+single user-defined type, which is allocated by each thread dynamically
+or on the stack. Then a pointer to this type is passed from subroutine
+to subroutine as an argument. Since the subroutine arguments are passed
+on the stack, which is not shared across all threads, each subroutine
+when executing within a thread operates on a private copy of the global
+variables.
+
+This scheme is demonstrated in the following examples. The original
+Fortran90 code contains a module ``shareddata``. This module is used in
+the main program and a subroutine ``subA``.
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   MODULE shareddata
+     INTEGER :: myrank
+     DOUBLE PRECISION :: xyz(100)
+   END MODULE
+
+   SUBROUTINE MPI_MAIN
+     USE shareddata
+     include 'mpif.h'
+     INTEGER :: i, ierr
+     CALL MPI_Init(ierr)
+     CALL MPI_Comm_rank(MPI_COMM_WORLD, myrank, ierr)
+     DO i = 1, 100
+       xyz(i) =  i + myrank
+     END DO
+     CALL subA
+     CALL MPI_Finalize(ierr)
+   END PROGRAM
+
+   SUBROUTINE subA
+     USE shareddata
+     INTEGER :: i
+     DO i = 1, 100
+       xyz(i) = xyz(i) + 1.0
+     END DO
+   END SUBROUTINE
+
+::
+
+   //C Example
+   #include <mpi.h>
+
+   int myrank;
+   double xyz[100];
+
+   void subA();
+   int main(int argc, char** argv){
+     int i;
+     MPI_Init(&argc, &argv);
+     MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
+     for(i=0;i<100;i++)
+       xyz[i] = i + myrank;
+     subA();
+     MPI_Finalize();
+   }
+
+   void subA(){
+     int i;
+     for(i=0;i<100;i++)
+       xyz[i] = xyz[i] + 1.0;
+   }
+
+AMPI executes the main subroutine inside a user-level thread as a
+subroutine.
+
+Now we transform this program using the argument passing strategy. We
+first group the shared data into a user-defined type.
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   MODULE shareddata
+     TYPE chunk ! modified
+       INTEGER :: myrank
+       DOUBLE PRECISION :: xyz(100)
+     END TYPE ! modified
+   END MODULE
+
+::
+
+   //C Example
+   struct shareddata{
+     int myrank;
+     double xyz[100];
+   };
+
+Now we modify the main subroutine to dynamically allocate this data and
+change the references to them. Subroutine ``subA`` is then modified to
+take this data as argument.
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   SUBROUTINE MPI_Main
+     USE shareddata
+     USE AMPI
+     INTEGER :: i, ierr
+     TYPE(chunk), pointer :: c ! modified
+     CALL MPI_Init(ierr)
+     ALLOCATE(c) ! modified
+     CALL MPI_Comm_rank(MPI_COMM_WORLD, c%myrank, ierr)
+     DO i = 1, 100
+       c%xyz(i) =  i + c%myrank ! modified
+     END DO
+     CALL subA(c)
+     CALL MPI_Finalize(ierr)
+   END SUBROUTINE
+
+   SUBROUTINE subA(c)
+     USE shareddata
+     TYPE(chunk) :: c ! modified
+     INTEGER :: i
+     DO i = 1, 100
+       c%xyz(i) = c%xyz(i) + 1.0 ! modified
+     END DO
+   END SUBROUTINE
+
+::
+
+   //C Example
+   void MPI_Main{
+     int i,ierr;
+     struct shareddata *c;
+     ierr = MPI_Init();
+     c = (struct shareddata*)malloc(sizeof(struct shareddata));
+     ierr = MPI_Comm_rank(MPI_COMM_WORLD, c.myrank);
+     for(i=0;i<100;i++)
+       c.xyz[i] = i + c.myrank;
+     subA(c);
+     ierr = MPI_Finalize();
+   }
+
+   void subA(struct shareddata *c){
+     int i;
+     for(i=0;i<100;i++)
+       c.xyz[i] = c.xyz[i] + 1.0;
+   }
+
+With these changes, the above program can be made thread-safe. Note that
+it is not really necessary to dynamically allocate ``chunk``. One could
+have declared it as a local variable in subroutine ``MPI_Main``. (Or for
+a small example such as this, one could have just removed the
+``shareddata`` module, and instead declared both variables ``xyz`` and
+``myrank`` as local variables). This is indeed a good idea if shared
+data are small in size. For large shared data, it would be better to do
+heap allocation because in AMPI, the stack sizes are fixed at the
+beginning (and can be specified from the command line) and stacks do not
+grow dynamically.
+
+Source-to-source Transformation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Another approach is to do the changes described in the previous scheme
+automatically. It means that we can use a tool to transform the source
+code to move global or static variables in an object and pass them
+around. This approach is portable across systems and compilers and may
+also improve locality and hence cache utilization. It also does not have
+the context-switch overhead of swapping globals. We have multiple tools
+for automating these transformations for different languages. Currently,
+there is a tool called *Photran*\  [3]_ for refactoring Fortran codes
+that can do this transformation. It is Eclipse-based and works by
+constructing Abstract Syntax Trees (ASTs) of the program. We also have a
+tool built on top of the *ROSE compiler*\  [4]_ that works for C/C++ and
+Fortran programs that is available upon request. It emits patches for
+all files containing global variables which can then be applied to the
+source code.
+
+Table :numref:`tab:portability` shows portability of
+different schemes.
+
+.. _tab:portability:
+.. 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.
+
+   ==================== === ====== ====== ==== ======= ===== =====
+   Privatization Scheme x86 x86_64 Mac OS BG/Q Windows PPC   ARM7
+   ==================== === ====== ====== ==== ======= ===== =====
+   Transformation       Yes Yes    Yes    Yes  Yes     Yes   Yes
+   GOT-Globals          Yes Yes    No     No   No      Yes   Yes
+   TLS-Globals          Yes Yes    No     No   Maybe   Maybe Maybe
+   ==================== === ====== ====== ==== ======= ===== =====
+
+Extensions for Migrations
+-------------------------
+
+AMPI provides fully automated support for migrating MPI ranks between
+nodes of a system without any application-specific code at all. We do so
+using a memory allocator, Isomalloc, that allocates memory per
+user-level thread to globally unique virtual memory addresses. This
+means that every worker thread in the system reserves slices of virtual
+memory for all user-level threads, allowing transparent migration of
+stacks and pointers into memory (Isomalloc requires 64-bit virtual
+memory addresses and support from the operating system for mapping
+memory to arbitrary virtual addresses). Applications only need to link
+with Isomalloc to enable automatic migratability, using *-memory
+isomalloc*.
+
+For systems that do not support Isomalloc and for users that wish to
+have more fine-grain control over which application data structures will
+be copied at migration time, we have added a few calls to AMPI. These
+include the ability to register thread-specific data with the run-time
+system, to pack and unpack all of the thread’s data, and to express
+willingness to migrate.
+
+Registering User Data
+~~~~~~~~~~~~~~~~~~~~~
+
+When the AMPI runtime system decides that load imbalance exists within
+the application, it will invoke one of its internal load balancing
+strategies, which determines the new mapping of AMPI ranks so as to
+balance the load. Then the AMPI runtime packs up the rank’s state and
+moves it to its new home processor. AMPI packs up any internal data in
+use by the rank, including the thread’s stack in use. This means that
+the local variables declared in subroutines in a rank, which are created
+on stack, are automatically packed up by the AMPI runtime system.
+However, it has no way of knowing what other data are in use by the
+rank. Thus upon starting execution, a rank needs to notify the system
+about the data that it is going to use (apart from local variables).
+Even with the data registration, AMPI cannot determine what size the
+data is, or whether the registered data contains pointers to other
+places in memory. For this purpose, a packing subroutine also needs to
+be provided to the AMPI runtime system along with registered data. (See
+next section for writing packing subroutines.) The call provided by AMPI
+for doing this is ``AMPI_Register_pup``. This function takes three
+arguments: a data item to be transported along with the rank, the pack
+subroutine, and a pointer to an integer which denotes the registration
+identifier. In C/C++ programs, it may be necessary to use this integer
+value after migration completes and control returns to the rank with the
+function ``AMPI_Get_pup_data``.
+
+Migration
+~~~~~~~~~
+
+The AMPI runtime system could detect load imbalance by itself and invoke
+the load balancing strategy. However, since the application code is
+going to pack/unpack the rank’s data, writing the pack subroutine will
+be complicated if migrations occur at a stage unknown to the
+application. For example, if the system decides to migrate a rank while
+it is in initialization stage (say, reading input files), application
+code will have to keep track of how much data it has read, what files
+are open etc. Typically, since initialization occurs only once in the
+beginning, load imbalance at that stage would not matter much.
+Therefore, we want the demand to perform load balance check to be
+initiated by the application.
+
+AMPI provides a subroutine ``AMPI_Migrate(MPI_Info hints);`` for this
+purpose. Each rank periodically calls ``AMPI_Migrate``. Typical CSE
+applications are iterative and perform multiple time-steps. One should
+call ``AMPI_Migrate`` in each rank at the end of some fixed number of
+timesteps. The frequency of ``AMPI_Migrate`` should be determined by a
+tradeoff between conflicting factors such as the load balancing
+overhead, and performance degradation caused by load imbalance. In some
+other applications, where application suspects that load imbalance may
+have occurred, as in the case of adaptive mesh refinement; it would be
+more effective if it performs a couple of timesteps before telling the
+system to re-map ranks. This will give the AMPI runtime system some time
+to collect the new load and communication statistics upon which it bases
+its migration decisions. Note that ``AMPI_Migrate`` does NOT tell the
+system to migrate the rank, but merely tells the system to check the
+load balance after all the ranks call ``AMPI_Migrate``. To migrate the
+rank or not is decided only by the system’s load balancing strategy.
+
+Essentially, a call to ``AMPI_Migrate`` signifies to the runtime system
+that the application has reached a point at which it is safe to
+serialize the local state. Knowing this, the runtime system can act in
+several ways.
+
+The MPI_Info object taken as a parameter by ``AMPI_Migrate`` gives users
+a way to influence the runtime system’s decision-making and behavior.
+AMPI provides two built-in MPI_Info objects for this, called
+``AMPI_INFO_LB_SYNC`` and ``AMPI_INFO_LB_ASYNC``. Synchronous load
+balancing assumes that the application is already at a synchronization
+point. Asynchronous load balancing does not assume this.
+
+Calling ``AMPI_Migrate`` on a rank with pending send requests (i.e. from
+MPI_Isend) is currently not supported, therefore users should always
+wait on any outstanding send requests before calling ``AMPI_Migrate``.
+
+::
+
+   // Main time-stepping loop
+   for (int iter=0; iter < max_iters; iter++) {
+
+     // Time step work ...
+
+     if (iter % lb_freq == 0)
+       AMPI_Migrate(AMPI_INFO_LB_SYNC);
+   }
+
+Note that migrating ranks around the cores and nodes of a system can
+change which ranks share physical resources, such as memory. A
+consequence of this is that communicators created via
+``MPI_Comm_split_type`` are invalidated by calls to ``AMPI_Migrate``
+that result in migration which breaks the semantics of that communicator
+type. The only valid routine to call on such communicators is
+``MPI_Comm_free``.
+
+We also provide callbacks that user code can register with the runtime
+system to be invoked just before and right after migration:
+``AMPI_Register_about_to_migrate`` and ``AMPI_Register_just_migrated``
+respectively. Note that the callbacks are only invoked on those ranks
+that are about to actually migrate or have just actually migrated.
+
+AMPI provide routines for starting and stopping load measurements, and
+for users to explicitly set the load value of a rank using the
+following: ``AMPI_Load_start_measure``, ``AMPI_Load_stop_measure``,
+``AMPI_Load_reset_measure``, and ``AMPI_Load_set_value``. And since AMPI
+builds on top of Charm++, users can experiment with the suite of load
+balancing strategies included with Charm++, as well as write their own
+strategies based on user-level information and heuristics.
+
+Packing/Unpacking Thread Data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once the AMPI runtime system decides which ranks to send to which
+processors, it calls the specified pack subroutine for that rank, with
+the rank-specific data that was registered with the system using
+``AMPI_Register_pup``. If an AMPI application uses Isomalloc, then the
+system will define the Pack/Unpack routines for the user. This section
+explains how a subroutine should be written for performing explicit
+pack/unpack.
+
+There are three steps for transporting the rank’s data to another
+processor. First, the system calls a subroutine to get the size of the
+buffer required to pack the rank’s data. This is called the "sizing"
+step. In the next step, which is called immediately afterward on the
+source processor, the system allocates the required buffer and calls the
+subroutine to pack the rank’s data into that buffer. This is called the
+"packing" step. This packed data is then sent as a message to the
+destination processor, where first a rank is created (along with the
+thread) and a subroutine is called to unpack the rank’s data from the
+buffer. This is called the "unpacking" step.
+
+Though the above description mentions three subroutines called by the
+AMPI runtime system, it is possible to actually write a single
+subroutine that will perform all the three tasks. This is achieved using
+something we call a "pupper". A pupper is an external subroutine that is
+passed to the rank’s pack-unpack-sizing subroutine, and this subroutine,
+when called in different phases performs different tasks. An example
+will make this clear:
+
+Suppose the user data, chunk, is defined as a derived type in Fortran90:
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   MODULE chunkmod
+     INTEGER, parameter :: nx=4, ny=4, tchunks=16
+     TYPE, PUBLIC :: chunk
+         REAL(KIND=8) t(22,22)
+         INTEGER xidx, yidx
+         REAL(KIND=8), dimension(400):: bxm, bxp, bym, byp
+     END TYPE chunk
+   END MODULE
+
+::
+
+   //C Example
+   struct chunk{
+     double t;
+     int xidx, yidx;
+     double bxm,bxp,bym,byp;
+   };
+
+Then the pack-unpack subroutine ``chunkpup`` for this chunk module is
+written as:
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   SUBROUTINE chunkpup(p, c)
+     USE pupmod
+     USE chunkmod
+     IMPLICIT NONE
+     INTEGER :: p
+     TYPE(chunk) :: c
+
+     call pup(p, c%t)
+     call pup(p, c%xidx)
+     call pup(p, c%yidx)
+     call pup(p, c%bxm)
+     call pup(p, c%bxp)
+     call pup(p, c%bym)
+     call pup(p, c%byp)
+   end subroutine
+
+::
+
+   //C Example
+   void chunkpup(pup_er p, struct chunk c){
+     pup_double(p,c.t);
+     pup_int(p,c.xidx);
+     pup_int(p,c.yidx);
+     pup_double(p,c.bxm);
+     pup_double(p,c.bxp);
+     pup_double(p,c.bym);
+     pup_double(p,c.byp);
+   }
+
+There are several things to note in this example. First, the same
+subroutine ``pup`` (declared in module ``pupmod``) is called to
+size/pack/unpack any type of data. This is possible because of procedure
+overloading possible in Fortran90. Second is the integer argument ``p``.
+It is this argument that specifies whether this invocation of subroutine
+``chunkpup`` is sizing, packing or unpacking. Third, the integer
+parameters declared in the type ``chunk`` need not be packed or unpacked
+since they are guaranteed to be constants and thus available on any
+processor.
+
+A few other functions are provided in module ``pupmod``. These functions
+provide more control over the packing/unpacking process. Suppose one
+modifies the ``chunk`` type to include allocatable data or pointers that
+are allocated dynamically at runtime. In this case, when chunk is
+packed, these allocated data structures should be deallocated after
+copying them to buffers, and when chunk is unpacked, these data
+structures should be allocated before copying them from the buffers. For
+this purpose, one needs to know whether the invocation of ``chunkpup``
+is a packing one or unpacking one. For this purpose, the ``pupmod``
+module provides functions ``fpup_isdeleting``\ (``fpup_isunpacking``).
+These functions return logical value ``.TRUE.`` if the invocation is for
+packing (unpacking), and ``.FALSE.`` otherwise. The following example
+demonstrates this:
+
+Suppose the type ``dchunk`` is declared as:
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   MODULE dchunkmod
+     TYPE, PUBLIC :: dchunk
+         INTEGER :: asize
+         REAL(KIND=8), pointer :: xarr(:), yarr(:)
+     END TYPE dchunk
+   END MODULE
+
+::
+
+   //C Example
+   struct dchunk{
+     int asize;
+     double* xarr, *yarr;
+   };
+
+Then the pack-unpack subroutine is written as:
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   SUBROUTINE dchunkpup(p, c)
+     USE pupmod
+     USE dchunkmod
+     IMPLICIT NONE
+     INTEGER :: p
+     TYPE(dchunk) :: c
+
+     pup(p, c%asize)
+
+     IF (fpup_isunpacking(p)) THEN       !! if invocation is for unpacking
+       allocate(c%xarr(c%asize))
+       ALLOCATE(c%yarr(c%asize))
+     ENDIF
+
+     pup(p, c%xarr)
+     pup(p, c%yarr)
+
+     IF (fpup_isdeleting(p)) THEN        !! if invocation is for packing
+       DEALLOCATE(c%xarr)
+       DEALLOCATE(c%yarr)
+     ENDIF
+
+
+   END SUBROUTINE
+
+::
+
+   //C Example
+   void dchunkpup(pup_er p, struct dchunk c){
+     pup_int(p,c.asize);
+     if(pup_isUnpacking(p)){
+       c.xarr = (double *)malloc(sizeof(double)*c.asize);
+       c.yarr = (double *)malloc(sizeof(double)*c.asize);
+     }
+     pup_doubles(p,c.xarr,c.asize);
+     pup_doubles(p,c.yarr,c.asize);
+     if(pup_isPacking(p)){
+       free(c.xarr);
+       free(c.yarr);
+     }
+   }
+
+One more function ``fpup_issizing`` is also available in module
+``pupmod`` that returns ``.TRUE.`` when the invocation is a sizing one.
+In practice one almost never needs to use it.
+
+Charm++ also provides higher-level PUP routines for C++ STL data
+structures and Fortran90 data types. The STL PUP routines will deduce
+the size of the structure automatically, so that the size of the data
+does not have to be passed in to the PUP routine. This facilitates
+writing PUP routines for large pre-existing codebases. To use it, simply
+include pup_stl.h in the user code. For modern Fortran with pointers and
+allocatable data types, AMPI provides a similarly automated PUP
+interface called apup. User code can include pupmod and then call apup()
+on any array (pointer or allocatable, multi-dimensional) of built-in
+types (character, short, int, long, real, double, complex, double
+complex, logical) and the runtime will deduce the size and shape of the
+array, including unassociated and NULL pointers. Here is the dchunk
+example from earlier, written to use the apup interface:
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   SUBROUTINE dchunkpup(p, c)
+     USE pupmod
+     USE dchunkmod
+     IMPLICIT NONE
+     INTEGER :: p
+     TYPE(dchunk) :: c
+
+     !! no need for asize
+     !! no isunpacking allocation necessary
+
+     apup(p, c%xarr)
+     apup(p, c%yarr)
+
+     !! no isdeleting deallocation necessary
+
+   END SUBROUTINE
+
+Calling ``MPI_`` routines or accessing global variables that have been
+privatized by use of tlsglobals or swapglobals from inside a user PUP
+routine is currently not allowed in AMPI. Users can store MPI-related
+information like communicator rank and size in data structures to be be
+packed and unpacked before they are needed inside a PUP routine.
+
+Extensions for Checkpointing
+----------------------------
+
+The pack-unpack subroutines written for migrations make sure that the
+current state of the program is correctly packed (serialized) so that it
+can be restarted on a different processor. Using the *same* subroutines,
+it is also possible to save the state of the program to disk, so that if
+the program were to crash abruptly, or if the allocated time for the
+program expires before completing execution, the program can be
+restarted from the previously checkpointed state. Thus, the pack-unpack
+subroutines act as the key facility for checkpointing in addition to
+their usual role for migration. Just as in load balancing, no
+application specific code is required when using Isomalloc: the AMPI
+runtime takes care of all the details involved in migrating data.
+
+To perform a checkpoint in an AMPI program, all you have to do is make a
+call to ``int AMPI_Migrate(MPI_Info hints)`` with an ``MPI_Info`` object
+that specifies how you would like to checkpoint. Checkpointing can be
+thought of as migrating AMPI ranks to storage. Users set the
+checkpointing policy on an ``MPI_Info`` object’s ``"ampi_checkpoint"``
+key to one of the following values: ``"to_file=directory_name"`` or
+``"false"``. To perform checkpointing in memory a built-in MPI_Info
+object called ``AMPI_INFO_CHKPT_IN_MEMORY`` is provided.
+
+Checkpointing to file tells the runtime system to save checkpoints in a
+given directory. (Typically, in an iterative program, the iteration
+number, converted to a character string, can serve as a checkpoint
+directory name.) This directory is created, and the entire state of the
+program is checkpointed to this directory. One can restart the program
+from the checkpointed state (using the same, more, or fewer physical
+processors than were checkpointed with) by specifying
+``"+restart directory_name"`` on the command-line.
+
+Checkpointing in memory allows applications to transparently tolerate
+failures online. The checkpointing scheme used here is a double
+in-memory checkpoint, in which virtual processors exchange checkpoints
+pairwise across nodes in each other’s memory such that if one node
+fails, that failed node’s AMPI ranks can be restarted by its buddy once
+the failure is detected by the runtime system. As long as no two buddy
+nodes fail in the same checkpointing interval, the system can restart
+online without intervention from the user (provided the job scheduler
+does not revoke its allocation). Any load imbalance resulting from the
+restart can then be managed by the runtime system. Use of this scheme is
+illustrated in the code snippet below.
+
+::
+
+   // Main time-stepping loop
+   for (int iter=0; iter < max_iters; iter++) {
+
+     // Time step work ...
+
+     if (iter % chkpt_freq == 0)
+       AMPI_Migrate(AMPI_INFO_CHKPT_IN_MEMORY);
+   }
+
+A value of ``"false"`` results in no checkpoint being done that step.
+Note that ``AMPI_Migrate`` is a collective function, meaning every
+virtual processor in the program needs to call this subroutine with the
+same MPI_Info object. The checkpointing capabilities of AMPI are powered
+by the Charm++ runtime system. For more information about
+checkpoint/restart mechanisms please refer to the Charm++
+manual: :numref:`sec:checkpoint`.
+
+Extensions for Memory Efficiency
+--------------------------------
+
+MPI functions usually require the user to preallocate the data buffers
+needed before the functions being called. For unblocking communication
+primitives, sometimes the user would like to do lazy memory allocation
+until the data actually arrives, which gives the opportunities to write
+more memory efficient programs. We provide a set of AMPI functions as an
+extension to the standard MPI-2 one-sided calls, where we provide a
+split phase ``MPI_Get`` called ``AMPI_Iget``. ``AMPI_Iget`` preserves
+the similar semantics as ``MPI_Get`` except that no user buffer is
+provided to hold incoming data. ``AMPI_Iget_wait`` will block until the
+requested data arrives and runtime system takes care to allocate space,
+do appropriate unpacking based on data type, and return.
+``AMPI_Iget_free`` lets the runtime system free the resources being used
+for this get request including the data buffer. Finally,
+``AMPI_Iget_data`` is the routine used to access the data.
+
+::
+
+
+   int AMPI_Iget(MPI_Aint orgdisp, int orgcnt, MPI_Datatype orgtype, int rank,
+                 MPI_Aint targdisp, int targcnt, MPI_Datatype targtype, MPI_Win win,
+                 MPI_Request *request);
+
+   int AMPI_Iget_wait(MPI_Request *request, MPI_Status *status, MPI_Win win);
+
+   int AMPI_Iget_free(MPI_Request *request, MPI_Status *status, MPI_Win win);
+
+   int AMPI_Iget_data(void *data, MPI_Status status);
+
+Extensions for Interoperability
+-------------------------------
+
+Interoperability between different modules is essential for coding
+coupled simulations. In this extension to AMPI, each MPI application
+module runs within its own group of user-level threads distributed over
+the physical parallel machine. In order to let AMPI know which ranks are
+to be created, and in what order, a top level registration routine needs
+to be written. A real-world example will make this clear. We have an MPI
+code for fluids and another MPI code for solids, both with their main
+programs, then we first transform each individual code to run correctly
+under AMPI as standalone codes. Aside from the global and static
+variable privatization transformations needed, this also involves making
+the main program into a subroutine and naming it ``MPI_Main``.
+
+Thus now, we have two ``MPI_Main``\ s, one for the fluids code and one
+for the solids code. We now make these codes co-exist within the same
+executable, by first renaming these ``MPI_Main``\ s as ``Fluids_Main``
+and ``Solids_Main``\  [5]_ writing a subroutine called ``MPI_Setup``.
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   SUBROUTINE MPI_Setup
+     USE ampi
+     CALL AMPI_Register_main(Solids_Main)
+     CALL AMPI_Register_main(Fluids_Main)
+   END SUBROUTINE
+
+::
+
+   //C Example
+   void MPI_Setup(){
+     AMPI_Register_main(Solids_Main);
+     AMPI_Register_main(Fluids_Main);
+   }
+
+This subroutine is called from the internal initialization routines of
+AMPI and tells AMPI how many numbers of distinct modules exist, and
+which orchestrator subroutines they execute.
+
+The number of ranks to create for each module is specified on the
+command line when an AMPI program is run. Appendix B explains how AMPI
+programs are run, and how to specify the number of ranks (``+vp``
+option). In the above case, suppose one wants to create 128 ranks of
+Solids and 64 ranks of Fluids on 32 physical processors, one would
+specify those with multiple ``+vp`` options on the command line as:
+
+::
+
+   > ./charmrun gen1.x +p 32 +vp 128 +vp 64
+
+This will ensure that multiple modules representing different complete
+applications can co-exist within the same executable. They can also
+continue to communicate among their own ranks using the same AMPI
+function calls to send and receive with communicator argument as
+``MPI_COMM_WORLD``. But this would be completely useless if these
+individual applications cannot communicate with each other, which is
+essential for building efficient coupled codes. For this purpose, we
+have extended the AMPI functionality to allow multiple
+"``COMM_WORLD``\ s"; one for each application. These *world
+communicators* form a "communicator universe" an array of communicators
+aptly called *MPI_COMM_UNIVERSE*. This array of communicators is indexed
+[1 . . . ``MPI_MAX_COMM``]. In the current implementation,
+``MPI_MAX_COMM`` is 8, that is, maximum of 8 applications can co-exist
+within the same executable.
+
+The order of these ``COMM_WORLD``\ s within ``MPI_COMM_UNIVERSE`` is
+determined by the order in which individual applications are registered
+in ``MPI_Setup``.
+
+Thus, in the above example, the communicator for the Solids module would
+be ``MPI_COMM_UNIVERSE(1)`` and communicator for Fluids module would be
+``MPI_COMM_UNIVERSE(2)``.
+
+Now any rank within one application can communicate with any rank in the
+other application using the familiar send or receive AMPI calls by
+specifying the appropriate communicator and the rank number within that
+communicator in the call. For example if a Solids rank number 36 wants
+to send data to rank number 47 within the Fluids module, it calls:
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   INTEGER , PARAMETER :: Fluids_Comm = 2
+   CALL MPI_Send(InitialTime, 1, MPI_Double_Precision, tag,
+                 47, MPI_Comm_Universe(Fluids_Comm), ierr)
+
+::
+
+   //C Example
+   int Fluids_Comm = 2;
+   ierr = MPI_Send(InitialTime, 1, MPI_DOUBLE, tag,
+                   47, MPI_Comm_Universe(Fluids_Comm));
+
+The Fluids rank has to issue a corresponding receive call to receive
+this data:
+
+.. code-block:: fortran
+
+   !FORTRAN EXAMPLE
+   INTEGER , PARAMETER :: Solids_Comm = 1
+   CALL MPI_Recv(InitialTime, 1, MPI_Double_Precision, tag,
+                 36, MPI_Comm_Universe(Solids_Comm), stat, ierr)
+
+::
+
+   //C Example
+   int Solids_Comm = 1;
+   ierr = MPI_Recv(InitialTime, 1, MPI_DOUBLE, tag,
+                   36, MPI_Comm_Universe(Solids_Comm), &stat);
+
+Extensions for Sequential Re-run of a Parallel Node
+---------------------------------------------------
+
+In some scenarios, a sequential re-run of a parallel node is desired.
+One example is instruction-level accurate architecture simulations, in
+which case the user may wish to repeat the execution of a node in a
+parallel run in the sequential simulator. AMPI provides support for such
+needs by logging the change in the MPI environment on a certain
+processors. To activate the feature, build AMPI module with variable
+"AMPIMSGLOG" defined, like the following command in charm directory.
+(Linking with zlib "-lz" might be required with this, for generating
+compressed log file.)
+
+::
+
+   > ./build AMPI netlrts-linux-x86_64 -DAMPIMSGLOG
+
+The feature is used in two phases: writing (logging) the environment and
+repeating the run. The first logging phase is invoked by a parallel run
+of the AMPI program with some additional command line options.
+
+::
+
+   > ./charmrun ./pgm +p4 +vp4 +msgLogWrite +msgLogRank 2 +msgLogFilename "msg2.log"
+
+In the above example, a parallel run with 4 worker threads and 4 AMPI
+ranks will be executed, and the changes in the MPI environment of worker
+thread 2 (also rank 2, starting from 0) will get logged into diskfile
+"msg2.log".
+
+Unlike the first run, the re-run is a sequential program, so it is not
+invoked by charmrun (and omitting charmrun options like +p4 and +vp4),
+and additional command line options are required as well.
+
+::
+
+   > ./pgm +msgLogRead +msgLogRank 2 +msgLogFilename "msg2.log"
+
+User Defined Initial Mapping
+----------------------------
+
+You can define the initial mapping of virtual processors (vp) to
+physical processors (p) as a runtime option. You can choose from
+predefined initial mappings or define your own mappings. The following
+predefined mappings are available:
+
+Round Robin
+   This mapping scheme maps virtual processor to physical processor in
+   round-robin fashion, i.e. if there are 8 virtual processors and 2
+   physical processors then virtual processors indexed 0,2,4,6 will be
+   mapped to physical processor 0 and virtual processors indexed 1,3,5,7
+   will be mapped to physical processor 1.
+
+   .. code-block:: bash
+
+      > ./charmrun ./hello +p2 +vp8 +mapping RR_MAP
+
+Block Mapping
+   This mapping scheme maps virtual processors to physical processor in
+   ranks, i.e. if there are 8 virtual processors and 2 physical
+   processors then virtual processors indexed 0,1,2,3 will be mapped to
+   physical processor 0 and virtual processors indexed 4,5,6,7 will be
+   mapped to physical processor 1.
+
+   .. code-block:: bash
+
+      > ./charmrun ./hello +p2 +vp8 +mapping BLOCK_MAP
+
+Proportional Mapping
+   This scheme takes the processing capability of physical processors
+   into account for mapping virtual processors to physical processors,
+   i.e. if there are 2 processors running at different frequencies, then
+   the number of virtual processors mapped to processors will be in
+   proportion to their processing power. To make the load balancing
+   framework aware of the heterogeneity of the system, the flag
+   *+LBTestPESpeed* should also be used.
+
+   .. code-block:: bash
+
+      > ./charmrun ./hello +p2 +vp8 +mapping PROP_MAP
+      > ./charmrun ./hello +p2 +vp8 +mapping PROP_MAP +balancer GreedyLB +LBTestPESpeed
+
+If you want to define your own mapping scheme, please contact us for
+assistance.
+
+Performance Visualization
+-------------------------
+
+AMPI users can take advantage of Charm++’s tracing framework and
+associated performance visualization tool, Projections. Projections
+provides a number of different views of performance data that help users
+diagnose performance issues. Along with the traditional Timeline view,
+Projections also offers visualizations of load imbalance and
+communication-related data.
+
+In order to generate tracing logs from an application to view in
+Projections, link with ``ampicc -tracemode projections``.
+
+AMPI defines the following extensions for tracing support:
+
+::
+
+   AMPI_Trace_begin                      AMPI_Trace_end
+
+When using the *Timeline* view in Projections, AMPI users can visualize
+what each VP on each processor is doing (what MPI method it is running
+or blocked in) by clicking the *View* tab and then selecting *Show
+Nested Bracketed User Events* from the drop down menu. See the
+Projections manual for information on performance analysis and
+visualization.
+
+AMPI users can also use any tracing libraries or tools that rely on
+MPI’s PMPI profiling interface, though such tools may not be aware of
+AMPI process virtualization.
+
+Compiling AMPI Programs
+-----------------------
+
+AMPI provides a cross-platform compile-and-link script called *ampicc*
+to compile C, C++, and Fortran AMPI programs. This script resides in the
+``bin`` subdirectory in the Charm++ installation directory. The main
+purpose of this script is to deal with the differences of various
+compiler names and command-line options across various machines on which
+AMPI runs. It is recommended that the AMPI compiler scripts be used to
+compile and link AMPI programs. One major advantage of using these is
+that one does not have to specify which libraries are to be linked for
+ensuring that C++ and Fortran90 codes are linked together correctly.
+Appropriate libraries required for linking such modules together are
+known to *ampicc* for various machines.
+
+In spite of the platform-neutral syntax of *ampicc*, one may have to
+specify some platform-specific options for compiling and building AMPI
+codes. Fortunately, if *ampicc* does not recognize any particular
+options on its command line, it promptly passes it to all the individual
+compilers and linkers it invokes to compile the program. See the
+appendix for more details on building and running AMPI programs.
+
+.. _adaptive-mpi-ampi-codes:
+
+AMPI Example Applications
+-------------------------
+
+| This section contains a list of applications that have been written or
+  adapted to work with AMPI. Most applications are available on git:
+| ``git clone ssh://charm.cs.illinois.edu:9418/benchmarks/ampi-benchmarks``.
+
+Most benchmarks can be compiled with the provided top-level Makefile:
+
+::
+
+       > git clone ssh://charm.cs.illinois.edu:9418/benchmarks/ampi-benchmarks
+       > cd ampi-benchmarks
+       > make -f Makefile.ampi
+
+Mantevo project v3.0
+~~~~~~~~~~~~~~~~~~~~
+
+Set of mini-apps from the Mantevo project. Download at
+https://mantevo.org/download/.
+
+MiniFE
+^^^^^^
+
+-  Mantevo mini-app for unstructured implicit Finite Element
+   computations.
+
+-  No changes necessary to source to run on AMPI. Modify file
+   ``makefile.ampi`` and change variable ``AMPIDIR`` to point to your
+   Charm++ directory, execute ``make -f makefile.ampi`` to build the
+   program.
+
+-  Refer to the ``README`` file on how to run the program. For example:
+   ``./charmrun +p4 ./miniFE.x nx=30 ny=30 nz=30 +vp32``
+
+MiniMD v2.0
+^^^^^^^^^^^
+
+-  Mantevo mini-app for particle interaction in a Lennard-Jones system,
+   as in the LAMMPS MD code.
+
+-  No changes necessary to source code. Modify file ``Makefile.ampi``
+   and change variable ``AMPIDIR`` to point to your Charm++ directory,
+   execute ``make ampi`` to build the program.
+
+-  Refer to the ``README`` file on how to run the program. For example:
+   ``./charmrun +p4 ./miniMD_ampi +vp32``
+
+CoMD v1.1
+^^^^^^^^^
+
+-  Mantevo mini-app for molecular dynamics codes:
+   https://github.com/exmatex/CoMD
+
+-  To AMPI-ize it, we had to remove calls to not thread-safe
+   ``getopt()``. Support for dynamic load balancing has been added in
+   the main loop and the command line options. It will run on all
+   platforms.
+
+-  Just update the Makefile to point to AMPI compilers and run with the
+   provided run scripts.
+
+MiniXYCE v1.0
+^^^^^^^^^^^^^
+
+-  Mantevo mini-app for discrete analog circuit simulation, version 1.0,
+   with serial, MPI, OpenMP, and MPI+OpenMP versions.
+
+-  No changes besides Makefile necessary to run with virtualization. To
+   build, do ``cp common/generate_info_header miniXyce_ref/.``, modify
+   the CC path in ``miniXyce_ref/`` and run ``make``. Run scripts are in
+   ``test/``.
+
+-  Example run command:
+   ``./charmrun +p3 ./miniXyce.x +vp3 -circuit ../tests/cir1.net -t_start 1e-6 -pf params.txt``
+
+HPCCG v1.0
+^^^^^^^^^^
+
+-  Mantevo mini-app for sparse iterative solves using the Conjugate
+   Gradient method for a problem similar to that of MiniFE.
+
+-  No changes necessary except to set compilers in ``Makefile`` to the
+   AMPI compilers.
+
+-  Run with a command such as:
+   ``./charmrun +p2 ./test_HPCCG 20 30 10 +vp16``
+
+MiniAMR v1.0
+^^^^^^^^^^^^
+
+-  miniAMR applies a stencil calculation on a unit cube computational
+   domain, which is refined over time.
+
+-  No changes if using swap-globals. Explicitly extern global variables
+   if using TLS.
+
+Not yet AMPI-zed (reason):
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+MiniAero v1.0 (build issues), MiniGhost v1.0.1 (globals), MiniSMAC2D
+v2.0 (globals), TeaLeaf v1.0 (globals), CloverLeaf v1.1 (globals),
+CloverLeaf3D v1.0 (globals).
+
+LLNL ASC Proxy Apps
+~~~~~~~~~~~~~~~~~~~
+
+LULESH v2.0
+^^^^^^^^^^^
+
+-  LLNL Unstructured Lagrangian-Eulerian Shock Hydrodynamics proxy app:
+   https://codesign.llnl.gov/lulesh.php
+
+-  Charm++, MPI, MPI+OpenMP, Liszt, Loci, Chapel versions all exist for
+   comparison.
+
+-  Manually privatized version of LULESH 2.0, plus a version with PUP
+   routines in subdirectory ``pup_lulesh202/``.
+
+AMG 2013
+^^^^^^^^
+
+-  LLNL ASC proxy app: Algebraic Multi-Grid solver for linear systems
+   arising from unstructured meshes:
+   https://codesign.llnl.gov/amg2013.php
+
+-  AMG is based on HYPRE, both from LLNL. The only change necessary to
+   get AMG running on AMPI with virtualization is to remove calls to
+   HYPRE’s timing interface, which is not thread-safe.
+
+-  To build, point the CC variable in Makefile.include to your AMPI CC
+   wrapper script and ``make``. Executable is ``test/amg2013``.
+
+Lassen v1.0
+^^^^^^^^^^^
+
+-  LLNL ASC mini-app for wave-tracking applications with dynamic load
+   imbalance. Reference versions are serial, MPI, Charm++, and
+   MPI/Charm++ interop: https://codesign.llnl.gov/lassen.php
+
+-  No changes necessary to enable AMPI virtualization. Requires some
+   C++11 support. Set ``AMPIDIR`` in Makefile and ``make``. Run with:
+   ``./charmrun +p4 ./lassen_mpi +vp8 default 2 2 2 50 50 50``
+
+Kripke v1.1
+^^^^^^^^^^^
+
+-  LLNL ASC proxy app for ARDRA, a full Sn deterministic particle
+   transport application: https://codesign.llnl.gov/kripke.php
+
+-  Charm++, MPI, MPI+OpenMP, MPI+RAJA, MPI+CUDA, MPI+OCCA versions exist
+   for comparison.
+
+-  Kripke requires no changes between MPI and AMPI since it has no
+   global/static variables. It uses cmake so edit the cmake toolchain
+   files in ``cmake/toolchain/`` to point to the AMPI compilers, and
+   build in a build directory:
+
+   .. code-block:: bash
+
+      > mkdir build; cd build;
+      > cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain/linux-gcc-ampi.cmake
+      -DENABLE_OPENMP=OFF
+      > make
+
+   Run with:
+
+   .. code-block:: bash
+
+      > ./charmrun +p8 ./src/tools/kripke +vp8 --zones 64,64,64 --procs 2,2,2 --nest ZDG
+
+MCB v1.0.3 (2013)
+^^^^^^^^^^^^^^^^^
+
+-  LLNL ASC proxy app for Monte Carlo particle transport codes:
+   https://codesign.llnl.gov/mcb.php
+
+-  MPI+OpenMP reference version.
+
+-  Run with:
+
+   .. code-block:: bash
+
+      > OMP_NUM_THREADS=1 ./charmrun +p4 ./../src/MCBenchmark.exe --weakScaling
+       --distributedSource --nCores=1 --numParticles=20000 --multiSigma --nThreadCore=1 +vp16
+
+.. _not-yet-ampi-zed-reason-1:
+
+Not yet AMPI-zed (reason)
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+: UMT 2013 (global variables).
+
+Other Applications
+~~~~~~~~~~~~~~~~~~
+
+MILC 7.0
+^^^^^^^^
+
+-  MILC is a code to study quantum chromodynamics (QCD) physics.
+   http://www.nersc.gov/users/computational-systems/cori/nersc-8-procurement/trinity-nersc-8-rfp/nersc-8-trinity-benchmarks/milc/
+
+-  Moved ``MPI_Init_thread`` call to ``main()``, added ``__thread`` to
+   all global/static variable declarations. Runs on AMPI with
+   virtualization when using -tlsglobals.
+
+-  Build: edit ``ks_imp_ds/Makefile`` to use AMPI compiler wrappers, run
+   ``make su3_rmd`` in ``ks_imp_ds/``
+
+-  Run with: ``./su3_rmd +vp8 ../benchmark_n8/single_node/n8_single.in``
+
+SNAP v1.01 (C version)
+^^^^^^^^^^^^^^^^^^^^^^
+
+-  LANL proxy app for PARTISN, an Sn deterministic particle transport
+   application: https://github.com/losalamos/SNAP
+
+-  SNAP is an update to Sweep3D. It simulates the same thing as Kripke,
+   but with a different decomposition and slight algorithmic
+   differences. It uses a 1- or 2-dimensional decomposition and the KBA
+   algorithm to perform parallel sweeps over the 3-dimensional problem
+   space. It contains all of the memory, computation, and network
+   performance characteristics of a real particle transport code.
+
+-  Original SNAP code is Fortran90-MPI-OpenMP, but this is a
+   C-MPI-OpenMP version of it provided along with the original version.
+   The Fortran90 version will require global variable privatization,
+   while the C version works out of the box on all platforms.
+
+-  Edit the Makefile for AMPI compiler paths and run with:
+   ``./charmrun +p4 ./snap +vp4 --fi center_src/fin01 --fo center_src/fout01``
+
+Sweep3D
+^^^^^^^
+
+-  Sweep3D is a *particle transport* program that analyzes the flux of
+   particles along a space. It solves a three-dimensional particle
+   transport problem.
+
+-  This mini-app has been deprecated, and replaced at LANL by SNAP
+   (above).
+
+-  Build/Run Instructions:
+
+   -  Modify the ``makefile`` and change variable CHARMC to point to
+      your Charm++ compiler command, execute ``make mpi`` to build the
+      program.
+
+   -  Modify file ``input`` to set the different parameters. Refer to
+      file ``README`` on how to change those parameters. Run with:
+      ``./charmrun ./sweep3d.mpi +p8 +vp16``
+
+PENNANT v0.8
+^^^^^^^^^^^^
+
+-  Unstructured mesh Rad-Hydro mini-app for a full application at LANL
+   called FLAG. https://github.com/losalamos/PENNANT
+
+-  Written in C++, only global/static variables that need to be
+   privatized are mype and numpe. Done manually.
+
+-  Legion, Regent, MPI, MPI+OpenMP, MPI+CUDA versions of PENNANT exist
+   for comparison.
+
+-  For PENNANT-v0.8, point CC in Makefile to AMPICC and just ’make’. Run
+   with the provided input files, such as:
+   ``./charmrun +p2 ./build/pennant +vp8 test/noh/noh.pnt``
+
+Benchmarks
+~~~~~~~~~~
+
+Jacobi-2D (Fortran)
+^^^^^^^^^^^^^^^^^^^
+
+-  Jacobi-2D with 1D decomposition. Problem size and number of
+   iterations are defined in the source code. Manually privatized.
+
+Jacobi-3D (C)
+^^^^^^^^^^^^^
+
+-  Jacobi-3D with 3D decomposition. Manually privatized. Includes
+   multiple versions: Isomalloc, PUP, FT, LB, Isend/Irecv, Iput/Iget.
+
+NAS Parallel Benchmarks (NPB 3.3)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+-  A collection of kernels used in different scientific applications.
+   They are mainly implementations of various linear algebra methods.
+   http://www.nas.nasa.gov/Resources/Software/npb.html
+
+-  Build/Run Instructions:
+
+   -  Modify file ``config/make.def`` to make variable ``CHAMRDIR``
+      point to the right Charm++ directory.
+
+   -  Use ``make <benchmark> NPROCS=<P> CLASS=<C>`` to build a
+      particular benchmark. The values for ``<benchmark>`` are (bt, cg,
+      dt, ep, ft, is, lu, mg, sp), ``<P>`` is the number of ranks and
+      ``<C>`` is the class or the problem size (to be chosen from
+      A,B,C,D or E). Some benchmarks may have restrictions on values of
+      ``<P>`` and ``<C>``. For instance, to make CG benchmark with 256
+      ranks and class C, we will use the following command:
+      ``make cg NPROCS=256``
+
+   -  The resulting executable file will be generated in the respective
+      directory for the benchmark. In the previous example, a file
+      *cg.256.C* will appear in the *CG* and ``bin/`` directories. To
+      run the particular benchmark, you must follow the standard
+      procedure of running AMPI programs:
+      ``./charmrun ./cg.C.256 +p64 +vp256 ++nodelist nodelist +isomalloc_sync``
+
+NAS PB Multi-Zone Version (NPB-MZ 3.3)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+-  A multi-zone version of BT, SP and LU NPB benchmarks. The multi-zone
+   intentionally divides the space unevenly among ranks and causes load
+   imbalance. The original goal of multi-zone versions was to offer an
+   test case for hybrid MPI+OpenMP programming, where the load imbalance
+   can be dealt with by increasing the number of threads in those ranks
+   with more computation.
+   http://www.nas.nasa.gov/Resources/Software/npb.html
+
+-  The BT-MZ program shows the heaviest load imbalance.
+
+-  Build/Run Instructions:
+
+   -  Modify file ``config/make.def`` to make variable ``CHAMRDIR``
+      point to the right Charm++ build.
+
+   -  Use the format ``make <benchmark> NPROCS=<P> CLASS=<C>`` to build
+      a particular benchmark. The values for ``<benchmark>`` are (bt-mz,
+      lu-mz, sp-mz), ``<P>`` is the number of ranks and ``<C>`` is the
+      class or the problem size (to be chosen from A,B,C,D or E). Some
+      benchmarks may have restrictions on values of ``<P>`` and ``<C>``.
+      For instance, to make the BT-MZ benchmark with 256 ranks and class
+      C, you can use the following command:
+      ``make bt-mz NPROCS=256 CLASS=C``
+
+   -  The resulting executable file will be generated in the *bin/*
+      directory. In the previous example, a file *bt-mz.256.C* will be
+      created in the ``bin`` directory. To run the particular benchmark,
+      you must follow the standard procedure of running AMPI programs:
+      ``./charmrun ./bt-mz.C.256 +p64 +vp256 ++nodelist nodelist +isomalloc_sync``
+
+HPCG v3.0
+^^^^^^^^^
+
+-  High Performance Conjugate Gradient benchmark, version 3.0. Companion
+   metric to Linpack, with many vendor-optimized implementations
+   available: http://hpcg-benchmark.org/
+
+-  No AMPI-ization needed. To build, modify ``setup/Make.AMPI`` for
+   compiler paths, do
+   ``mkdir build && cd build && configure ../setup/Make.AMPI && make``.
+   To run, do ``./charmrun +p16 ./bin/xhpcg +vp64``
+
+Intel Parallel Research Kernels (PRK) v2.16
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+-  A variety of kernels (Branch, DGEMM, Nstream, Random, Reduce, Sparse,
+   Stencil, Synch_global, Synch_p2p, and Transpose) implemented for a
+   variety of runtimes (SERIAL, OpenMP, MPI-1, MPI-RMA, MPI-SHM,
+   MPI+OpenMP, SHMEM, FG_MPI, UPC, Grappa, Charm++, and AMPI).
+   https://github.com/ParRes/Kernels
+
+-  For AMPI tests, set ``CHARMTOP`` and run: ``make allampi``. There are
+   run scripts included.
+
+OSU Microbenchmarks
+^^^^^^^^^^^^^^^^^^^
+
+MPI collectives performance testing suite.
+https://charm.cs.illinois.edu/gerrit/#/admin/projects/benchmarks/osu-collectives-benchmarking
+
+-  Build with: ``./configure CC=~/charm/bin/ampicc && make``
+
+Third Party Open Source Libraries
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+HYPRE-2.11.1
+^^^^^^^^^^^^
+
+-  High Performance Preconditioners and solvers library from LLNL.
+   https://computation.llnl.gov/project/linear_solvers/software.php
+
+-  Hypre-2.11.1 builds on top of AMPI using the configure command:
+
+   ::
+
+      > ./configure --with-MPI
+            CC=~/charm/bin/ampicc
+            CXX=~/charm/bin/ampicxx
+            F77=~/charm/bin/ampif77
+            --with-MPI-include=~/charm/include
+            --with-MPI-lib-dirs=~/charm/lib
+            --with-MPI-libs=mpi --without-timing --without-print-errors
+      > make -j8
+
+-  All HYPRE tests and examples pass tests with virtualization,
+   migration, etc. except for those that use Hypre’s timing interface,
+   which uses a global variable internally. So just remove those calls
+   and do not define ``HYPRE_TIMING`` when compiling a code that uses
+   Hypre. In the examples directory, you’ll have to set the compilers to
+   your AMPI compilers explicitly too. In the test directory, you’ll
+   have to edit the Makefile to 1) Remove ``-DHYPRE_TIMING`` from both
+   ``CDEFS`` and ``CXXDEFS``, 2) Remove both ``${MPILIBS}`` and
+   ``${MPIFLAGS}`` from ``MPILIBFLAGS``, and 3) Remove ``${LIBS}`` from
+   ``LIBFLAGS``. Then run ``make``.
+
+-  To run the ``new_ij`` test, run:
+   ``./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``
+
+MFEM-3.2
+^^^^^^^^
+
+-  MFEM is a scalable library for Finite Element Methods developed at
+   LLNL. http://mfem.org/
+
+-  MFEM-3.2 builds on top of AMPI (and METIS-4.0.3 and HYPRE-2.11.1).
+   Download MFEM,
+   `HYPRE <https://computation.llnl.gov/project/linear_solvers/software.php>`__,
+   and `METIS <http://glaros.dtc.umn.edu/gkhome/fsroot/sw/metis/OLD>`__.
+   Untar all 3 in the same top-level directory.
+
+-  Build HYPRE-2.11.1 as described above.
+
+-  Build METIS-4.0.3 by doing ``cd metis-4.0.3/ && make``
+
+-  Build MFEM-3.2 serial first by doing ``make serial``
+
+-  Build MFEM-3.2 parallel by doing:
+
+   -  First, comment out ``#define HYPRE_TIMING`` in
+      ``mfem/linalg/hypre.hpp``. Also, you must add a
+      ``#define hypre_clearTiming()`` at the top of
+      ``linalg/hypre.cpp``, because Hypre-2.11.1 has a bug where it
+      doesn’t provide a definition of this function if you don’t define
+      ``HYPRE_TIMING``.
+
+   -  ``make parallel MFEM_USE_MPI=YES MPICXX=~/charm/bin/ampicxx HYPRE_DIR=~/hypre-2.11.1/src/hypre METIS_DIR=~/metis-4.0.3``
+
+-  To run an example, do
+   ``./charmrun +p4 ./ex15p -m ../data/amr-quad.mesh +vp16``. You may
+   want to add the runtime options ``-no-vis`` and ``-no-visit`` to
+   speed things up.
+
+-  All example programs and miniapps pass with virtualization, and
+   migration if added.
+
+XBraid-1.1
+^^^^^^^^^^
+
+-  XBraid is a scalable library for parallel time integration using
+   MultiGrid, developed at LLNL.
+   https://computation.llnl.gov/project/parallel-time-integration/software.php
+
+-  XBraid-1.1 builds on top of AMPI (and its examples/drivers build on
+   top of MFEM-3.2, HYPRE-2.11.1, and METIS-4.0.3 or METIS-5.1.0).
+
+-  To build XBraid, modify the variables CC, MPICC, and MPICXX in
+   makefile.inc to point to your AMPI compilers, then do ``make``.
+
+-  To build XBraid’s examples/ and drivers/ modify the paths to MFEM and
+   HYPRE in their Makefiles and ``make``.
+
+-  To run an example, do
+   ``./charmrun +p2 ./ex-02 -pgrid 1 1 8 -ml 15 -nt 128 -nx 33 33 -mi 100 +vp8 ++local``.
+
+-  To run a driver, do
+   ``./charmrun +p4 ./drive-03 -pgrid 2 2 2 2 -nl 32 32 32 -nt 16 -ml 15 +vp16 ++local``
+
+Other AMPI codes
+~~~~~~~~~~~~~~~~
+
+-  FLASH
+
+-  BRAMS (Weather prediction model)
+
+-  CGPOP
+
+-  Fractography3D (Crack Propagation)
+
+-  JetAlloc
+
+-  PlasComCM (XPACC)
+
+-  PlasCom2 (XPACC)
+
+-  Harm3D
+
+Installing AMPI
+===============
+
+AMPI is included in the source distribution of Charm++. To get the
+latest sources from PPL, visit: http://charm.cs.illinois.edu/software
+
+and follow the download links. Then build Charm++ and AMPI from source.
+
+The build script for Charm++ is called ``build``. The syntax for this
+script is:
+
+::
+
+   > build <target> <version> <opts>
+
+For building AMPI (which also includes building Charm++ and other
+libraries needed by AMPI), specify ``<target>`` to be ``AMPI``. And
+``<opts>`` are command line options passed to the ``charmc`` compile
+script. Common compile time options such as
+``-g, -O, -Ipath, -Lpath, -llib`` are accepted.
+
+To build a debugging version of AMPI, use the option: ``-g``. To build a
+production version of AMPI, use the option: ``-with-production``.
+
+``<version>`` depends on the machine, operating system, and the
+underlying communication library one wants to use for running AMPI
+programs. See the charm/README file for details on picking the proper
+version. Here is an example of how to build a debug version of AMPI in a
+linux and ethernet environment:
+
+::
+
+   > build AMPI netlrts-linux-x86_64 -g
+
+And the following is an example of how to build a production version of
+AMPI on a Cray XC system, with MPI-level error checking in AMPI turned
+off:
+
+::
+
+   > build AMPI gni-crayxc --with-production --disable-ampi-error-checking
+
+AMPI can also be built with support for shared memory on any
+communication layer by adding "smp" as an option after the build target.
+For example, on an Infiniband Linux cluster:
+
+::
+
+   > build AMPI verbs-linux-x86_64 smp --with-production
+
+AMPI ranks are implemented as user-level threads with a stack size
+default of 1MB. If the default is not correct for your program, you can
+specify a different default stack size (in bytes) at build time. The
+following build command illustrates this for an Intel Omni-Path system:
+
+::
+
+   > build AMPI ofi-linux-x86_64 --with-production -DTCHARM_STACKSIZE_DEFAULT=16777216
+
+The same can be done for AMPI’s RDMA messaging threshold using
+``AMPI_RDMA_THRESHOLD_DEFAULT`` and, for messages sent within the same
+address space (ranks on the same worker thread or ranks on different
+worker threads in the same process in SMP builds), using
+``AMPI_SMP_RDMA_THRESHOLD_DEFAULT``. Contiguous messages with sizes
+larger than the threshold are sent via RDMA on communication layers that
+support this capability. You can also set the environment variables
+``AMPI_RDMA_THRESHOLD`` and ``AMPI_SMP_RDMA_THRESHOLD`` before running a
+job to override the default specified at build time.
+
+Building and Running AMPI Programs
+==================================
+
+Building AMPI Programs
+----------------------
+
+AMPI provides a compiler called *ampicc* in your charm/bin/ directory.
+You can use this compiler to build your AMPI program the same way as
+other compilers like cc. All the command line flags that you would use
+for other compilers can be used with the AMPI compilers the same way.
+For example:
+
+::
+
+   > ampicc -c pgm.c -O3
+   > ampif90 -c pgm.f90 -O0 -g
+   > ampicc -o pgm pgm.o -lm -O3
+
+To use Isomalloc for transparently migrating user heap data, link with
+*-memory isomalloc*. To use a Charm++ load balancer, link a strategy or
+a suite of strategies in with *-module <LB>*. For example:
+
+::
+
+   > ampicc pgm.c -o pgm -O3 -memory isomalloc -module CommonLBs
+
+Running AMPI programs
+---------------------
+
+AMPI offers two options to execute an AMPI program, ``charmrun`` and
+``ampirun``.
+
+Running with charmrun
+~~~~~~~~~~~~~~~~~~~~~
+
+The Charm++ distribution contains a script called ``charmrun`` that
+makes the job of running AMPI programs portable and easier across all
+parallel machines supported by Charm++. ``charmrun`` is copied to a
+directory where an AMPI program is built using ``ampicc``. It takes a
+command line parameter specifying number of processors, and the name of
+the program followed by AMPI options (such as number of ranks to create,
+and the stack size of every user-level thread) and the program
+arguments. A typical invocation of an AMPI program ``pgm`` with
+``charmrun`` is:
+
+::
+
+   > ./charmrun +p16 ./pgm +vp64
+
+Here, the AMPI program ``pgm`` is run on 16 physical processors with 64
+total virtual ranks (which will be mapped 4 per processor initially).
+
+To run with load balancing, specify a load balancing strategy. If
+Address Space Layout Randomization is enabled on your target system, you
+may need to add the flag ``+isomalloc_sync`` when running with
+migration. You can also specify the size of user-level thread’s stack
+using the ``+tcharm_stacksize`` option, which can be used to decrease
+the size of the stack that must be migrated, as in the following
+example:
+
+::
+
+   > ./charmrun +p16 ./pgm +vp128 +tcharm_stacksize 32K +balancer RefineLB
+
+Running with ampirun
+~~~~~~~~~~~~~~~~~~~~
+
+For compliance with the MPI standard and simpler execution, AMPI ships
+with the ``ampirun`` script that is similar to ``mpirun`` provided by
+other MPI runtimes. As with ``charmrun``, ``ampirun`` is copied
+automatically to the program directory when compiling an application
+with ``ampicc``.
+
+The basic usage of ampirun is as follows:
+
+::
+
+   > ./ampirun -np 16 --host h1,h2,h3,h4 ./pgm
+
+This command will create 16 (non-virtualized) ranks and distribute them
+on the hosts h1-h4.
+
+When using the ``-vr`` option, AMPI will create the number of ranks
+specified by the ``-np`` parameter as virtual ranks, and will create
+only one process per host:
+
+::
+
+   > ./ampirun -np 16 --host h1,h2,h3,h4 -vr ./pgm
+
+Other options (such as the load balancing strategy), can be specified in
+the same way as for charmrun:
+
+::
+
+   > ./ampirun -np 16 ./pgm +balancer RefineLB
+
+Other options
+~~~~~~~~~~~~~
+
+Note that for AMPI programs compiled with gfortran, users may need to
+set the following environment variable to see program output to stdout:
+
+::
+
+   > export GFORTRAN_UNBUFFERED_ALL=1
+
+.. [1]
+   Currently, AMPI supports the MPI-2.2 standard, and the MPI-3.1
+   standard is under active development, though we already support
+   non-blocking and neighborhood collectives among other MPI-3.1
+   features.
+
+.. [2]
+   http://www-unix.mcs.anl.gov/romio/
+
+.. [3]
+   http://www.eclipse.org/photran
+
+.. [4]
+   http://rosecompiler.org/
+
+.. [5]
+   Currently, we assume that the interface code, which does mapping and
+   interpolation among the boundary values of Fluids and Solids domain,
+   is integrated with one of Fluids and Solids.
diff --git a/doc/armci/manual.rst b/doc/armci/manual.rst
new file mode 100644 (file)
index 0000000..0acdc8d
--- /dev/null
@@ -0,0 +1,471 @@
+=============================
+ARMCI Interface under Charm++
+=============================
+
+.. contents::
+   :depth: 3
+
+Introduction
+============
+
+This manual describes the basic features and API of the Aggregate Remote
+Memory Copy Interface (ARMCI) library implemented under Charm++. It is
+meant for developers using ARMCI who desire the performance features of
+the Charm++ run-time system (e.g. dynamic load balancing, fault
+tolerance and scalability) applied transparently to their libraries
+written using the ARMCI API.
+
+ARMCI is a library that supports remote memory copy functionality. It
+focuses on non-contiguous data transfers and is meant to be used by
+other libraries as opposed to application development. Libraries that
+the original ARMCI developers have targeted include Global Arrays,
+P++/Overture and the Adlib PCRC run-time system.
+
+ARMCI remote copy operations are one-sided and complete, regardless of
+the actions taken by the remote process. For performance reasons,
+polling can be helpful but should not be necessary to ensure progress.
+The operations are ordered when referencing the same remote process.
+Operations issued to different processes can complete in an arbitrary
+order. Both blocking and non-blocking APIs are supported.
+
+ARMCI supports three classes of operations: data transfer using *put*,
+*get* and *accumulate* operations; synchronization with local and global
+*fence* operations and atomic read-modify-write; and utility functions
+for memory management and error handling. *Accumulate* and atomic
+read-modify-write operations are currently not implemented for the
+charmpp port.
+
+A *get* operation transfers data from the remote process memory (source)
+to the calling processing local memory (destination). A *put* operation
+transfers data from the local memory of the calling process (source) to
+the memory of the remote process (destination).
+
+This manual will include several useful Charm++-specific extensions to
+the ARMCI API. It will also list the functions that have not yet been
+implemented but exists in the original ARMCI implementation. Readers of
+this manual are advised to refer to the original ARMCI documentation
+(See Section :numref:`sec::related doc`) for more complete information
+and motivation for the development of this library.
+
+.. _sec::charm build:
+
+Building ARMCI Support under The Charm++ Runtime System
+-------------------------------------------------------
+
+Build charm target ARMCI (instead of charm or AMPI):
+
+::
+
+   > cd charm
+   > ./build ARMCI netlrts-linux -O3
+
+.. _sec::simple program:
+
+Writing a Simple ARMCI Program
+------------------------------
+
+The following simple example has two processes place their own string
+into the global array and then acquire the appropriate string from the
+other’s global address space in order to print “hello world”.
+
+The main function has to be compliant to ANSI C:
+
+::
+
+   #include <stdio.h>
+   #include <stdlib.h>
+   #include <string.h>
+
+   #include <armci.h>
+
+   #define MAX_PROCESSORS 2
+
+   int main(int argc, char * argv[]) {
+     void *baseAddress[MAX_PROCESSORS];
+     char *myBuffer;
+     int thisImage;
+
+     // initialize
+     ARMCI_Init();
+     ARMCI_Myid(&thisImage);
+
+     // allocate data (collective operation)
+     ARMCI_Malloc(baseAddress, strlen("hello")+1);
+
+     if (thisImage == 0) {
+       sprintf((char *)baseAddress[0], "%s", "hello");
+     } else if (thisImage == 1) {
+       sprintf((char *)baseAddress[1], "%s", "world");
+     }
+
+     // allocate space for local buffer
+     myBuffer = (char *)AMRCI_Malloc_local(strlen("hello")+1);
+
+     ARMCI_Barrier();
+
+     if (thisImage == 0) {
+       ARMCI_Get(baseAddress[1], myBuffer, strlen("hello")+1, 1);
+       printf("[%d] %s %s\n",thisImage, baseAddress[0], myBuffer);
+     } else if (thisImage == 1) {
+       ARMCI_Get(baseAddress[0], myBuffer, strlen("hello")+1, 0);
+       printf("[%d] %s %s\n",thisImage, myBuffer, baseAddress[1]);
+     }
+
+     // finalize
+     ARMCI_Finalize();
+     return 0;
+   }
+
+.. _sec::armci build:
+
+Building an ARMCI Binary and Execution
+--------------------------------------
+
+Compiling the code with:
+
+.. code-block:: bash
+
+   > charm/bin/charmc -c hello.c /$(OPTS)
+
+Linking the program with:
+
+.. code-block:: bash
+
+   > charm/bin/charmc hello.o -o hello -swapglobals -memory isomalloc -language armci $(OPTS)
+
+Run the program:
+
+.. code-block:: bash
+
+   > ./charmrun ./hello +p2 +vp8
+
+.. _sec::data structures:
+
+ARMCI Data Structures
+=====================
+
+ARMCI provides two formats to describe non-contiguous layouts of data in
+memory.
+
+The *generalized I/O vector* is the most general format intended for
+multiple sets of equally sized data segments to be moved between
+arbitrary local and remote memory locations. It uses two arrays of
+pointers: one for source and one for destination addresses. The length
+of each array is equal to the number of segments.
+
+::
+
+   typedef struct {
+     void *src_ptr_ar;
+     void *dst_ptr_ar;
+     int bytes;
+     int ptr_ar_len;
+   } armci_giov_t;
+
+Currently, there is no support for *generalized I/O vector* operations
+in the charmpp implementation.
+
+The *strided* format is an optimization of the generalized I/O vector
+format. It is intended to minimize storage required to describe sections
+of dense multi-dimensional arrays. Instead of including addresses for
+all the segments, it specifies only an address of the first segment in
+the set for source and destination. The addresses of the other segments
+can be computed using the stride information.
+
+
+Application Programmer’s Interface
+==================================
+
+The following is a list of functions supported on the Charm++ port of
+ARMCI. The integer value returned by most ARMCI operations represents
+the error code. The zero value is successful, other values represent
+failure (See Section :numref:`sec::error codes` for details).
+
+Startup, Cleanup and Status Functions
+-------------------------------------
+
+::
+
+   int ARMCI_Init(void);
+
+Initializes the ARMCI library. This function must be called before any
+ARMCI functions may be used.
+
+::
+
+   int ARMCI_Finalize(void);
+
+Shuts down the ARMCI library. No ARMCI functions may be called after
+this call is made. It must be used before terminating the program
+normally.
+
+::
+
+   void ARMCI_Cleanup(void);
+
+Releases system resources that the ARMCI library might be holding. This
+is intended to be used before terminating the program in case of error.
+
+::
+
+   void ARMCI_Error(char *msg, int code);
+
+Combines the functionality of ARMCI_Cleanup and Charm++’s CkAbort call.
+Prints to *stdout* and *stderr* ``msg`` followed by an integer ``code``.
+
+::
+
+   int ARMCI_Procs(int *procs);
+
+The number of processes is stored in the address ``procs``.
+
+::
+
+   int ARMCI_Myid(int *myid);
+
+The id of the process making this call is stored in the address
+``myid``.
+
+ARMCI Memory Allocation
+-----------------------
+
+::
+
+   int ARMCI_Malloc(void* ptr_arr[], int bytes);
+
+Collective operation to allocate memory that can be used in the context
+of ARMCI copy operations. Memory of size ``bytes`` is allocated on each
+process. The pointer address of each process’ allocated memory is stored
+at ``ptr_arr[]`` indexed by the process’ id (see ``ARMCI_Myid``). Each
+process gets a copy of ``ptr_arr``.
+
+::
+
+   int ARMCI_Free(void *ptr);
+
+Collective operation to free memory which was allocated by
+``ARMCI_Malloc``.
+
+::
+
+   void *ARMCI_Malloc_local(int bytes);
+
+Local memory of size ``bytes`` allocated. Essentially a wrapper for
+``malloc``.
+
+::
+
+   int ARMCI_Free_local(void *ptr);
+
+Local memory address pointed to by ``ptr`` is freed. Essentially a
+wrapper for ``free``.
+
+Put and Get Communication
+-------------------------
+
+::
+
+   int ARMCI_Put(void *src, void *dst, int bytes, int proc);
+
+Transfer contiguous data of size ``bytes`` from the local process memory
+(source) pointed to by ``src`` into the remote memory of process id
+``proc`` pointed to by ``dst`` (remote memory pointer at destination).
+
+::
+
+   int ARMCI_NbPut(void *src, void* dst, int bytes, int proc,
+                   armci_hdl_t *handle);
+
+The non-blocking version of ``ARMCI_Put``. Passing a ``NULL`` value to
+``handle`` makes this function perform an implicit handle non-blocking
+transfer.
+
+::
+
+   int ARMCI_PutS(void *src_ptr, int src_stride_ar[],
+                  void *dst_ptr, int dst_stride_ar[],
+                  int count[], int stride_levels, int proc);
+
+Transfer strided data from the local process memory (source) into remote
+memory of process id ``proc``. ``src_ptr`` points to the first memory
+segment in local process memory. ``dst_ptr`` is a remote memory address
+that points to the first memory segment in the memory of process
+``proc``. ``stride_levels`` represents the number of additional
+dimensions of striding beyond 1. ``src_stride_ar`` is an array of size
+``stride_levels`` whose values indicate the number of bytes to skip on
+the local process memory layout. ``dst_stride_ar`` is an array of size
+``stride_levels`` whose values indicate the number of bytes to skip on
+process ``proc``\ ’s memory layout. ``count`` is an array of size
+``stride_levels + 1`` whose values indicate the number of bytes to copy.
+
+As an example, assume two 2-dimensional C arrays residing on different
+processes.
+
+::
+
+             double A[10][20]; /* local process */
+             double B[20][30]; /* remote process */
+
+To put a block of data of 3x6 doubles starting at location (1,2) in
+``A`` into location (3,4) in ``B``, the arguments to ``ARMCI_PutS`` will
+be as follows (assuming C/C++ memory layout):
+
+::
+
+             src_ptr = &A[0][0] + (1 * 20 + 2); /* location (1,2) */
+             src_stride_ar[0] = 20 * sizeof(double);
+             dst_ptr = &B[0][0] + (3 * 30 + 4); /* location (3,4) */
+             dst_stride_ar[0] = 30 * sizeof(double);
+             count[0] = 6 * sizeof(double); /* contiguous data */
+             count[1] = 3; /* number of rows of contiguous data */
+             stride_levels = 1;
+             proc = /*<B's id> */;
+
+::
+
+   int ARMCI_NbPutS(void *src_ptr, int src_stride_ar[],
+                    void *dst_ptr, int dst_stride_ar[],
+                    int count[], int stride_levels, int proc
+                    armci_hdl_t *handle);
+
+The non-blocking version of ``ARMCI_PutS``. Passing a ``NULL`` value to
+``handle`` makes this function perform an implicit handle non-blocking
+transfer.
+
+::
+
+   int ARMCI_Get(void *src, void *dst, int bytes, int proc);
+
+Transfer contiguous data of size ``bytes`` from the remote process
+memory at process ``proc`` (source) pointed to by ``src`` into the local
+memory of the calling process pointed to by ``dst``.
+
+::
+
+   int ARMCI_NbGet(void *src, void *dst, int bytes, int proc,
+                   armci_hdl_t *handle);
+
+The non-blocking version of ``ARMCI_Get``. Passing a ``NULL`` value to
+``handle`` makes this function perform an implicit handle non-blocking
+transfer.
+
+::
+
+   int ARMCI_GetS(void *src_ptr, int src_stride_ar[],
+                  void* dst_ptr, int dst_stride_ar[],
+                  int count[], int stride_levels, int proc);
+
+Transfer strided data segments from remote process memory on process
+``proc`` to the local memory of the calling process. The semantics of
+the parameters to this function are the same as that for ``ARMCI_PutS``.
+
+::
+
+   int ARMCI_NbGetS(void *src_ptr, int src_stride_ar[],
+                    void* dst_ptr, int dst_stride_ar[],
+                    int count[], int stride_levels, int proc,
+                    armci_hdl_t *handle);
+
+The non-blocking version of ``ARMCI_GetS``. Passing a ``NULL`` value to
+``handle`` makes this function perform an implicit handle non-blocking
+transfer.
+
+Explicit Synchronization
+------------------------
+
+::
+
+   int ARMCI_Wait(armci_hdl_t *handle);
+   int ARMCI_WaitProc(int proc);
+   int ARMCI_WaitAll();
+   int ARMCI_Test(armci_hdl_t *handle);
+   int ARMCI_Barrier();
+
+::
+
+   int ARMCI_Fence(int proc);
+
+Blocks the calling process until all *put* or *accumulate* operations
+the process issued to the remote process ``proc`` are completed at the
+destination.
+
+::
+
+   int ARMCI_AllFence(void);
+
+Blocks the calling process until all outstanding *put* or *accumulate*
+operations it issued are completed on all remote destinations.
+
+.. _sec::extensions:
+
+Extensions to the Standard API
+------------------------------
+
+::
+
+   void ARMCI_Migrate(void);
+   void ARMCI_Async_Migrate(void);
+   void ARMCI_Checkpoint(char* dirname);
+   void ARMCI_MemCheckpoint(void);
+
+   int armci_notify(int proc);
+   int armci_notify_wait(int proc, int *pval);
+
+List of Unimplemented Functions
+===============================
+
+The following functions are supported on the standard ARMCI
+implementation but not yet supported in the Charm++ port.
+
+::
+
+   int ARMCI_GetV(...);
+   int ARMCI_NbGetV(...);
+   int ARMCI_PutV(...);
+   int ARMCI_NbPutV(...);
+   int ARMCI_AccV(...);
+   int ARMCI_NbAccV(...);
+
+   int ARMCI_Acc(...);
+   int ARMCI_NbAcc(...);
+   int ARMCI_AccS(...);
+   int ARMCI_NbAccS(...);
+
+   int ARMCI_PutValueLong(long src, void* dst, int proc);
+   int ARMCI_PutValueInt(int src, void* dst, int proc);
+   int ARMCI_PutValueFloat(float src, void* dst, int proc);
+   int ARMCI_PutValueDouble(double src, void* dst, int proc);
+   int ARMCI_NbPutValueLong(long src, void* dst, int proc, armci_hdl_t* handle);
+   int ARMCI_NbPutValueInt(int src, void* dst, int proc, armci_hdl_t* handle);
+   int ARMCI_NbPutValueFloat(float src, void* dst, int proc, armci_hdl_t* handle);
+   int ARMCI_NbPutValueDouble(double src, void* dst, int proc, armci_hdl_t* handle);
+   long ARMCI_GetValueLong(void *src, int proc);
+   int ARMCI_GetValueInt(void *src, int proc);
+   float ARMCI_GetValueFloat(void *src, int proc);
+   double ARMCI_GetValueDouble(void *src, int proc);
+
+   void ARMCI_SET_AGGREGATE_HANDLE (armci_hdl_t* handle);
+   void ARMCI_UNSET_AGGREGATE_HANDLE (armci_hdl_t* handle);
+
+   int ARMCI_Rmw(int op, int *ploc, int *prem, int extra, int proc);
+   int ARMCI_Create_mutexes(int num);
+   int ARMCI_Destroy_mutexes(void);
+   void ARMCI_Lock(int mutex, int proc);
+   void ARMCI_Unlock(int mutex, int proc);
+
+.. _sec::error codes:
+
+Error Codes
+===========
+
+As of this writing, attempts to locate the documented error codes have
+failed because the release notes have not been found. Attempts are being
+made to derive these from the ARMCI source directly. Currently Charm++
+implementation does not implement any error codes.
+
+.. _sec::related doc:
+
+Related Manuals and Documents
+=============================
+
+ARMCI website: http://www.emsl.pnl.gov/docs/parsoft/armci/index.html
diff --git a/doc/bignetsim/manual.rst b/doc/bignetsim/manual.rst
new file mode 100644 (file)
index 0000000..5904a81
--- /dev/null
@@ -0,0 +1,397 @@
+==============================================================
+BigSimulator (BigNetSim) for Extremely Large Parallel Machines
+==============================================================
+
+.. contents::
+   :depth: 3
+
+.. _bignetsim:
+
+BigSim Network Simulator
+========================
+
+The BigSim Network Simulator is also known as Bigsimulator and lives in
+the SVN repository https://charm.cs.uiuc.edu/svn/repos/BigNetSim. The
+Network simulator is actually more of an Inter-connection network
+simulator and hence more important in the context of large parallel
+machines with interconnects. The BigSim simulator along with the network
+simulator is together also known as BigNetSim.
+
+Both the simulators run on top of the POSE framework, which is a
+Parallel Discrete Event Simulation framework built on top of Charm++.
+
+What does this software do?
+---------------------------
+
+BigNetSim is an effort to simulate large current and future computer
+systems to study the behavior of applications developed for those
+systems. BigNetSim could be used to study
+
+-  new types of interconnection topologies and routing algorithms along
+   with different types of switching architecture.
+
+-  application performance on different machines. This uses the API
+   provided in Section :numref:`bgapi` to run the application on
+   some number of processors on some machine and generate (dump) all
+   events (entry method executions or message send/recv). BigNetSim is
+   used to model the machine that needs to be studied for this
+   application and these logs are then fed into this simulation, and it
+   predicts the performance of this application.
+
+So, the two important uses are studying *interconnection networks* and
+*performance prediction for applications*.
+
+Compiling BigSimulator
+----------------------
+
+To compile the simulator which is called BigSimulator (or BigNetSim), we
+need the regular Charm++ build (netlrts-linux-x86_64 in our example). It
+needs to be complemented with a few more libraries from BigSim and with
+the Pose discrete-event simulator. These pieces can be built,
+respectively, with:
+
+::
+
+   ./build bgampi netlrts-linux-x86_64 -O2
+   ./build pose netlrts-linux-x86_64 -O2
+
+Access to the discrete-event simulation is realized via a Charm++
+package originally named BigNetSim (now called BigSimulator). Assuming
+that the ’subversion’ (svn) package is available, this package can be
+obtained from the Web with a subversion checkout such as:
+
+.. code-block:: bash
+
+      svn co https://charm.cs.uiuc.edu/svn/repos/BigNetSim/
+
+In the subdir ’trunk/’ created by the checkout, the file Makefile.common
+must be edited so that ’CHARMBASE’ points to the regular Charm++
+installation. Having that done, one chooses a topology in that subdir
+(e.g. BlueGene for a torus topology) by doing a "cd" into the
+corresponding directory (e.g. ’cd BlueGene’). Inside that directory, one
+should simply "make". This will produce the binary
+"../tmp/bigsimulator". That file, together with file
+"BlueGene/netconfig.vc", will be used during a simulation. It may be
+useful to set the variable SEQUENTIAL to 1 in Makefile.common to build a
+sequential (non-parallel) version of bigsimulator.
+
+Using BigSimulator
+------------------
+
+BigSimulator (BigNetSim) has 2 major modes.
+
+-  Trace based traffic simulation
+
+-  Artificial traffic generation based simulation. The mode of the
+   simulator is governed by the :math:`USE\_TRANSCEIVER` parameter in
+   the netconfig file. When set to 0, trace based simulation is used,
+   when set to 1, traffic generation is used.
+
+Trace based simulation. This is used to study target application
+performance, or detailed network performance when loaded by a specific
+application.
+
+There are two command line parameters for traced based simulation.
+
+.. code-block:: none
+
+     ./charmrun +p2 ./bigsimulator arg1 arg2
+
+.. code-block:: none
+
+     arg1 = 0 => Latency only mode
+            1 => Detailed contention model
+     arg2 = N => starts execution at the time marked by skip point N (0 is start)
+
+Simple Latency Model
+~~~~~~~~~~~~~~~~~~~~
+
+To use the simple latency model, follow the setup procedure above,
+noting that the files are located in the trunk/SimpleLatency directory.
+This will produce the "bigsimulator" file.
+
+The command line parameters used for this model are different. The
+format is as follows:
+
+.. code-block:: none
+
+     [charmrun +p#] bigsimulator -lat <latency> -bw <bandwidth>
+                  [-cpp <cost per packet> -psize <packet size>]
+                  [-winsize <window size>] [-skip] [-print_params]
+
+.. code-block:: none
+
+     Latency (lat)         - type double; in microseconds
+     Bandwidth (bw)        - type double; in GB/s
+     Cost per packet (cpp) - type double; in microseconds
+     Packet size (psize)   - type int; in bytes
+     Window size (winsize) - type int; in log entries
+
+The implemented equation is: :math:`lat + (N/bw) + cpp \times (N/psize)`
+
+Latency and bandwidth are required. If cost per packet is given, then
+packet size must be given, as well. Otherwise, cost per packet defaults
+to 0.0. Packet size, if given, must be a positive integer.
+
+The -winsize flag allows the user to specify the size of the window
+(number of log entries) used when reading in the bgTrace log files. This
+is useful if the log files are large. If -winsize is not specified, the
+value defaults to 0, which indicates that no windowing will be used
+(i.e., there will be one window for each time line that is equal to the
+size of the time line).
+
+As with the second parameter in the examples of part (a) of this
+section, the -skip flag indicates that the simulation should skip
+forward to the time stamp set during trace creation (see the BigSim
+tutorial talk from the 2008 Charm++ workshop). If -skip is not included,
+then no skipping will occur.
+
+The -print_params flag is provided for debugging convenience. When
+present, the simple latency model parameters will be displayed during
+simulation initialization.
+
+Artificial Traffic Models
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Artificial traffic generation based simulation is use to study the
+performance of interconnects under standard network load schemes.
+
+.. code-block:: none
+
+     ./bigsimulator arg1 arg2 arg3 arg4 arg5 arg6
+
+example
+
+.. code-block:: none
+
+     ./bigsimulator 1 2 3 100 2031 0.1
+
+.. code-block:: none
+
+     arg1 = 0 => Latency only mode
+            1 => Detailed contention model
+     arg2 = 1 => deterministic traffic
+            2 => poisson traffic
+     arg3 = 1 => KSHIFT
+            2 => RING
+            3 => BITTRANSPOSE
+            4 => BITREVERSAL
+            5 => BITCOMPLEMENT
+            6 => UNIFORM_DISTRIBUTION
+     arg4 = number of packets
+     arg5 = message size
+     arg6 = load factor
+
+Which Interconnection networks are implemented?
+-----------------------------------------------
+
+A large number of topologies and routing strategies are implemented in
+the software. Here, we present a list of interconnection networks. For a
+complete list of routing strategies, input/output VC selectors, refer to
+the corresponding directories in the software.
+
+-  HyperCube
+
+-  FatTree
+
+-  DenseGraph
+
+-  Three dimensional Mesh
+
+-  K-ary-N-cube
+
+-  K-ary-N-fly
+
+-  K-ary-N-mesh
+
+-  K-ary-N-tree
+
+-  N-mesh
+
+-  Hybrid of Fattree and Dense Graph
+
+-  Hybrid of Fattree and HyperCube
+
+Build your own Interconnection network
+--------------------------------------
+
+To build a new interconnection network, one has to create a new
+directory for that interconnection network and then create the routing
+strategy, topology, input virtual channel selection and output virtual
+channel selection strategies for that network. If existing strategies
+could be used, then reuse them, but if new ones are required, one has to
+write these new strategies in the corresponding directories for routing,
+topology, etc.
+
+The InitNetwork function must be provided in InitNetwork.C for this new
+interconnection network. It builds up all the nodes and switches and
+NICs and channels that form the network. Look at one of the existing
+interconnection topologies for reference.
+
+BigNetSim Design and Internals
+------------------------------
+
+.. figure:: figures/detailedsim_newer.png
+   :width: 3.2in
+
+   BigNetSim conceptual model
+
+This section focuses on the interconnection network simulation. The
+entities that form an interconnection network are:
+
+-  *switch:* A switch decides the routing on a packet. Switches could be
+   input buffered or output buffered. The former are implemented as
+   individual posers per port of each switch while the latter are
+   implemented as a poser per switch. In an *Input Buffered (IB)*
+   switch, a packet in a switch is stored at the input port until its
+   next route is decided and leaves the switch if it finds available
+   space on the next switch in the route. While in an *Output Buffered
+   (OB)* switch, a packet in a switch decides beforehand on the next
+   route to take and is buffered at the output port until space is
+   available on the next switch along the route. Switches are modeled in
+   much detail. Ports, buffers and virtual channels at ports to avoid
+   head-of-the-line blocking are modeled. Hardware collectives are
+   implemented on the switch to enable broadcasts, multicasts and other
+   collective operations efficiently. These are configurable and can be
+   used if the system being simulated supports them. We also support
+   configurable strategies for arbitration, input virtual channel
+   selection and output virtual channel selection. The configurability
+   of the switch provides a flexible design, satisfying the requirements
+   of a large number of networks.
+
+-  *network card:* Network cards packetize and unpacketize messages. A
+   NIC is implemented as two posers. The sending and receiving entities
+   in a NIC are implemented as separate posers. A NIC is attached to
+   each node.
+
+-  *channel:* These are modeled as posers and connect a NIC to a switch
+   or a switch to another switch.
+
+-  *compute node:* Each compute node connects to a network interface
+   card. A compute node simulates execution of entry methods on it. It
+   is also attached to a message traffic generator, which is used when
+   only an interconnection network is being simulated. This traffic
+   generator can generate any message pattern on each of the compute
+   nodes. The traffic generator can send point-to-point messages,
+   reductions, multicasts, broadcasts and other collective traffic. It
+   supports k-shift, ring, bit-transpose, bit-reversal, bit-complement
+   and uniform random traffic. These are based on common communication
+   patterns found in real applications. The frequency of message
+   generation is determined by a uniform or Poisson distribution.
+
+Topology, Routing and Virtual Channel Selection
+-----------------------------------------------
+
+Topology, Routing strategies and input and output virtual channel
+selection strategies need to be decided for any inter-connection
+network. Once we have all of these in place we can simulate an
+inter-connection network.
+
+Topology
+~~~~~~~~
+
+For every architecture one wants to design, a topology file has to
+written which defines a few basic functions for that particular
+topology. These are:
+
+``void getNeighbours(int nodeid, int numP)``
+
+This is called initially for every switch and this populates the data
+structure next in a switch which contains the connectivity of that
+switch. The switch specified by switch has numP ports.
+
+``int getNext(int portid, int nodeid, int numP)``
+
+Returns the index of the switch/node that is connected to the switch
+nodeid, at portid. The number of ports this node has is numP.
+
+``int getNextChannel(int portid, int nodeid, int numP)``
+
+Returns the index of the channel that is connected to the switch nodeid,
+at portid. The number of ports this node has is numP.
+
+``int getStartPort(int nodeid, int numP, int dest)``
+
+Return the index of the port that is connected to this compute node from
+a switch
+
+``int getStartVc()``
+
+Returns the index of the first virtual channel (mostly 0).
+
+``int getStartSwitch(int nodeid)``
+
+Returns the index of the node/switch that is connected to the first port
+
+``int getStartNode()``
+
+Returns the index of the first node. Each poser has a separate index,
+irrespective of the type of the poser.
+
+``int getEndNode()``
+
+Returns the index of the last node.
+
+Routing
+~~~~~~~
+
+Routing strategy needs to be specified for every interconnection
+network. There is usually at least one routing strategy that needs to be
+defined for every topology, Usually we have many more. The following
+functions need to be defined for every routing strategy.
+
+``int selectRoute(int current, int dest, int numP, Topology* top, Packet
+*p, map<int,int> &bufsize, unsigned short *xsubi)``
+
+Returns the portid that should be taken on switch current if the
+destination is dest. The number of ports on a switch is numP. We also
+pass the pointer to the topology and to the Packet.
+
+``int selectRoute(int current, int dest, int numP, Topology* top, Packet
+*p, map<int,int> &bufsize, map<int,int> &portContention, unsigned short
+*xsubi)``
+
+Returns the portid that should be taken on switch current if the
+destination is dest. The number of ports on a switch is numP. We also
+pass the pointer to the topology and to the Packet. Bufsize is the state
+of the ports in a switch, i.e. how many buffers on each port are full,
+while portContention is used to give priority to certain ports, when
+more options are available.
+
+``int expectedTime(int src, int dest, POSE_TimeType ovt, POSE_TimeType
+origOvt, int length, int *numHops)``
+
+Returns the expected time for a packet to travel from src to dest, when
+the number of hops it will need to travel is numHops.
+
+``int convertOutputToInputPort(int id, Packet *p, int numP, int *next)``
+
+Translate this output port to input port on the switch this port is
+connected to.
+
+Input Virtual Channel Selection
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For every switch, we need to know the mechanism it uses to choose input
+virtual channel. There are a few different input virtual channel
+selection strategies, and a switch can choose among them. Each should
+implement the following function.
+
+``int selectInputVc(map<int,int> &availBuffer, map<int,int> &request,
+map<int,vector<Header> > &inBuffer, int globalVc, int curSwitch)``
+
+Returns the input virtual channel to be used depending on the strategy
+and the input parameters.
+
+Output Virtual Channel Selection
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For every switch, we need to know the mechanism it uses to choose output
+virtual channel. There are a few different output virtual channel
+selection strategies, and a switch can choose among them. Each should
+implement the following function.
+
+``int selectOutputVc(map<int,int> &bufsize, Packet *p, int unused)``
+
+Returns the output virtual channel to be used depending on the strategy
+and the input parameters.
diff --git a/doc/bigsim/manual.rst b/doc/bigsim/manual.rst
new file mode 100644 (file)
index 0000000..a2296ba
--- /dev/null
@@ -0,0 +1,1081 @@
+===============================================================
+BigSim Parallel Simulator for Extremely Large Parallel Machines
+===============================================================
+
+.. contents::
+   :depth: 3
+
+Introduction
+============
+
+Parallel machines with an extremely large number of processors are now
+being designed and built. For example, the BlueGene/L (BG/L) machine
+built by IBM has 64,000 dual-processor nodes with 360 teraflops of peak
+performance. Another more radical design from IBM, code-named Cyclops
+(BlueGene/C), had over one million floating point units, fed by 8
+million instructions streams supported by individual thread units,
+targeting 1 petaflops of peak performance.
+
+It is important that one can study the programming issues and
+performance of parallel applications on such machines even before the
+machine is built. Thus, we have developed a parallel simulator - BigSim,
+to facilitate this research.
+
+Since our research was initiated by the BlueGene/C project, in previous
+editions of this manual we also called our simulator as Blue Gene
+Simulator. Our simulator is capable of simulating a broad class of
+"Massively Parallel Processors-In-Memory", or MPPIM machines.
+
+Simulator system components
+---------------------------
+
+Our simulator system includes these components:
+
+#. a parallel emulator which emulates a low level machine API targeting
+   an architecture like BlueGene;
+
+#. a message driven programming language (Charm++) running on top of the
+   emulator;
+
+#. the Adaptive MPI (an implementation of MPI on top of Charm++)
+   environment;
+
+#. a parallel post-mortem mode simulator for performance prediction,
+   including network simulation.
+
+History
+-------
+
+The first version of the BlueGene emulator was written in Charm++, a
+parallel object language, in fall 2001. The second version of the
+BlueGene emulator was completely rewritten on top of Converse instead of
+Charm++ in spring 2002. While the API supported by the original emulator
+remains almost the same, many new features were added. The new emulator
+was implemented on a portable low layer communication library -
+Converse, in order to achieve better performance by avoiding the cross
+layer overhead.
+
+Charm++ was ported to the emulator in 2002, providing the first parallel
+language model on top of the emulator.
+
+A performance simulation capability was added to the emulator in spring
+2003. The new simulator was renamed to BigSim at the same time. During
+the same year, we developed a POSE-based postmortem mode network
+simulator called BigNetSim. In fall 2006, we renamed BigNetSim as simply
+BigSim simulator.
+
+In the following sections, we will first describe how to download and
+compile the BigSim system (Section :numref:`install`).
+Section :numref:`bgemulator` describes the BigSim Emulator and the low
+level machine API in detail.
+
+.. _install:
+
+BigSim Emulator Installation and Usage
+======================================
+
+Installing Charm++ and BigSim
+-----------------------------
+
+The BigSim Emulator is distributed as part of the Charm++ standard
+distribution. One needs to download Charm++ and compile the BigSim
+Simulator. This process should begin with downloading Charm++ from the
+website: http://charm.cs.uiuc.edu.
+
+Please refer to “Charm++ Installation and Usage Manual” and also the
+file README in the source code for detailed instructions on how to
+compile Charm++. In short, the “build” script is the main tool for
+compiling Charm++. One needs to provide *target* and *platform*
+selections:
+
+::
+
+    ./build <target> <platform> [options ...] [charmc-options ...]
+
+For example, to compile on a 64-bit Linux machine, one would type:
+
+::
+
+   ./build charm++ netlrts-linux-x86_64 -O2
+
+which builds essential Charm++ kernel using UDP sockets as the
+communication method; alternatively, it is possible to build the Charm++
+kernel on MPI using:
+
+::
+
+   ./build charm++ mpi-linux-x86_64 -O2
+
+For other platforms, netlrts-linux-x86_64 should be replaced by whatever
+platform is being used. See the charm/README file for a complete list of
+supported platforms.
+
+Building Only the BigSim Emulator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The BigSim Emulator is implemented on top of Converse in Charm++. To
+compile the BigSim Emulator, one can compile Emulator libraries directly
+on top of normal Charm++ using “bgampi” as the compilation target, like
+
+::
+
+   ./build bgampi netlrts-linux-x86_64 -O2
+
+With Emulator libraries, one can write BigSim applications using its low
+level machine API (defined in  :numref:`bgemulator`).
+
+Building Charm++ or AMPI on the BigSim Emulator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to build Charm++ or AMPI on top of BigSim Emulator (which
+itself is implemented on top of Converse), a special build option
+“bigemulator” needs to be specified:
+
+::
+
+   ./build bgampi netlrts-linux-x86_64 bigemulator -O2
+
+The “bgampi” option is the compilation *target* that tells “build” to
+compile BigSim Emulator libraries in addition to Charm++ kernel
+libraries. The “bigemulator” option is a build *option* to platform
+“netlrts-linux”, which tells “build” to build Charm++ on top of the
+BigSim Emulator.
+
+The above “build" command creates a directory named
+“netlrts-linux-x86_64-bigemulator" under charm, which contains all the
+header files and libraries needed for compiling a user application. With
+this version of Charm++, one can run normal Charm++ and AMPI application
+on top of the emulator (in a virtualized environment).
+
+Compiling BigSim Applications
+-----------------------------
+
+Charm++ provides a compiler script ``charmc`` to compile all programs.
+As will be described in this subsection, there are three methods to
+write a BigSim application: (a) using the low level machine API, (b)
+using Charm++ or (c) using AMPI. Methods (b) and (c) are essentially
+used to obtain traces from the BigSim Emulator, such that one can use
+those traces in a post-mortem simulation as explained in
+Section :numref:`bignetsim`.
+
+Writing a BigSim application using low level machine API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The original goal of the low level machine API was to mimic the
+BlueGene/C low level programming API. It is defined in
+section :numref:`bgemulator`. Writing a program in the low level
+machine API, one just needs to link Charm++’s BigSim emulator libraries,
+which provide the emulation of the machine API using Converse as the
+communication layer.
+
+In order to link against the BigSim library, one must specify
+``-language bigsim`` as an argument to the ``charmc`` command, for
+example:
+
+::
+
+   charmc -o hello hello.C -language bigsim
+
+Sample applications in low level machine API can be found in the
+directory charm/examples/bigsim/emulator/.
+
+Writing a BigSim application in Charm++
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+One can write a normal Charm++ application which can automatically run
+on the BigSim Emulator after compilation. Charm++ implements an
+object-based message-driven execution model. In Charm++ applications,
+there are collections of C++ objects, which communicate by remotely
+invoking methods on other objects via messages.
+
+To compile a program written in Charm++ on the BigSim Emulator, one
+specifies ``-language charm++`` as an argument to the ``charmc``
+command:
+
+::
+
+   charmc -o hello hello.C -language charm++
+
+This will link both Charm++ runtime libraries and BigSim Emulator
+libraries.
+
+Sample applications in Charm++ can be found in the directory
+charm/examples/bigsim, specifically charm/examples/bigsim/emulator/littleMD.
+
+Writing a BigSim application in MPI
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+One can also write an MPI application for the BigSim Emulator. Adaptive
+MPI, or AMPI, is implemented on top of Charm++, supporting dynamic load
+balancing and multithreading for MPI applications. Those are based on
+the user-level migrating threads and load balancing capabilities
+provided by the Charm++ framework. This allows legacy MPI programs to
+run on top of BigSim Charm++ and take advantage of the Charm++’s
+virtualization and adaptive load balancing capability.
+
+Currently, AMPI implements most features in the MPI version 1.0, with a
+few extensions for migrating threads and asynchronous reduction.
+
+To compile an AMPI application for the BigSim Emulator, one needs to
+link against the AMPI library as well as the BigSim Charm++ runtime
+libraries by specifying ``-language ampi`` as an argument to the
+``charmc`` command:
+
+::
+
+   charmc -o hello hello.C -language ampi
+
+Sample applications in AMPI can be found in the directory
+charm/examples/ampi, specifically charm/examples/ampi/pingpong.
+
+Running a BigSim Application
+----------------------------
+
+To run a parallel BigSim application, Charm++ provides a utility program
+called ``charmrun`` that starts the parallel execution. For detailed
+description on how to run a Charm++ application, refer to the file
+charm/README in the source code distribution.
+
+To run a BigSim application, one needs to specify the following
+parameters to ``charmrun`` to define the simulated machine size:
+
+#. ``+vp``: define the number of processors of the hypothetical (future)
+   system
+
+#. ``+x, +y`` and ``+z``: optionally define the size of the machine in
+   three dimensions, these define the number of nodes along each
+   dimension of the machine (assuming a torus/mesh topology);
+
+#. ``+wth`` and ``+cth``: For one node, these two parameters define the
+   number of worker processors (``+wth``) and the number of
+   communication processors (``+cth``).
+
+#. ``+bgwalltime``: used only in simulation mode, when specified, use
+   wallclock measurement of the time taken on the simulating machine to
+   estimate the time it takes to run on the target machine.
+
+#. ``+bgcounter``: used only in simulation mode, when specified, use the
+   performance counter to estimate the time on target machine. This is
+   currently only supported when perfex is installed, like Origin2000.
+
+#. ``+bglog``: generate BigSim trace log files, which can be used with
+   BigNetSim.
+
+#. ``+bgcorrect``: starts the simulation mode to predict performance.
+   Without this option, a program simply runs on the emulator without
+   doing any performance prediction. Note: this option is obsolete, and
+   no longer maintained, use +bglog to generate trace logs, and use
+   BigNetSim for performance prediction.
+
+For example, to simulate a parallel machine of size 64K as 40x40x40,
+with one worker processor and one communication processor on each node,
+and use 100 real processors to run the simulation, the command to be
+issued should be:
+
+::
+
+   ./charmrun +p100 ./hello +x40 +y40 +z40 +cth1 +wth1
+
+To run an AMPI program, one may also want to specify the number of
+virtual processors to run the MPI code by using ``+vp``. As an example,
+
+::
+
+   ./charmrun +p100 ./hello +x40 +y40 +z40 +cth1 +wth1 +vp 128000
+
+starts the simulation of a machine of size 40x40x40 with one worker
+processor in each node, running 128000 MPI tasks (2 MPI tasks on each
+node), using 100 real processors to run the simulation. In this case,
+``MPI_Comm_size()`` returns 128000 for ``MPI_COMM_WORLD``. If the
+``+vp`` option is not specified, the number of virtual processors will
+be equal to the number of worker processors of the simulated machine, in
+this case 64000.
+
+.. _bgemulator:
+
+BigSim Emulator
+===============
+
+The BigSim emulator environment is designed with the following
+objectives:
+
+#. To support a realistic BigSim API on existing parallel machines
+
+#. To obtain first-order performance estimates of algorithms
+
+#. To facilitate implementations of alternate programming models for
+   Blue Gene
+
+The machine supported by the emulator consists of three-dimensional grid
+of 1-chip nodes. The user may specify the size of the machine along each
+dimension (e.g. 34x34x36). The chip supports :math:`k` threads (e.g.
+200), each with its own integer unit. The proximity of the integer unit
+with individual memory modules within a chip is not currently modeled.
+
+The API supported by the emulator can be broken down into several
+components:
+
+#. Low-level API for chip-to-chip communication
+
+#. Mid-level API that supports local micro-tasking with a chip level
+   scheduler with features such as: read-only variables, reductions,
+   broadcasts, distributed tables, get/put operations
+
+#. Migratable objects with automatic load balancing support
+
+Of these, the first two have been implemented. The simple time stamping
+algorithm, without error correction, has been implemented. More
+sophisticated timing algorithms, specifically aimed at error correction,
+and more sophisticated features (2, 3, and others), as well as libraries
+of commonly needed parallel operations are part of the proposed work for
+future.
+
+The following sections define the appropriate parts of the API, with
+example programs and instructions for executing them.
+
+BigSim Programming Environment
+------------------------------
+
+The basic philosophy of the BigSim Emulator is to hide intricate details
+of the simulated machine from the application developer. Thus, the
+application developer needs to provide initialization details and
+handler functions only and gets the result as though running on a real
+machine. Communication, Thread creation, Time Stamping, etc are done by
+the emulator.
+
+BigSim API: Level 0
+~~~~~~~~~~~~~~~~~~~
+
+``void addBgNodeInbuffer(bgMsg *msgPtr, int nodeID)``
+
+low-level primitive invoked by Blue Gene emulator to put the message to
+the inbuffer queue of a node.
+
+msgPtr - pointer to the message to be sent to target node;
+
+nodeID - node ID of the target node, it is the serial number of a
+bluegene node in the emulator’s physical node.
+
+``void addBgThreadMessage(bgMsg *msgPtr, int threadID)`` add a message to a
+thread’s affinity queue, these messages can be only executed by a
+specific thread indicated by threadID.
+
+``void addBgNodeMessage(bgMsg *msgPtr)`` add a message to a node’s
+non-affinity queue, these messages can be executed by any thread in the
+node.
+
+``boolean checkReady()`` invoked by communication thread to see if there is
+any unattended message in inBuffer.
+
+``bgMsg * getFullBuffer()`` invoked by communication thread to retrieve the
+unattended message in inBuffer.
+
+``CmiHandler msgHandlerFunc(char *msg)``
+Handler function type that user
+can register to handle the message.
+
+``void sendPacket(int x, int y, int z, int msgSize,bgMsg *msg)``
+
+chip-to-chip communication function. It send a message to Node[x][y][z].
+
+bgMsg is the message type with message envelope used internally.
+
+Initialization API: Level 1a
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All the functions defined in API Level 0 are used internally for the
+implementation of bluegene node communication and worker threads.
+
+From this level, the functions defined are exposed to users to write
+bluegene programs on the emulator.
+
+Considering that the emulator machine will emulate several Bluegene
+nodes on each physical node, the emulator program defines this function
+BgEmulatorInit(int argc, char \**argv) to initialize each emulator node.
+In this function, user program can define the Bluegene machine size,
+number of communication/worker threads, and check the command line
+arguments.
+
+The size of the simulated machine being emulated and the number of
+thread per node is determined either by the command line arguments or
+calling following functions:
+
+``void BgSetSize(int sx, int sy, int sz)``
+set Blue Gene Machine size;
+
+``void BgSetNumWorkThread(int num)``
+set number of worker threads per node;
+
+``void BgSetNumCommThread(int num)``
+set number of communication threads per node;
+
+``int BgRegisterHandler(BgHandler h)``
+register user message handler functions;
+
+For each simulated node, the execution starts at ``BgNodeStart(int argc,
+char **argv)`` called by the emulator, where application handlers can be
+registered and computation is triggered by creating a task at required
+nodes.
+
+Similar to pthread’s thread specific data, each bluegene node has its
+own node specific data associated with it. To do this, the user needs to
+define its own node-specific variables encapsulated in a struct
+definition and register the pointer to the data with the emulator by
+following function:
+
+``void BgSetNodeData(char *data)``
+
+To retrieve the node specific data, call:
+
+``char *BgGetNodeData()``
+
+After completion of execution, user program invokes a function:
+
+``void BgShutdown()``
+
+to terminate the emulator.
+
+Handler Function API: Level 1a
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following functions can be called in user’s application program to
+retrieve the simulated machine information, get thread execution time,
+and perform the communication.
+
+``void BgGetSize(int *sx, int *sy, int *sz)``
+
+``int BgGetNumWorkThread()``
+
+``int BgGetNumCommThread()``
+
+``int BgGetThreadID()``
+
+``double BgGetTime()``
+
+``void BgSendPacket(int x, int y, int z, int threadID, int handlerID,
+WorkType type, int numbytes, char* data)``
+
+This sends a trunk of data to Node[x, y, z] and also specifies the
+handler function to be used for this message i.e. the handlerID;
+threadID specifies the desired thread to handle the message, ANYTHREAD
+means no preference.
+
+To specify the thread category:
+
+1:
+   a small piece of work that can be done by communication thread
+   itself, so NO scheduling overhead.
+
+0:
+   a large piece of work, so communication thread schedules it for a
+   worker thread
+
+Writing a BigSim Application
+----------------------------
+
+Application Skeleton
+~~~~~~~~~~~~~~~~~~~~
+
+::
+
+   Handler function prototypes;
+   Node specific data type declarations;
+
+   void  BgEmulatorInit(int argc, char **argv)  function
+     Configure bluegene machine parameters including size, number of threads, etc.
+     You also need to register handlers here.
+
+   void *BgNodeStart(int argc, char **argv) function
+     The usual practice in this function is to send an initial message to trigger
+     the execution.
+     You can also register node specific data in this function.
+
+   Handler Function 1, void handlerName(char *info)
+   Handler Function 2, void handlerName(char *info)
+   ..
+   Handler Function N, void handlerName(char *info)
+
+Sample Application 1
+~~~~~~~~~~~~~~~~~~~~
+
+::
+
+   /* Application:
+    *   Each node starting at [0,0,0] sends a packet to next node in
+    *   the ring order.
+    *   After node [0,0,0] gets message from last node
+    *   in the ring, the application ends.
+    */
+
+
+   #include "blue.h"
+
+   #define MAXITER 2
+
+   int iter = 0;
+   int passRingHandler;
+
+   void passRing(char *msg);
+
+   void nextxyz(int x, int y, int z, int *nx, int *ny, int *nz)
+   {
+     int numX, numY, numZ;
+
+     BgGetSize(&numX, &numY, &numZ);
+     *nz = z+1; *ny = y; *nx = x;
+     if (*nz == numZ) {
+       *nz = 0; (*ny) ++;
+       if (*ny == numY) {
+         *ny = 0; (*nx) ++;
+         if (*nx == numX) *nx = 0;
+       }
+     }
+   }
+
+   void BgEmulatorInit(int argc, char **argv)
+   {
+     passRingHandler = BgRegisterHandler(passRing);
+   }
+
+   /* user defined functions for bgnode start entry */
+   void BgNodeStart(int argc, char **argv)
+   {
+     int x,y,z;
+     int nx, ny, nz;
+     int data, id;
+
+     BgGetXYZ(&x, &y, &z);
+     nextxyz(x, y, z, &nx, &ny, &nz);
+     id = BgGetThreadID();
+     data = 888;
+     if (x == 0 && y==0 && z==0) {
+       BgSendPacket(nx, ny, nz, -1,passRingHandler, LARGE_WORK,
+                               sizeof(int), (char *)&data);
+     }
+   }
+
+   /* user write code */
+   void passRing(char *msg)
+   {
+     int x, y, z;
+     int nx, ny, nz;
+     int id;
+     int data = *(int *)msg;
+
+     BgGetXYZ(&x, &y, &z);
+     nextxyz(x, y, z, &nx, &ny, &nz);
+     if (x==0 && y==0 && z==0) {
+       if (++iter == MAXITER) BgShutdown();
+     }
+     id = BgGetThreadID();
+     BgSendPacket(nx, ny, nz, -1, passRingHandler, LARGE_WORK,
+                               sizeof(int), (char *)&data);
+   }
+
+Sample Application 2
+~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: C
+
+
+   /* Application:
+    *   Find the maximum element.
+    *   Each node computes maximum of it's elements and
+    *   the max values it received from other nodes
+    *   and sends the result to next node in the reduction sequence.
+    * Reduction Sequence: Reduce max data to X-Y Plane
+    *   Reduce max data to Y Axis
+    *   Reduce max data to origin.
+    */
+
+
+   #include <stdlib.h>
+   #include "blue.h"
+
+   #define A_SIZE 4
+
+   #define X_DIM 3
+   #define Y_DIM 3
+   #define Z_DIM 3
+
+   int REDUCE_HANDLER_ID;
+   int COMPUTATION_ID;
+
+   extern "C" void reduceHandler(char *);
+   extern "C" void computeMax(char *);
+
+   class ReductionMsg {
+   public:
+     int max;
+   };
+
+   class ComputeMsg {
+   public:
+     int dummy;
+   };
+
+   void BgEmulatorInit(int argc, char **argv)
+   {
+     if (argc < 2) {
+       CmiAbort("Usage: <program> <numCommTh> <numWorkTh>\n");
+     }
+
+     /* set machine configuration */
+     BgSetSize(X_DIM, Y_DIM, Z_DIM);
+     BgSetNumCommThread(atoi(argv[1]));
+     BgSetNumWorkThread(atoi(argv[2]));
+
+     REDUCE_HANDLER_ID = BgRegisterHandler(reduceHandler);
+     COMPUTATION_ID = BgRegisterHandler(computeMax);
+
+   }
+
+   void BgNodeStart(int argc, char **argv) {
+     int x, y, z;
+     BgGetXYZ(&x, &y, &z);
+
+     ComputeMsg *msg = new ComputeMsg;
+     BgSendLocalPacket(ANYTHREAD, COMPUTATION_ID, LARGE_WORK,
+                       sizeof(ComputeMsg), (char *)msg);
+   }
+
+   void reduceHandler(char *info) {
+     // assumption: THey are initialized to zero?
+     static int max[X_DIM][Y_DIM][Z_DIM];
+     static int num_msg[X_DIM][Y_DIM][Z_DIM];
+
+     int i,j,k;
+     int external_max;
+
+     BgGetXYZ(&i,&j,&k);
+     external_max = ((ReductionMsg *)info)->max;
+     num_msg[i][j][k]++;
+
+     if ((i == 0) && (j == 0) && (k == 0)) {
+       // master node expects 4 messages:
+       // 1 from itself;
+       // 1 from the i dimension;
+       // 1 from the j dimension; and
+       // 1 from the k dimension
+       if (num_msg[i][j][k] < 4) {
+         // not ready yet, so just find the max
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+       } else {
+         // done. Can report max data after making last comparison
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+         CmiPrintf("The maximal value is %d \n", max[i][j][k]);
+         BgShutdown();
+         return;
+       }
+     } else if ((i == 0) && (j == 0) && (k != Z_DIM - 1)) {
+       // nodes along the k-axis other than the last one expects 4 messages:
+       // 1 from itself;
+       // 1 from the i dimension;
+       // 1 from the j dimension; and
+       // 1 from the k dimension
+       if (num_msg[i][j][k] < 4) {
+         // not ready yet, so just find the max
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+       } else {
+         // done. Forwards max data to node i,j,k-1 after making last comparison
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+         ReductionMsg *msg = new ReductionMsg;
+         msg->max = max[i][j][k];
+         BgSendPacket(i,j,k-1,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK,
+                               sizeof(ReductionMsg), (char *)msg);
+       }
+     } else if ((i == 0) && (j == 0) && (k == Z_DIM - 1)) {
+       // the last node along the k-axis expects 3 messages:
+       // 1 from itself;
+       // 1 from the i dimension; and
+       // 1 from the j dimension
+       if (num_msg[i][j][k] < 3) {
+         // not ready yet, so just find the max
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+       } else {
+         // done. Forwards max data to node i,j,k-1 after making last comparison
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+         ReductionMsg *msg = new ReductionMsg;
+         msg->max = max[i][j][k];
+         BgSendPacket(i,j,k-1,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK,
+                               sizeof(ReductionMsg), (char *)msg);
+       }
+     } else if ((i == 0) && (j != Y_DIM - 1)) {
+       // for nodes along the j-k plane except for the last and first row of j,
+       // we expect 3 messages:
+       // 1 from itself;
+       // 1 from the i dimension; and
+       // 1 from the j dimension
+       if (num_msg[i][j][k] < 3) {
+         // not ready yet, so just find the max
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+       } else {
+         // done. Forwards max data to node i,j-1,k after making last comparison
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+         ReductionMsg *msg = new ReductionMsg;
+         msg->max = max[i][j][k];
+         BgSendPacket(i,j-1,k,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK,
+                               sizeof(ReductionMsg), (char *)msg);
+       }
+     } else if ((i == 0) && (j == Y_DIM - 1)) {
+       // for nodes along the last row of j on the j-k plane,
+       // we expect 2 messages:
+       // 1 from itself;
+       // 1 from the i dimension;
+       if (num_msg[i][j][k] < 2) {
+         // not ready yet, so just find the max
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+       } else {
+         // done. Forwards max data to node i,j-1,k after making last comparison
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+         ReductionMsg *msg = new ReductionMsg;
+         msg->max = max[i][j][k];
+         BgSendPacket(i,j-1,k,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK,
+                               sizeof(ReductionMsg), (char *)msg);
+       }
+     } else if (i != X_DIM - 1) {
+       // for nodes anywhere the last row of i,
+       // we expect 2 messages:
+       // 1 from itself;
+       // 1 from the i dimension;
+       if (num_msg[i][j][k] < 2) {
+         // not ready yet, so just find the max
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+       } else {
+         // done. Forwards max data to node i-1,j,k after making last comparison
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+         ReductionMsg *msg = new ReductionMsg;
+         msg->max = max[i][j][k];
+         BgSendPacket(i-1,j,k,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK,
+                               sizeof(ReductionMsg), (char *)msg);
+       }
+     } else if (i == X_DIM - 1) {
+       // last row of i, we expect 1 message:
+       // 1 from itself;
+       if (num_msg[i][j][k] < 1) {
+         // not ready yet, so just find the max
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+       } else {
+         // done. Forwards max data to node i-1,j,k after making last comparison
+         if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+         }
+         ReductionMsg *msg = new ReductionMsg;
+         msg->max = max[i][j][k];
+         BgSendPacket(i-1,j,k,-1,REDUCE_HANDLER_ID,LARGE_WORK,
+                               sizeof(ReductionMsg), (char *)msg);
+       }
+     }
+   }
+
+   void computeMax(char *info) {
+     int A[A_SIZE][A_SIZE];
+     int i, j;
+     int max = 0;
+
+     int x,y,z; // test variables
+     BgGetXYZ(&x,&y,&z);
+
+     // Initialize
+     for (i=0;i<A_SIZE;i++) {
+       for (j=0;j<A_SIZE;j++) {
+         A[i][j] = i*j;
+       }
+     }
+
+   //  CmiPrintf("Finished Initializing %d %d %d!\n",  x , y , z);
+
+     // Find Max
+     for (i=0;i<A_SIZE;i++) {
+       for (j=0;j<A_SIZE;j++) {
+         if (max < A[i][j]) {
+       max = A[i][j];
+         }
+       }
+     }
+
+     // prepare to reduce
+     ReductionMsg *msg = new ReductionMsg;
+     msg->max = max;
+     BgSendLocalPacket(ANYTHREAD, REDUCE_HANDLER_ID, LARGE_WORK,
+                               sizeof(ReductionMsg), (char *)msg);
+
+   //  CmiPrintf("Sent reduce message to myself with max value %d\n", max);
+   }
+
+Interpolation / Extrapolation Tool
+=================================================
+
+It is often desirable to predict performance of non-existent machines,
+or across architectures. This section describes a tool that rewrites the
+log files produced by BigSim (also known as *bgTrace trace logs*) to
+provide new durations for portions of the application consisting of
+sequential execution blocks. These new durations can be based upon
+multiple types of models. The tool can be easily modified to add new
+types of models if the user requires. The models can be generated from
+full or partial executions of an application on an existing processor or
+on a cycle-accurate simulator.
+
+When predicting the runtime of a parallel application on a
+not-yet-existent parallel platform, there are two important concerns.
+The first is correctly modeling the interconnection network, which is
+handled by BigSimulator (also called BigNetSim). The second is
+determining the durations of the relevant sequential portions of code,
+which we call **Sequential Execution Blocks (SEB)**, on a new type of
+processor. The interpolation tool of this section handles only the
+prediction of SEB durations, using currently three types of implemented
+models:
+
+#. **Scaling of SEB durations** observed on an available (existing)
+   processor, via multiplication of the original durations by a constant
+   factor.
+
+#. **Parameterizations of SEBs**: each SEB is augmented with
+   user-defined parameters that influence the duration of the SEB. An
+   extrapolation model based on those parameters can predict the
+   durations of SEBs not instrumented in the initial emulation run.
+
+#. **Parameterizations with cycle-accurate simulations** for
+   non-existent architectures: processor designers use cycle-accurate
+   simulators to simulate the performance of a piece of code on a future
+   processor that is currently unavailable. Timings for each SEB can be
+   estimated in such a cycle-accurate simulator. The cycle-accurate
+   timings can be extrapolated to predict the durations of SEBs not
+   instrumented in the cycle-accurate simulator.
+
+This tool will soon include a new model with support for performance
+counters. The currently available tool rewrites the log files produced
+by a run in the BigSim Emulator. The rewritten log files can then be
+consumed by BigSimulator. This usage flow can be seen in
+Figure :numref:`interpolationflow`, showing
+that multiple types of models are supported in the tool.
+
+.. _interpolationflow:
+.. figure:: figures/InterpolationFlow.png
+   :width: 4in
+
+   Flow diagram for use of the interpolation tool
+
+Tool Usage
+-----------------
+
+The interpolation tool is part of the regular Charm++ distribution and
+can be found under the directory
+``charm/examples/bigsim/tools/rewritelog`` with a ``README`` file
+describing its use in more detail than this manual.
+
+Producing the Parameterized Timings Log
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The interpolation tool uses as input a log of actual durations of
+user-bracketed sequential execution blocks. These timings come from a
+full or partial execution of the parallel application on a real machine
+or within a cycle-accurate simulator.
+
+The user must insert ``startTraceBigSim()`` and ``endTraceBigSim()``
+calls around the main computational regions in the parallel application.
+These two calls bracket the region of interest and print out a record
+for that computational region. The functions should be called at most
+once during any SEB. The output produced by ``endTraceBigSim()`` is a
+line similar to
+
+``TRACEBIGSIM: event:{ PairCalculator::bwMultiplyHelper } time:{ 0.002586 } params:{ 16384.00 1.00 220.00 128.00 128.00 0.00 0.00 0.00 }``.
+
+The event name and the values (in double-precision floating-point) for
+up to 20 parameters are specified in the call to ``endTraceBigSim()``;
+the ``time`` field records the duration of the bracketed region of
+sequential code.
+
+To run in a cycle-accurate simulator such as IBM’s MAMBO, the
+``startTraceBigSim()`` and ``endTraceBigSim()`` functions would be
+modified to switch between the “fast forward” mode used during the rest
+of the program and the cycle-accurate mode during the bracketed region
+of code. The functions are provided in C++ source files under the
+directory ``charm/examples/bigsim/tools/rewritelog/traceBigSim`` and
+their calls must be added to an application’s source file manually.
+
+The BigSim log file format
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To understand how the interpolation tool works, it is instructive to
+consider the format of logs produced by the BigSim Emulator. A BigSim
+log file (i.e. bgTrace log) contains data from emulation of the full
+parallel application. There is an entry for each SEB, with the following
+fields: *ID*, *Name*, :math:`T_{start}`, :math:`T_{end}`, *Back*,
+*Forward*, *Message ID*, *Source Node*, *Message ID*, *Sent Messages*.
+The final field is actually a list of records for each message sent by
+the execution block; each record contains the following fields: *Message
+ID*, :math:`T_{sent}`, :math:`T_{recv}`, *Destination PE*, *Size*,
+*Group*.
+
+The interpolation tool will rewrite the durations of the SEBs by
+correcting the :math:`T_{end}` field for the SEB and the
+:math:`T_{sent}` fields for each message sent. The new durations of all
+SEBs will be based upon some model :math:`M:SEB\rightarrow Duration`.
+
+Each SEB can be decomposed into three temporal regions as shown in
+Figure :numref:`event_diagram`:. The entire SEB is
+associated with execution of a Charm++ entry method, while the middle
+region is the computational kernel of interest, bracketed by the user’s
+``startTraceBigSim()`` and ``endTraceBigSim()`` calls. The model is used
+only to approximate the new duration of the middle temporal region; the
+durations of the beginning and ending regions are simply scaled by a
+constant factor. Internally, the interpolation tool takes the ID for
+each SEB and looks up its associated parameters. When those parameters
+are found, they are used as input for evaluation of the new duration
+:math:`d_{new}` for the SEB. The end time is then modified to be
+:math:`T_{end}\leftarrow  T_{start}+d_{new}`.
+
+.. _event_diagram:
+.. figure:: figures/event_diagram.png
+   :width: 5in
+
+   SEBs in the bgTrace file have a start and end time. Only a portion of
+   the SEB, e.g. the important computational kernel, is timed when
+   performing cycle accurate simulation. The duration of the middle
+   portion of the SEB can be estimated in a different manner than the
+   rest of the SEB. For example, the begin and end pieces can be scaled
+   by some constant factor, while the bracketed middle region’s duration
+   can be estimated based on a more sophisticated model.
+
+.. _event_diagram2:
+.. figure:: figures/event_diagram2.png
+   :width: 6in
+
+   Message send times for messages sent from an SEB are remapped
+   linearly onto the new time ranges for the SEB, region by region.
+
+
+The messages in the message list for each SEB must also have their
+:math:`T_{sent}` times rewritten. This is accomplished by linearly
+mapping the old :math:`T_{sent}` value from to the new range for the
+enclosing SEB region, as shown in Figure
+:numref:`event_diagram2`. Any message sent during the
+first portion will be mapped linearly onto the new first portion of the
+SEB. The new message :math:`T_{recv}` times are ignored by BigSimulator,
+so they do not need to be modified.
+
+Supported performance models
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The interpolation tool supports three types of models, as described in
+this subsection. The more sophisticated models use the least-square
+curve fitting technique. The current implementation uses the Gnu
+Scientific Library(gsl) to perform the least-square fit to the given
+data. The library provides both the coefficients and a :math:`\chi^2`
+measure of the closeness of the fit to the input data.
+
+Model 1: Scaling SEB durations by a constant factor
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In simple cases, a sufficient approximation of the performance of a
+parallel application can be obtained by simply scaling the SEB durations
+by a constant factor. As an example, a user may know that a desired
+target machine has processors that will execute each SEB twice as fast
+as on an existing machine. The application is emulated on the existing
+machine and the observed SEB durations are scaled by a factor of
+:math:`2.0`. Although simple, this method may be sufficient in many
+cases. It becomes unnecessary to use the ``startTraceBigSim()`` and
+``endTraceBigSim()`` calls. The scaling factor is hard coded in the
+interpolation tool as ``time_dilation_factor``. It is used to scale all
+blocks unless a suitable advanced model has a better method for
+approximating the block’s duration. It will always be used to scale any
+portions of blocks that are not bracketed with the calls
+``startTraceBigSim()`` and ``endTraceBigSim()``.
+
+Model 2: Extrapolation based on user’s parameterizations
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The user can simply insert the bracketing calls ``startTraceBigSim()``
+and ``endTraceBigSim()`` around the computational kernels to log the
+times taken for each kernel. In practice, the duration of the SEB will
+likely depend upon the data distribution and access patterns for the
+parallel application. Thus, the user must specify parameters likely to
+influence the SEB duration. The parameters can include variables
+indicating number of loop iterations, number of calls to computational
+kernels, or sizes of accessed portions of data arrays. A model is built
+to approximate the duration of any SEB based upon its specified
+parameters.
+
+As an example, NAMD uses a number of different types of objects. The
+``compute`` objects will spend varying amounts of time depending upon
+the lengths of their associated atom lists. If an atom list is large,
+more interactions are computed and thus more computation is performed.
+Meanwhile, assume that a Charm++ entry method called
+``doWork(atomList)`` is where the majority of the work from an
+application occurs. The function computes forces on atoms of various
+types. Different calls to the function will contain different numbers
+and types of atoms. The source code for ``doWork(atomList)`` will be
+modified by the user to contain calls to ``startTraceBigSim()`` at the
+entry and ``endTraceBigSim()`` at the exit of the function. The program
+will be run, and the resulting timed samples will be used to build a
+model. Assume the expected runtime of ``doWork(atomList)`` is quadratic
+in the ``atomList`` length and linear in the number of carbon atoms in
+the ``atomList``. The ``endTraceBigSim()`` call would be provided with a
+descriptive name and a set of parameters, such as
+``endTraceBigSim(“doWork()”, p_1,p_2)``, where parameter :math:`p_1` is
+the length of ``atomList`` and parameter :math:`p_2` is the number of
+carbon atoms in ``atomList``.
+
+The goal of using a model is to be able to predict the execution time of
+any arbitrary call to ``doWork()``, given its parameters. The
+application can be run on an existing processor or parallel cluster for
+only a few timesteps with the modified ``doWork()`` method. This run
+will produce a list of
+{:math:`\left(p_1,p_2\right)\rightarrow duration`} records. A least
+squares method is applied to fit a curve
+:math:`f(p_1,p_2)=c_1+c_2 p_1+c_3 p_1^2 + c_4 p_2` approximating the
+durations of the records. The least square method minimizes the sum of
+the squares of the difference between the function :math:`f` evaluated
+at each parameter set and the actual timing observed at those
+parameters. The least square method is provided
+:math:`\left(1.0,p_1,p_1^2,p_2,time\right)` for each sample point and
+produces the coefficients :math:`c_n` in :math:`f`. An arbitrary set of
+parameters (in the current implementation, up to twenty) can be input to
+:math:`f` to produce an approximation of the runtime of ``doWork()``
+even though the particular instance was never timed before.
+
+Model 3: Extrapolation of partial executions with cycle accurate simulations and user’s parameterizations
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In this case, a cycle accurate simulator can be used to simulate a small
+fraction of all SEBs for a run of the application. The partial execution
+is used to build a model which applies to the whole execution.
+Parameterizations can be used as previously described, so that only some
+fraction of the SEBs will be run in the expensive cycle-accurate
+simulator. In NAMD, for example, a sufficient model can be built from a
+random sample of 2% of the cycle-accurate SEB durations from four
+timeloop iterations.
+
+.. _bgapi:
+
+BigSim Log Generation API
+=========================
+
+To be added ...
diff --git a/doc/charisma/manual.rst b/doc/charisma/manual.rst
new file mode 100644 (file)
index 0000000..9f26613
--- /dev/null
@@ -0,0 +1,753 @@
+===============
+Charisma Manual
+===============
+
+.. contents::
+   :depth: 3
+
+Introduction
+============
+
+This manual describes Charisma, an orchestration language for migratable
+parallel objects. Charisma can be downloaded from the CVS repository
+hosted on ``charm.cs.uiuc.edu``:
+
+::
+
+     cvs co orchestration
+
+Charisma Syntax
+===============
+
+A Charisma program is composed of two parts: the orchestration code in a
+.or file, and sequential user code in C/C++ form.
+
+Orchestration Code
+------------------
+
+The orchestration code in the .or file can be divided into two part. The
+header part contains information about the program, included external
+files, defines, and declaration of parallel constructs used in the code.
+The orchestration section is made up of statements that forms a global
+control flow of the parallel program. In the orchestration code,
+Charisma employs a macro dataflow approach; the statements produce and
+consume values, from which the control flows can be organized, and
+messages and method invocations generated.
+
+Header Section
+~~~~~~~~~~~~~~
+
+The very first line should give the name of the Charisma program with
+the ``program`` keyword.
+
+.. code-block:: none
+
+       program jacobi
+
+The ``program`` keyword can be replaced with ``module``, which means
+that the output program is going to be a library module instead of a
+stand-alone program. Please refer to Section :numref:`secmodule` for
+more details.
+
+Next, the programmer can include external code files in the generated
+code with keyword ``include`` with the filename without extension. For
+example, the following statement tells the Charisma compiler to look for
+header file “particles.h” to be included in the generated header file
+“jacobi.h” and to look for C/C++ code file “particles.[C|cc|cpp|cxx|c]”
+to be included in the generated C++ code file “jacobi.C”.
+
+.. code-block:: none
+
+       include particles;
+
+It is useful when there are source code that must precede the generated
+parallel code, such as basic data structure declaration.
+
+After the ``include`` section is the ``define`` section, where
+environmental variables can be defined for Charisma. For example, to
+tell Charisma to generate additional code to enable the load balancing
+module, the programmer needs to define “ldb” in the orchestration code.
+Please refer to Section :numref:`secldb` for details.
+
+Declaration Section
+~~~~~~~~~~~~~~~~~~~
+
+Next comes the declaration section, where classes, objects and
+parameters are declared. A Charisma program is composed of multiple sets
+of parallel objects which are organized by the orchestration code.
+Different sets of objects can be instantiated from different class
+types. Therefore, we have to specify the class types and object
+instantiation. Also we need to specify the parameters (See
+Section :numref:`sec:orchsec`) to use in the orchestration
+statements.
+
+A Charisma program or module has one “MainChare” class, and it does not
+require explicit instantiation since it is a singleton. The statement to
+declare MainChare looks like this:
+
+.. code-block:: none
+
+       class JacobiMain : MainChare;
+
+For object arrays, we first need to declare the class types inherited
+from 1D object array, 2D object array, etc, and then instantiate from
+the class types. The dimensionality information of the object array is
+given in a pair of brackets with each dimension size separated by a
+comma.
+
+.. code-block:: none
+
+       class JacobiWorker : ChareArray1D;
+       obj workers : JacobiWorker[N];
+
+       class Cell : ChareArray3D;
+       obj cells : Cell[M,M,M];
+
+Note that key word “class” is for class type derivation, and “obj” is
+for parallel object or object array instantiation. The above code
+segment declares a new class type JacobiWorker which is a 1D object
+array, (and the programmer is supposed to supply sequential code for it
+in files “JacobiWorker.h” and “JacobiWorker.C” (See
+Section :numref:`sec:sequential` for more details on sequential
+code). Object array “workers” is instantiated from “JacobiWorker” and
+has 16 elements.
+
+The last part is orchestration parameter declaration. These parameters
+are used only in the orchestration code to connect input and output of
+orchestration statements, and their data type and size is declared here.
+More explanation of these parameters can be found in
+Section :numref:`sec:orchsec`.
+
+.. code-block:: none
+
+       param lb : double[N];
+       param rb : double[N];
+
+With this, “lb” and “rb” are declared as parameters of that can be
+“connected” with local variables of double array with size of 512.
+
+.. _sec:orchsec:
+
+Orchestration Section
+~~~~~~~~~~~~~~~~~~~~~
+
+In the main body of orchestration code, the programmer describes the
+behavior and interaction of the elements of the object arrays using
+orchestration statements.
+
+:math:`\bullet` **Foreach Statement**
+
+The most common kind of parallelism is the invocation of a method across
+all elements in an object array. Charisma provides a *foreach* statement
+for specifying such parallelism. The keywords ``foreach`` and
+``end-foreach`` forms an enclosure within which the parallel invocation
+is performed. The following code segment invokes the entry method
+``compute`` on all the elements of array ``myWorkers``.
+
+.. code-block:: none
+
+     foreach i in workers
+       workers[i].compute();
+     end-foreach
+
+:math:`\bullet` **Publish Statement and Produced/Consumed Parameters**
+
+In the orchestration code, an object method invocation can have input
+and output (consumed and produced) parameters. Here is an orchestration
+statement that exemplifies the input and output of this object methods
+``workers.produceBorders`` and ``workers.compute``.
+
+.. code-block:: none
+
+     foreach i in workers
+       (lb[i], rb[i]) <- workers[i].produceBorders();
+       workers[i].compute(lb[i+1], rb[i-1]);
+
+       (+error) <- workers[i].reduceData();
+     end-foreach
+
+Here, the entry method ``workers[i].produceBorders`` produces (called
+*published* in Charisma) values of ``lb[i], rb[i]``, enclosed in a pair
+of parentheses before the publishing sign “``<-``”. In the second
+statement, function ``workers[i].compute`` consumes values of
+``lb[i+1], rb[i-1]``, just like normal function parameters. If a
+reduction operation is needed, the reduced parameter is marked with a
+“``+``” before it, like the ``error`` in the third statement.
+
+A entry method can have arbitrary number of published (produced and
+reduced) values and consumed values. In addition to basic data types,
+each of these values can also be an object of arbitrary type. The values
+published by ``A[i]`` must have the index ``i``, whereas values consumed
+can have the index ``e(i)``, which is an index expression in the form of
+``i``\ :math:`\pm c` where :math:`c` is a constant. Although we have
+used different symbols (``p`` and ``q``) for the input and the output
+variables, they are allowed to overlap.
+
+The parameters are produced and consumed in the program order. Namely, a
+parameter produced in an early statement will be consumed by the next
+consuming statement, but will no longer be visible to any consuming
+statement after a subsequent statement producing the same parameter in
+program order. Special rules involving loops are discussed later with
+loop statement.
+
+:math:`\bullet` **Overlap Statement**
+
+Complicated parallel programs usually have concurrent flows of control.
+To explicitly express this, Charisma provides a ``overlap`` keyword,
+whereby the programmer can fire multiple overlapping control flows.
+These flows may contain different number of steps or statements, and
+their execution should be independent of one another so that their
+progress can interleave with arbitrary order and always return correct
+results.
+
+.. code-block:: none
+
+     overlap
+     {
+       foreach i in workers1
+         (lb[i], rb[i]) <- workers1[i].produceBorders();
+       end-foreach
+       foreach i in workers1
+         workers1[i].compute(lb[i+1], rb[i-1]);
+       end-foreach
+     }
+     {
+       foreach i in workers2
+         (lb[i], rb[i]) <- workers2[i].compute(lb[i+1], rb[i-1]);
+       end-foreach
+     }
+     end-overlap
+
+This example shows an ``overlap`` statement where two blocks in curly
+brackets are executed in parallel. Their execution join back to one at
+the end mark of ``end-overlap``.
+
+:math:`\bullet` **Loop Statement**
+
+Loops are supported with ``for`` statement and ``while`` statement. Here
+are two examples.
+
+.. code-block:: none
+
+     for iter = 0 to MAX_ITER
+        workers.doWork();
+     end-for
+
+.. code-block:: none
+
+     while (err > epsilon)
+        (+err) <- workers.doWork();
+        MainChare.updateError(err);
+     end-while
+
+The loop condition in ``for`` statement is independent from the main
+program; It simply tells the program to repeat the block for so many
+times. The loop condition in ``while`` statement is actually updated in
+the MainChare. In the above example, ``err`` and ``epsilon`` are both
+member variables of class ``MainChare``, and can be updated as the
+example shows. The programmer can active the “autoScalar” feature by
+including a “``define autoScalar;``” statement in the orchestration
+code. When autoScalar is enabled, Charisma will find all the scalars in
+the ``.or`` file, and create a local copy in the ``MainChare``. Then
+every time the scalar is published by a statement, an update statement
+will automatically be inserted after that statement. The only thing that
+the programmer needs to do is to initialize the local scalar with a
+proper value.
+
+Rules of connecting produced and consumed parameters concerning loops
+are natural. The first consuming statement will look for values produced
+by the last producing statement before the loop, for the first
+iteration. The last producing statement within the loop body, for the
+following iterations. At the last iteration, the last produced values
+will be disseminated to the code segment following the loop body. Within
+the loop body, program order holds.
+
+.. code-block:: none
+
+     for iter = 1 to MAX_ITER
+       foreach i in workers
+         (lb[i], rb[i]) <- workers[i].compute(lb[i+1], rb[i-1]);
+       end-foreach
+     end-for
+
+One special case is when one statement’s produced parameter and consumed
+parameter overlaps. It must be noted that there is no dependency within
+the same ``foreach`` statement. In the above code segment, the values
+consumed ``lb[i], rb[i]`` by ``worker[i]`` will not come from its
+neighbors in this iteration. The rule is that the consumed values always
+originate from previous ``foreach`` statements or ``foreach`` statements
+from a previous loop iteration, and the published values are visible
+only to following ``foreach`` statements or ``foreach`` statements in
+following loop iterations.
+
+:math:`\bullet` **Scatter and Gather Operation**
+
+A collection of values produced by one object may be split and consumed
+by multiple object array elements for a scatter operation. Conversely, a
+collection of values from different objects can be gathered to be
+consumed by one object.
+
+.. code-block:: none
+
+     foreach i in A
+       (points[i,*]) <- A[i].f(...);
+     end-foreach
+     foreach k,j in B
+       (...) <- B[k,j].g(points[k,j]);
+     end-foreach
+
+A wildcard dimension “\*” in ``A[i].f()``\ ’s output ``points``
+specifies that it will publish multiple data items. At the consuming
+side, each ``B[k,j]`` consumes only one point in the data, and therefore
+a scatter communication will be generated from ``A`` to ``B``. For
+instance, ``A[1]`` will publish data ``points[1,0..N-1]`` to be consumed
+by multiple array objects ``B[1,0..N-1]``.
+
+.. code-block:: none
+
+     foreach i,j in A
+       (points[i,j]) <- A[i,j].f(...);
+     end-foreach
+     foreach k in B
+       (...) <- B[k].g(points[*,k]);
+     end-foreach
+
+Similar to the scatter example, if a wildcard dimension “\*” is in the
+consumed parameter and the corresponding published parameter does not
+have a wildcard dimension, there is a gather operation generated from
+the publishing statement to the consuming statement. In the following
+code segment, each ``A[i,j]`` publishes a data point, then data points
+from ``A[0..N-1,j]`` are combined together to for the data to be
+consumed by ``B[j]``.
+
+Many communication patterns can be expressed with combination of
+orchestration statements. For more details, please refer to PPL
+technical report 06-18, “Charisma: Orchestrating Migratable Parallel
+Objects”.
+
+Last but not least, all the orchestration statements in the ``.or`` file
+together form the dependency graph. According to this dependency graph,
+the messages are created and the parallel program progresses. Therefore,
+the user is advised to put only parallel constructs that are driven by
+the data dependency into the orchestration code. Other elements such as
+local dependency should be coded in the sequential code.
+
+.. _sec:sequential:
+
+Sequential Code
+---------------
+
+Sequential Files
+~~~~~~~~~~~~~~~~
+
+The programmer supplies the sequential code for each class as necessary.
+The files should be named in the form of class name with appropriate
+file extension. The header file is not really an ANSI C header file.
+Instead, it is the sequential portion of the class’s declaration.
+Charisma will generate the class declaration from the orchestration
+code, and incorporate the sequential portion in the final header file.
+For example, if a molecular dynamics simulation has the following
+classes (as declared in the orchestration code):
+
+::
+
+       class MDMain : MainChare;
+       class Cell : ChareArray3D;
+       class CellPair : ChareArray6D;
+
+The user is supposed to prepare the following sequential files for the
+classes: MDMain.h, MDMain.C, Cell.h, Cell.C, CellPair.h and CellPair.C,
+unless a class does not need sequential declaration and/or definition
+code. Please refer to the example in the Appendix.
+
+For each class, a member function “void initialize(void)” can be defined
+and the generated constructor will automatically call it. This saves the
+trouble of explicitly call initialization code for each array object.
+
+Producing and Consuming Functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The C/C++ source code is nothing different than ordinary sequential
+source code, except for the producing/consuming part. For consumed
+parameters, a function treat them just like normal parameters passed in.
+To handle produced parameters, the sequential code needs to do two
+special things. First, the function should have extra parameter for
+output parameters. The parameter type is keyword ``outport``, and the
+parameter name is the same as appeared in the orchestration code.
+Second, in the body of the function, the keyword ``produce`` is used to
+connect the orchestration parameter and the local variables whose value
+will be sent out, in a format of a function call, as follows.
+
+::
+
+       produce(produced_parameter, local_variable[, size_of_array]);
+
+When the parameter represents a data array, we need the additional
+``size_of_array`` to specify the size of the data array.
+
+The dimensionality of an orchestration parameter is divided into two
+parts: its dimension in the orchestration code, which is implied by the
+dimensionality of the object arrays the parameter is associated, and the
+local dimensionality, which is declared in the declaration section. The
+orchestration dimension is not explicitly declared anywhere, but it is
+derived from the object arrays. For instance, in the 1D Jacobi worker
+example, “lb” and “rb” has the same orchestration dimensionality of
+workers, namely 1D of size [16]. The local dimensionality is used when
+the parameter is associated with local variables in sequential code.
+Since “lb” and “rb” are declared to have the local type and dimension of
+“double [512]”, the producing statement should connect it with a local
+variable of “double [512]”.
+
+::
+
+       void JacobiWorker::produceBorders(outport lb, outport rb){
+         . . .
+         produce(lb,localLB,512);
+         produce(rb,localRB,512);
+       }
+
+Special cases of the produced/consumed parameters involve scatter/gather
+operations. In scatter operation, since an additional dimension is
+implied in the produced parameter, we the ``local_variable`` should have
+additional dimension equal to the dimension over which the scatter is
+performed. Similarly, the input parameter in gather operation will have
+an additional dimension the same size of the dimension of the gather
+operation.
+
+For reduction, one additional parameter of type char[] is added to
+specify the reduction operation. Built-in reduction operations are “+”
+(sum), “\*” (product), “:math:`<`” (minimum), “:math:`>`” (maximum) for
+basic data types. For instance the following statements takes the sum of
+all local value of ``result`` and for output in ``sum``.
+
+::
+
+       reduce(sum, result, "+");
+
+If the data type is a user-defined class, then you might use the
+function or operator defined to do the reduction. For example, assume we
+have a class called “Force”, and we have an “add” function (or a “+”
+operator) defined.
+
+::
+
+       Force& Force::add(const Force& f);
+
+In the reduction to sum all the local forces, we can use
+
+::
+
+       reduce(sumForces, localForce, "add");
+
+Miscellaneous Issues
+~~~~~~~~~~~~~~~~~~~~
+
+In sequential code, the user can access the object’s index by a keyword
+“thisIndex”. The index of 1-D to 6-D object arrays are:
+
+.. code-block:: none
+
+     1D: thisIndex
+     2D: thisIndex.{x,y}
+     3D: thisIndex.{x,y,z}
+     4D: thisIndex.{w,x,y,z}
+     5D: thisIndex.{v,w,x,y,z}
+     6D: thisIndex.{x1,y1,z1,x2,y2,z2}
+
+Building and Running a Charisma Program
+=======================================
+
+There are two steps to build a Charisma program: generating Charm++
+program from orchestration code, and building the Charm++ program.
+
+1) Charisma compiler, currently named ``orchc``, is used to compile the
+orchestration code (.or file) and integrate sequential code to generate
+a Charm++ program. The resultant Charm++ program usually consists of the
+following code files: Charm++ Interface file ([modulename].ci), header
+file ([modulename].h) and C++ source code file ([modulename].C). The
+command for this step is as follows.
+
+::
+
+       > orchc [modulename].or
+
+2) Charm++ compiler, charmc, is used to parse the Charm++ Interface
+(.ci) file, compile C/C++ code, and link and build the executable. The
+typical commands are:
+
+::
+
+       > charmc [modulename].ci
+       > charmc [modulename].C -c
+       > charmc [modulename].o -o pgm -language charm++
+
+Running the Charisma program is the same as running a Charm++ program,
+using Charm++’s job launcher ``charmrun``. (On some platforms like CSE’s
+Turing Cluster, use the customized job launcher ``rjq`` or ``rj``.)
+
+::
+
+       > charmrun pgm +p4
+
+Please refer to Charm++’s manual and tutorial for more details of
+building and running a Charm++ program.
+
+.. _secmodule:
+
+Support for Library Module
+==========================
+
+Charisma is capable of producing library code for reuse with another
+Charisma program. We explain this feature in the following section.
+
+Writing Module Library
+======================
+
+The programmer uses the keyword ``module`` instead of ``program`` in the
+header section of the orchestration code to tell the compiler that it is
+a library module. Following keyword ``module`` is the module name, then
+followed by a set of configuration variables in a pair parentheses. The
+configuration variables are used in creating instances of the library,
+for such info as problem size.
+
+Following the first line, the library’s input and output parameters are
+posted with keywords ``inparam`` and ``outparam``.
+
+.. code-block:: none
+
+     module FFT3D(CHUNK, M, N);
+     inparam indata;
+     outparam outdata1,outdata2;
+
+The body of the library is not very different from that of a normal
+program. It takes input parameters and produces out parameters, as
+posted in the header section.
+
+Using Module Library
+====================
+
+To use a Charisma module library, the programmer first needs to create
+an instance of the library. There are two steps: including the module
+and creating an instance.
+
+.. code-block:: none
+
+     use FFT3D;
+     library f1 : FFT3D(CHUNK=10,M=10,N=100);
+     library f2 : FFT3D(CHUNK=8,M=8,N=64);
+
+The keyword ``use`` and the module name includes the module in the
+program, and the keyword ``library`` creates an instance with the
+instance name, followed by the module name with value assignment of
+configuration variables. These statements must appear in the declaration
+section before the library instance can be used in the main program’s
+orchestration code.
+
+Invoking the library is like calling a publish statement; the input and
+output parameters are the same, and the object name and function name
+are replaced with the library instance name and the keyword ``call``
+connected with a colon.
+
+::
+
+     (f1_outdata[*]) <- f1:call(f1_indata[*]);
+
+Multiple instances can be created out of the same module. Their
+execution can interleave without interfering with one another.
+
+.. _secldb:
+
+Using Load Balancing Module
+===========================
+
+Coding
+------
+
+To activate load balancing module and prepare objects for migration,
+there are 3 things that needs to be added in Charisma code.
+
+First, the programmer needs to inform Charisma about the load balancing
+with a "``define ldb;``" statement in the header section of the
+orchestration code. This will make Charisma generates extra Charm++ code
+to do load balancing such as ``PUP`` methods.
+
+Second, the user has to provide a ``PUP`` function for each class with
+sequential data that needs to be moved when the object migrates. When
+choosing which data items to ``pup``, the user has the flexibility to
+leave the dead data behind to save on communication overhead in
+migration. The syntax for the sequential ``PUP`` is similar to that in a
+Charm++ program. Please refer to the load balancing section in Charm++
+manual for more information on ``PUP`` functions. A typical example
+would look like this in user’s sequential ``.C`` file:
+
+::
+
+     void JacobiWorker::sequentialPup(PUP::er& p){
+       p|myLeft; p|myRight; p|myUpper; p|myLower;
+       p|myIter;
+       PUParray(p,(double *)localData,1000);
+     }
+
+Thirdly, the user will make the call to invoke load balancing session in
+the orchestration code. The call is ``AtSync();`` and it is invoked on
+all elements in an object array. The following example shows how to
+invoke load balancing session every 4th iteration in a for-loop.
+
+.. code-block:: none
+
+     for iter = 1 to 100
+       // work work
+       if(iter % 4 == 0) then
+         foreach i in workers
+           workers[i].AtSync();
+         end-foreach
+       end-if
+     end-for
+
+If a while-loop is used instead of for-loop, then the test-condition in
+the ``if`` statement is a local variable in the program’s MainChare. In
+the sequential code, the user can maintain a local variable called
+``iter`` in MainChare and increment it every iteration.
+
+Compiling and Running
+---------------------
+
+Unless linked with load balancer modules, a Charisma program will not
+perform actual load balancing. The way to link in a load balancer module
+is adding ``-module EveryLB`` as a link-time option.
+
+At run-time, the load balancer is specified in command line after the
+``+balancer`` option. If the balancer name is incorrect, the job
+launcher will automatically print out all available load balancers. For
+instance, the following command uses ``RotateLB``.
+
+::
+
+       > ./charmrun ./pgm +p16 +balancer RotateLB
+
+.. _secsparse:
+
+Handling Sparse Object Arrays
+=============================
+
+In Charisma, when we declare an object array, by default a dense array
+is created with all the elements populated. For instance, when we have
+the following declaration in the orchestration code, an array of NxNxN
+is created.
+
+.. code-block:: none
+
+       class Cell : ChareArray3D;
+       obj cells : Cell[N,N,N];
+
+There are certain occasions when the programmer may need sparse object
+arrays, in which not all elements are created. An example is
+neighborhood force calculation in molecular dynamics application. We
+have a 3D array of Cell objects to hold the atom coordinates, and a 6D
+array of CellPair objects to perform pairwise force calculation between
+neighboring cells. In this case, not all elements in the 6D array of
+CellPair are necessary in the program. Only those which represent two
+immediately neighboring cells are needed for the force calculation. In
+this case, Charisma provides flexibility of declaring a sparse object
+array, with a ``sparse`` keyword following the object array declaration,
+as follows.
+
+.. code-block:: none
+
+       class CellPair : ChareArray6D;
+       obj cellpairs : CellPair[N,N,N,N,N,N],sparse;
+
+Then the programmer is expected to supply a sequential function with the
+name ``getIndex_ARRAYNAME`` to generate a list of selected indices of
+the elements to create. As an example, the following function
+essentially tells the system to generate all the NxNxNxNxNxN elements
+for the 6D array.
+
+::
+
+     void getIndex_cellpairs(CkVec<CkArrayIndex6D>& vec){
+       int i,j,k,l,m,n;
+       for(i=0;i<N;i++)
+         for(j=0;j<N;j++)
+           for(k=0;k<N;k++)
+             for(l=0;l<N;l++)
+               for(m=0;m<N;m++)
+                 for(n=0;n<N;n++)
+                   vec.push_back(CkArrayIndex6D(i,j,k,l,m,n));
+     }
+
+
+Example: Jacobi 1D
+==================
+
+Following is the content of the orchestration file jacobi.or.
+
+.. code-block:: none
+
+   program jacobi
+
+   class  JacobiMain : MainChare;
+   class  JacobiWorker : ChareArray1D;
+   obj  workers : JacobiWorker[M];
+   param  lb : double[N];
+   param  rb : double[N];
+
+   begin
+       for iter = 1 to MAX_ITER
+       foreach i in workers
+           (lb[i], rb[i]) <- workers[i].produceBorders();
+           workers[i].compute(lb[i+1], rb[i-1]);
+       end-foreach
+       end-for
+   end
+
+The class ``JacobiMain`` does not need any sequential code, so the only
+sequential code are in JacobiWorker.h and JacobiWorker.C. Note that
+JacobiWorker.h contains only the sequential portion of JacobiWorker’s
+declaration.
+
+::
+
+   #define N 512
+   #define M 16
+
+   int currentArray;
+   double localData[2][M][N];
+   double localLB[N];
+   double localRB[N];
+   int myLeft,myRight,myUpper,myLower;
+
+   void initialize();
+   void compute(double lghost[], double rghost[]);
+   void produceBorders(outport lb,outport rb);
+   double abs(double d);
+
+Similarly, the sequential C code will be integrated into the generated C
+file. Below is part of the sequential C code taken from JacobiWorker.C
+to show how consumed parameters (``rghost`` and ``lghost`` in
+``JacobiWorker::compute``) and produced parameters (``lb`` and ``rb`` in
+``JacobiWorker::produceBorders``) are handled.
+
+::
+
+   void JacobiWorker::compute(double rghost[], double lghost[]){
+       /* local computation for updating elements*/
+   }
+
+   void JacobiWorker::produceBorders(outport lb, outport rb){
+       produce(lb,localData[currentArray][myLeft],myLower-myUpper+1);
+       produce(rb,localData[currentArray][myRight],myLower-myUpper+1);
+   }
+
+The user compile these input files with the following command:
+
+::
+
+     > orchc jacobi.or
+
+The compiler generates the parallel code for sending out messages,
+organizing flow of control, and then it looks for sequential code files
+for the classes declared, namely ``JacobiMain`` and ``JacobiWorker``,
+and integrates them into the final output: ``jacobi.h``, ``jacobi.C``
+and ``jacobi.ci``, which is a Charm++ program and can be built the way a
+Charm++ program is built.
diff --git a/doc/charj/manual.rst b/doc/charj/manual.rst
new file mode 100644 (file)
index 0000000..aa5a337
--- /dev/null
@@ -0,0 +1,171 @@
+=======================================================================
+Charj Manual Compiler Support for Productive Parallel Programming  [1]_
+=======================================================================
+
+.. contents::
+   :depth: 3
+
+Introduction
+============
+
+Charj is a new programming language which incorporates syntax, semantic
+analysis, and optimization targeted at HPC code with its associated
+compiler.
+
+.. figure:: fig/fig0.png
+   :name: fig:fig0
+   :width: 4in
+
+   Charj
+
+With Charj, we aim to allow programmers to achieve the performance
+associated with carefully written, hand-optimized Charm++ applications,
+but with much less time and effort. If effect, we hope to combine the
+productivity that programmers experience when writing relatively simple,
+naive applications while enjoying performance that would normally
+require a much greater investment of time, effort, and expertise.
+
+Charj compiler takes Charj codes as input and produces Charm++ interface
+(.ci) and C++ code (.C and .h) as an output.
+
+.. figure:: fig/fig1.png
+   :name: fig:fig1
+   :width: 4in
+
+   Compilation process for Charj application
+
+
+To make use of Charj;
+
+#. Build Charm++, then build Charj
+
+#. Write your Charj program
+
+#. Compile and run it!
+
+Building, Compiling and Running
+===============================
+
+**To write a program and compile with Charj:**
+
+#. Go to: *charm/src/langs/charj* and *"make"* (Assuming Charm++ is
+   already installed)
+
+#. Write your Charj code in a file with *.cj* extension.
+   *(SampleProgram.cj)*
+
+#. | Execute *charjc* script on the file *SampleProgram.cj*:
+   | *$ charm/src/langs/charj/bin/charjc SampleProgram.cj*
+   | For other compiler options, use help:
+   | *$ charm/src/langs/bin/charjc -h*
+
+#. After execution of *charjc* script, a folder named
+   *“SampleProgram.cj.gen”* will be created in the directory of
+   *SampleProgram.cj*. This folder will contain the emitted Charm++
+   files; *SampleProgram.ci, SampleProgram.h SampleProgram.cc* .
+
+   \* Example Charj programs can be found at
+   *charm/src/langs/charj/tests*
+
+Writing a Charj Program
+=======================
+
+General structure of a Charj program;
+--------------------------------------
+
+.. code-block:: none
+
+
+       readonly Main@ mainProxy;   //readonly proxy type
+       readonly int value;         //readonly variable
+
+       public mainchare Main {
+           public entry Main(CkArgMsg[~]@ m){...}  //Main constructor
+           public entry void done(){...}               //entry method
+           private int localMethod(int value){...}     //non-entry method
+       }
+       public chare_array [1d] SampleChareArray1d{...} //1d chare array
+       public chare_array [2d] SampleChareArray2d{...} //2d chare array
+
+       public class SampleObject{...}                  //sample class
+
+       public chare SampleChare {
+           public entry SampleChare(){...}             //constructor
+           public entry SampleChare(boolean flag){...} //constructor 2
+           public entry void test(SampleObject obj){...}   //entry method
+       }
+
+Chare creation and method calls:
+---------------------------------
+
+.. code-block:: none
+
+       SampleChare@ sp = new SampleChare@();
+       SampleChareArray1d@ sp1 = new SampleChareArray1d@(x_dim);
+       SampleChareArray2d@ sp2 = new SampleChareArray2d@(x_dim, y_dim);
+       sp@test();
+       sp1@test();
+       sp1[index]@test();
+       sp2@test(int value);
+
+Arrays:
+-------
+
+.. code-block:: none
+
+       Array<int> foo = new Array<int>([10]);  //1d array of integers of size 10
+       foo[i] = ...;
+       Array<double, 2> foo2 = new Array<double, 2>([s1, s2]); //2d array of size s1, s2
+       foo2[i, j] = ...;
+
+SDAG statements:
+----------------
+
+These statements can be used inside of any entry method.
+
+::
+
+       when receiveMsg(SampleObject obj) {...}
+
+       overlap{    //two overlapping when statements
+           when receiveMsg1[i](int iter, SampleObject obj) {...}
+           when receiveMsg2[i](int iter, int value) {...}
+       }
+
+Extern statements:
+-------------------
+
+If you want to use any other C++ function/feature, you have to define it
+as *extern*.
+
+::
+
+       extern atoi;            //define in the beginning of the file
+       int x = atoi(y);        //use anywhere
+
+Reduction statements:
+---------------------
+
+Currently only plain reductions are supported.
+
+::
+
+       contribute(CkCallback(CkReductionTarget(Main, done), mainProxy));
+
+Some Charm++ statements that can be used in a Charj program:
+------------------------------------------------------------
+
+::
+
+       CkExit();
+       CkPrintf();
+       CkMyPe();
+       CkNumPes();
+       CkMyNode();
+       CkNumNodes();
+       CkWallTimer();
+       thisProxy
+       thisIndex
+
+.. [1]
+   last modified 12/14/2012 by Bilge Acun
diff --git a/doc/charm++/manual.rst b/doc/charm++/manual.rst
new file mode 100644 (file)
index 0000000..41dbca2
--- /dev/null
@@ -0,0 +1,11983 @@
+==============================================
+The Charm++ Parallel Programming System Manual
+==============================================
+
+.. contents::
+   :depth: 3
+
+
+Basic Concepts
+==============
+
+Charm++ is a C++-based parallel programming system, founded on the
+migratable-objects programming model, and supported by a novel and
+powerful adaptive runtime system. It supports both irregular as well as
+regular applications, and can be used to specify task-parallelism as
+well as data parallelism in a single application. It automates dynamic
+load balancing for task-parallel as well as data-parallel applications,
+via separate suites of load-balancing strategies. Via its message-driven
+execution model, it supports automatic latency tolerance, modularity and
+parallel composition. Charm++ also supports automatic
+checkpoint/restart, as well as fault tolerance based on distributed
+checkpoints.
+
+Charm++ is a production-quality parallel programming system used by
+multiple applications in science and engineering on supercomputers as
+well as smaller clusters around the world. Currently the parallel
+platforms supported by Charm++ are the IBM BlueGene/Q and OpenPOWER
+systems, Cray XE, XK, and XC systems, Omni-Path and Infiniband clusters,
+single workstations and networks of workstations (including x86 (running
+Linux, Windows, MacOS)), etc. The communication protocols and
+infrastructures supported by Charm++ are UDP, MPI, OFI, Infiniband,
+uGNI, and PAMI. Charm++ programs can run without changing the source on
+all these platforms. Charm++ programs can also interoperate with MPI
+programs (§ :numref:`sec:interop`). Please see the Installation and Usage
+section for details about installing, compiling and running Charm++
+programs (§ :numref:`sec:install`).
+
+Programming Model
+-----------------
+
+The key feature of the migratable-objects programming model is
+*over-decomposition*: The programmer decomposes the program into a large
+number of work units and data units, and specifies the computation in
+terms of creation of and interactions between these units, without any
+direct reference to the processor on which any unit resides. This
+empowers the runtime system to assign units to processors, and to change
+the assignment at runtime as necessary. Charm++ is the main (and early)
+exemplar of this programming model. AMPI is another example within the
+Charm++ family of the same model.
+
+Execution Model
+---------------
+
+A basic unit of parallel computation in Charm++ programs is a *chare* .
+A chare is similar to a process, an actor, an ADA task, etc. At its most
+basic level, it is just a C++ object. A Charm++ computation consists of
+a large number of chares distributed on available processors of the
+system, and interacting with each other via asynchronous method
+invocations. Asynchronously invoking a method on a remote object can
+also be thought of as sending a “message” to it. So, these method
+invocations are sometimes referred to as messages. (besides, in the
+implementation, the method invocations are packaged as messages anyway).
+Chares can be created dynamically.
+
+Conceptually, the system maintains a “work-pool” consisting of seeds for
+new chares, and messages for existing chares. The Charm++ runtime system
+( *Charm RTS*) may pick multiple items, non-deterministically, from this
+pool and execute them, with the proviso that two different methods
+cannot be simultaneously executing on the same chare object (say, on
+different processors). Although one can define a reasonable theoretical
+operational semantics of Charm++ in this fashion, a more practical
+description of execution is useful to understand Charm++. A Charm++
+application’s execution is distributed among Processing Elements (PEs),
+which are OS threads or processes depending on the selected Charm++
+build options. (See section :numref:`sec:machine` for a
+precise description.) On each PE, there is a scheduler operating with
+its own private pool of messages. Each instantiated chare has one PE
+which is where it currently resides. The pool on each PE includes
+messages meant for Chares residing on that PE, and seeds for new Chares
+that are tentatively meant to be instantiated on that PE. The scheduler
+picks a message, creates a new chare if the message is a seed (i.e. a
+constructor invocation) for a new Chare, and invokes the method
+specified by the message. When the method returns control back to the
+scheduler, it repeats the cycle. I.e. there is no pre-emptive scheduling
+of other invocations.
+
+When a chare method executes, it may create method invocations for other
+chares. The Charm Runtime System (RTS, sometimes referred to as the
+Chare Kernel in the manual) locates the PE where the targeted chare
+resides, and delivers the invocation to the scheduler on that PE.
+
+Methods of a chare that can be remotely invoked are called *entry*
+methods. Entry methods may take serializable parameters, or a pointer to
+a message object. Since chares can be created on remote processors,
+obviously some constructor of a chare needs to be an entry method.
+Ordinary entry methods [1]_ are completely non-preemptive- Charm++ will
+not interrupt an executing method to start any other work, and all calls
+made are asynchronous.
+
+Charm++ provides dynamic seed-based load balancing. Thus location
+(processor number) need not be specified while creating a remote chare.
+The Charm RTS will then place the remote chare on a suitable processor.
+Thus one can imagine chare creation as generating only a seed for the
+new chare, which may *take root* on some specific processor at a later
+time.
+
+Chares can be grouped into collections. The types of collections of
+chares supported in Charm++ are: *chare-arrays*, *chare-groups*, and
+*chare-nodegroups*, referred to as *arrays*, *groups*, and *nodegroups*
+throughout this manual for brevity. A Chare-array is a collection of an
+arbitrary number of migratable chares, indexed by some index type, and
+mapped to processors according to a user-defined map group. A group
+(nodegroup) is a collection of chares, with exactly one member element
+on each PE (“node”).
+
+Charm++ does not allow global variables, except readonly variables (see
+:numref:`readonly`). A chare can normally only access its own data
+directly. However, each chare is accessible by a globally valid name.
+So, one can think of Charm++ as supporting a *global object space*.
+
+Every Charm++ program must have at least one mainchare. Each mainchare
+is created by the system on processor 0 when the Charm++ program starts
+up. Execution of a Charm++ program begins with the Charm Kernel
+constructing all the designated mainchares. For a mainchare named X,
+execution starts at constructor X() or X(CkArgMsg \*) which are
+equivalent. Typically, the mainchare constructor starts the computation
+by creating arrays, other chares, and groups. It can also be used to
+initialize shared readonly objects.
+
+Charm++ program execution is terminated by the CkExit call. Like the
+exit system call, CkExit never returns, and it optionally accepts an
+integer value to specify the exit code that is returned to the calling
+shell. If no exit code is specified, a value of zero (indicating
+successful execution) is returned. The Charm RTS ensures that no more
+messages are processed and no entry methods are called after a CkExit.
+CkExit need not be called on all processors; it is enough to call it
+from just one processor at the end of the computation.
+
+As described so far, the execution of individual Chares is “reactive”:
+When method A is invoked the chare executes this code, and so on. But
+very often, chares have specific life-cycles, and the sequence of entry
+methods they execute can be specified in a structured manner, while
+allowing for some localized non-determinism (e.g. a pair of methods may
+execute in any order, but when they both finish, the execution continues
+in a pre-determined manner, say executing a 3rd entry method). To
+simplify expression of such control structures, Charm++ provides two
+methods: the structured dagger notation (Sec :numref:`sec:sdag`), which
+is the main notation we recommend you use. Alternatively, you may use
+threaded entry methods, in combination with *futures* and *sync* methods
+(See :numref:`threaded`). The threaded methods run in light-weight
+user-level threads, and can block waiting for data in a variety of ways.
+Again, only the particular thread of a particular chare is blocked,
+while the PE continues executing other chares.
+
+The normal entry methods, being asynchronous, are not allowed to return
+any value, and are declared with a void return type. However, the *sync*
+methods are an exception to this. They must be called from a threaded
+method, and so are allowed to return (certain types of) values.
+
+.. _proxies:
+
+Proxies and the charm interface file
+------------------------------------
+
+To support asynchronous method invocation and global object space, the
+RTS needs to be able to serialize (“marshall”) the parameters, and be
+able to generate global “names” for chares. For this purpose,
+programmers have to declare the chare classes and the signature of their
+entry methods in a special “``.ci``” file, called an interface file.
+Other than the interface file, the rest of a Charm++ program consists of
+just normal C++ code. The system generates several classes based on the
+declarations in the interface file, including “Proxy” classes for each
+chare class. Those familiar with various component models (such as
+CORBA) in the distributed computing world will recognize “proxy” to be a
+dummy, standin entity that refers to an actual entity. For each chare
+type, a “proxy” class exists. The methods of this “proxy” class
+correspond to the remote methods of the actual class, and act as
+“forwarders”. That is, when one invokes a method on a proxy to a remote
+object, the proxy marshalls the parameters into a message, puts adequate
+information about the target chare on the envelope of the message, and
+forwards it to the remote object. Individual chares, chare array,
+groups, node-groups, as well as the individual elements of these
+collections have a such a proxy. Multiple methods for obtaining such
+proxies are described in the manual. Proxies for each type of entity in
+Charm++ have some differences among the features they support, but the
+basic syntax and semantics remain the same - that of invoking methods on
+the remote object by invoking methods on proxies.
+
+The following sections provide detailed information about various
+features of the Charm++ programming system. Part I, “Basic Usage”, is
+sufficient for writing full-fledged applications. Note that only the
+last two chapters of this part involve the notion of physical processors
+(cores, nodes, ..), with the exception of simple query-type utilities
+(Sec :numref:`basic utility fns`). We strongly suggest that all
+application developers, beginners and experts alike, try to stick to the
+basic language to the extent possible, and use features from the
+advanced sections only when you are convinced they are essential. (They
+are useful in specific situations; but a common mistake we see when we
+examine programs written by beginners is the inclusion of complex
+features that are not necessary for their purpose. Hence the caution).
+The advanced concepts in the Part II of the manual support
+optimizations, convenience features, and more complex or sophisticated
+features.  [2]_
+
+.. _machineModel:
+.. _sec:machine:
+
+Machine Model
+-------------
+
+At its basic level, Charm++ machine model is very simple:
+Think of each chare as a separate processor by itself. The methods of
+each chare can access its own instance variables (which are all private,
+at this level), and any global variables declared as *readonly*. It also
+has access to the names of all other chares (the “global object space”),
+but all that it can do with that is to send asynchronous remote method
+invocations towards other chare objects. (Of course, the instance
+variables can include as many other regular C++ objects that it “has”;
+but no chare objects. It can only have references to other chare
+objects).
+
+In accordance with this vision, the first part of the manual (up to and
+including the chapter on load balancing) has almost no mention of
+entities with physical meanings (cores, nodes, etc.). The runtime system
+is responsible for the magic of keeping closely communicating objects on
+nearby physical locations, and optimizing communications within chares
+on the same node or core by exploiting the physically available shared
+memory. The programmer does not have to deal with this at all. The only
+exception to this pure model in the basic part are the functions used
+for finding out which “processor” an object is running on, and for
+finding how many total processors are there.
+
+However, for implementing lower level libraries, and certain
+optimizations, programmers need to be aware of processors. In any case,
+it is useful to understand how the Charm++ implementation works under
+the hood. So, we describe the machine model, and some associated
+terminology here.
+
+In terms of physical resources, we assume the parallel machine consists
+of one or more *nodes*, where a node is a largest unit over which cache
+coherent shared memory is feasible (and therefore, the maximal set of
+cores per which a single process *can* run. Each node may include one or
+more processor chips, with shared or private caches between them. Each
+chip may contain multiple cores, and each core may support multiple
+hardware threads (SMT for example).
+
+Charm++ recognizes two logical entities: a PE (processing element) and a
+logical node, or simply “node”. In a Charm++ program, a PE is a unit of
+mapping and scheduling: each PE has a scheduler with an associated pool
+of messages. Each chare is assumed to reside on one PE at a time. A
+logical node is implemented as an OS process. In non-SMP mode there is
+no distinction between a PE and a logical node. Otherwise, a PE takes
+the form of an OS thread, and a logical node may contain one or more
+PEs. Physical nodes may be partitioned into one or more logical nodes.
+Since PEs within a logical node share the same memory address space, the
+Charm++ runtime system optimizes communication between them by using
+shared memory. Depending on the runtime command-line parameters, a PE
+may optionally be associated with a subset of cores or hardware threads.
+
+A Charm++ program can be launched with one or more (logical) nodes per
+physical node. For example, on a machine with a four-core processor,
+where each core has two hardware threads, common configurations in
+non-SMP mode would be one node per core (four nodes/PEs total) or one
+node per hardware thread (eight nodes/PEs total). In SMP mode, the most
+common choice to fully subscribe the physical node would be one logical
+node containing *seven* PEs-one OS thread is set aside per process for
+network communications. (When built in the “multicore” mode that lacks
+network support, a comm thread is unnecessary, and eight PEs can be used
+in this case. A comm thread is also omitted when using some
+high-performance network layers such as PAMI.) Alternatively, one can
+choose to partition the physical node into multiple logical nodes, each
+containing multiple PEs. One example would be *three* PEs per logical
+node and two logical nodes per physical node, again reserving a comm
+thread per logical node.
+
+It is not a general practice in Charm++ to oversubscribe the underlying
+physical cores or hardware threads on each node. In other words, a
+Charm++ program is usually not launched with more PEs than there are
+physical cores or hardware threads allocated to it. More information
+about these launch time options are provided in
+Appendix :numref:`sec:run`. And utility functions to retrieve the
+information about those Charm++ logical machine entities in user
+programs can be referred in section :numref:`basic utility fns`.
+
+Basic Charm++ Programming
+=========================
+
+Program Structure, Compilation and Utilities
+--------------------------------------------
+
+A Charm++ program is essentially a C++ program where some components
+describe its parallel structure. Sequential code can be written using
+any programming technologies that cooperate with the C++ toolchain. This
+includes C and Fortran. Parallel entities in the user’s code are written
+in C++. These entities interact with the Charm++ framework via inherited
+classes and function calls.
+
+Charm++ Interface (.ci) Files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All user program components that comprise its parallel interface (such
+as messages, chares, entry methods, etc.) are granted this elevated
+status by declaring them in separate *charm++ interface* description
+files. These files have a *.ci* suffix and adopt a C++-like declaration
+syntax with several additional keywords. In some declaration contexts,
+they may also contain some sequential C++ source code. Charm++ parses
+these interface descriptions and generates C++ code (base classes, utility
+classes, wrapper functions etc.) that facilitates the interaction of the
+user program’s entities with the framework. A program may have several
+interface description files.
+
+Syntax Highlighting of .ci Files
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Vim
+'''
+
+To enable syntax highlighting of .ci files in Vim, do the following:
+
+.. code-block:: bash
+
+   $ cp charm/contrib/ci.vim ~/.vim/syntax/.
+   $ vim ~/.vim/filetype.vim
+
+And paste the following line in that file:
+
+.. code-block:: vim
+
+   au! BufRead,BufNewFile *.ci set filetype=ci
+
+Sublime Text
+''''''''''''
+
+Syntax highlighting in Sublime Text (version 3 or newer) can be enabled
+by installing the *Charmci* package through Package Control.
+
+Modules
+~~~~~~~
+
+The top-level construct in a *ci* file is a named container for
+interface declarations called a module. Modules allow related
+declarations to be grouped together, and cause generated code for these
+declarations to be grouped into files named after the module. Modules
+cannot be nested, but each *ci* file can have several modules. Modules
+are specified using the keyword module. A module name must be a valid
+C++ identifier.
+
+::
+
+   module myFirstModule {
+       // Parallel interface declarations go here
+       ...
+   };
+
+Generated Files
+~~~~~~~~~~~~~~~
+
+Each module present in a *ci* file is parsed to generate two files. The
+basename of these files is the same as the name of the module and their
+suffixes are *.decl.h* and *.def.h*. For e.g., the module defined
+earlier will produce the files “myFirstModule.decl.h” and
+“myFirstModule.def.h”. As the suffixes indicate, they contain the
+declarations and definitions respectively, of all the classes and
+functions that are generated based on the parallel interface
+description.
+
+We recommend that the header file containing the declarations (decl.h)
+be included at the top of the files that contain the declarations or
+definitions of the user program entities mentioned in the corresponding
+module. The def.h is not actually a header file because it contains
+definitions for the generated entities. To avoid multiple definition
+errors, it should be compiled into just one object file. A convention we
+find useful is to place the def.h file at the bottom of the source file
+(.C, .cpp, .cc etc.) which includes the definitions of the corresponding
+user program entities.
+
+It should be noted that the generated files have no dependence on the
+name of the *ci* file, but only on the names of the modules. This can
+make automated dependency-based build systems slightly more complicated.
+We adopt some conventions to ease this process. This is described
+in :numref:`AppendixSectionDescribingPhilRamsWorkOnCi.stampAndCharmc-M`.
+
+Module Dependencies
+~~~~~~~~~~~~~~~~~~~
+
+A module may depend on the parallel entities declared in another module.
+It can express this dependency using the extern keyword. externed
+modules do not have to be present in the same *ci* file.
+
+::
+
+   module mySecondModule {
+
+       // Entities in this module depend on those declared in another module
+       extern module myFirstModule;
+
+       // More parallel interface declarations
+       ...
+   };
+
+The extern keyword places an include statement for the decl.h file of
+the externed module in the generated code of the current module. Hence,
+decl.h files generated from externed modules are required during the
+compilation of the source code for the current module. This is usually
+required anyway because of the dependencies between user program
+entities across the two modules.
+
+The Main Module and Reachable Modules
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Charm++ software can contain several module definitions from several
+independently developed libraries / components. However, the user
+program must specify exactly one module as containing the starting point
+of the program’s execution. This module is called the mainmodule. Every
+Charm++ program has to contain precisely one mainmodule.
+
+All modules that are “reachable” from the mainmodule via a chain of
+externed module dependencies are included in a Charm++ program. More
+precisely, during program execution, the Charm++ runtime system will
+recognize only the user program entities that are declared in reachable
+modules. The decl.h and def.h files may be generated for other modules,
+but the runtime system is not aware of entities declared in such
+unreachable modules.
+
+::
+
+   module A {
+       ...
+   };
+
+   module B {
+       extern module A;
+       ...
+   };
+
+   module C {
+       extern module A;
+       ...
+   };
+
+   module D {
+       extern module B;
+       ...
+   };
+
+   module E {
+       ...
+   };
+
+   mainmodule M {
+       extern module C;
+       extern module D;
+       // Only modules A, B, C and D are reachable and known to the runtime system
+       // Module E is unreachable via any chain of externed modules
+       ...
+   };
+
+Including other headers
+~~~~~~~~~~~~~~~~~~~~~~~
+
+There can be occasions where code generated from the module definitions
+requires other declarations / definitions in the user program’s
+sequential code. Usually, this can be achieved by placing such user code
+before the point of inclusion of the decl.h file. However, this can
+become laborious if the decl.h file has to included in several places.
+Charm++ supports the keyword include in *ci* files to permit the
+inclusion of any header directly into the generated decl.h files.
+
+::
+
+   module A {
+       include "myUtilityClass.h"; //< Note the semicolon
+       // Interface declarations that depend on myUtilityClass
+       ...
+   };
+
+   module B {
+       include "someUserTypedefs.h";
+       // Interface declarations that require user typedefs
+       ...
+   };
+
+   module C {
+       extern module A;
+       extern module B;
+       // The user includes will be indirectly visible here too
+       ...
+   };
+
+The main() function
+~~~~~~~~~~~~~~~~~~~
+
+The Charm++ framework implements its own main function and
+retains control until the parallel execution environment is initialized
+and ready for executing user code. Hence, the user program must not
+define a *main()* function. Control enters the user code via the
+mainchare of the mainmodule. This will be discussed in further detail
+in :numref:`mainchare`.
+
+Using the facilities described thus far, the parallel interface
+declarations for a Charm++ program can be spread across multiple ci
+files and multiple modules, permitting good control over the grouping
+and export of parallel API. This aids the encapsulation of parallel
+software.
+
+Compiling Charm++ Programs
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Charm++ provides a compiler-wrapper called charmc that handles all *ci*,
+C, C++ and Fortran source files that are part of a user program. Users can
+invoke charmc to parse their interface descriptions, compile source code
+and link objects into binaries. It also links against the appropriate
+set of charm framework objects and libraries while producing a binary.
+charmc and its functionality is described in :numref:`sec:compile`.
+
+.. _basic utility fns:
+
+Utility Functions
+~~~~~~~~~~~~~~~~~
+
+The following calls provide basic rank information and utilities useful
+when running a Charm++ program.
+
+void CkAssert(int expression) Aborts the program if expression is 0.
+
+void CkAbort(const char \*message) Causes the program to abort, printing
+the given error message. This function never returns.
+
+void CkExit() This call informs the Charm RTS that computation on all
+processors should terminate. This routine never returns, so any code
+after the call to CkExit() inside the function that calls it will not
+execute. Other processors will continue executing until they receive
+notification to stop, so it is a good idea to ensure through
+synchronization that all useful work has finished before calling
+CkExit().
+
+double CkWallTimer()
+
+Information about Logical Machine Entities
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+As described in section :numref:`machineModel`, Charm++ recognizes
+two logical machine entities: “node” and PE (processing element). The
+following functions provide basic information about such logical machine
+that a Charm++ program runs on. PE and “node” are numbered starting from
+zero.
+
+``int CkNumPes()`` returns the total number of PEs across all nodes.
+
+``int CkMyPe()`` returns the index of the PE on which the call was made.
+
+``int CkNumNodes()`` returns the total number of logical Charm++ nodes.
+
+``int CkMyNode()`` returns the index of the “node” on which the call was
+made.
+
+``int CkMyRank()`` returns the rank number of the PE on a “node” on which
+the call was made. PEs within a “node” are also ranked starting from
+zero.
+
+``int CkNodeFirst(int nd)`` returns the index of the first PE on the logical
+node :math:`nd`.
+
+``int CkNodeSize(int nd)`` returns the number of PEs on the logical node
+:math:`nd` on which the call was made.
+
+``int CkNodeOf(int pe)`` returns the “node” number that PE :math:`pe`
+belongs to.
+
+``int CkRankOf(int pe)`` returns the rank of the given PE within its node.
+
+Terminal I/O
+^^^^^^^^^^^^
+
+Charm++ provides both C and C++ style methods of doing terminal I/O.
+
+In place of C-style printf and scanf, Charm++ provides CkPrintf and
+CkScanf. These functions have interfaces that are identical to their C
+counterparts, but there are some differences in their behavior that
+should be mentioned.
+
+Charm++ also supports all forms of printf, cout, etc. in addition to the
+special forms shown below. The special forms below are still useful,
+however, since they obey well-defined (but still lax) ordering
+requirements.
+
+``int CkPrintf(format [, arg]*)`` This call is used for atomic terminal
+output. Its usage is similar to ``printf`` in C. However, CkPrintf has
+some special properties that make it more suited for parallel
+programming. CkPrintf routes all terminal output to a single end point
+which prints the output. This guarantees that the output for a single
+call to CkPrintf will be printed completely without being interleaved
+with other calls to CkPrintf. Note that CkPrintf is implemented using an
+asynchronous send, meaning that the call to CkPrintf returns immediately
+after the message has been sent, and most likely before the message has
+actually been received, processed, and displayed. As such, there is no
+guarantee of order in which the output for concurrent calls to CkPrintf
+is printed. Imposing such an order requires proper synchronization
+between the calls to CkPrintf in the parallel application.
+
+``void CkError(format [, arg]*))``
+Like CkPrintf, but used to print error messages on stderr.
+
+``int CkScanf(format [, arg]*)``
+This call is used for atomic terminal input. Its usage is similar to scanf in C. A call to CkScanf, unlike CkPrintf, blocks all execution on the processor it is called from, and returns only after all input has been retrieved.
+
+For C++ style stream-based I/O, Charm++ offers ``ckout`` and ``ckerr`` in place of
+``cout`` and ``cerr``. The C++ streams and their Charm++ equivalents are related
+in the same manner as printf and scanf are to ``CkPrintf`` and ``CkScanf``. The
+Charm++ streams are all used through the same interface as the
+C++ streams, and all behave in a slightly different way, just like C-style
+I/O.
+
+Basic Syntax
+------------
+
+.. _entry:
+
+Entry Methods
+~~~~~~~~~~~~~
+
+Member functions in the user program which function as entry methods
+have to be defined in public scope within the class definition. Entry
+methods typically do not return data and have a “void” return type. An
+entry method with the same name as its enclosing class is a constructor
+entry method and is used to create or spawn chare objects during
+execution. Class member functions are annotated as entry methods by
+declaring them in the interface file as:
+
+::
+
+   entry void Entry1(parameters);
+
+Parameters is either a list of serializable parameters, (e.g., “int i,
+double x”), or a message type (e.g., “MyMessage \*msg”). Since
+parameters get marshalled into a message before being sent across the
+network, in this manual we use “message” to mean either a message type
+or a set of marshalled parameters.
+
+Messages are lower level, more efficient, more flexible to use than
+parameter marshalling.
+
+For example, a chare could have this entry method declaration in the
+interface (``.ci``) file:
+
+::
+
+     entry void foo(int i,int k);
+
+Then invoking foo(2,3) on the chare proxy will eventually invoke
+foo(2,3) on the chare object.
+
+Since Charm++ runs on distributed memory machines, we cannot pass an
+array via a pointer in the usual C++ way. Instead, we must specify the
+length of the array in the interface file, as:
+
+::
+
+     entry void bar(int n,double arr[n]);
+
+Since C++ does not recognize this syntax, the array data must be passed to
+the chare proxy as a simple pointer. The array data will be copied and
+sent to the destination processor, where the chare will receive the copy
+via a simple pointer again. The remote copy of the data will be kept
+until the remote method returns, when it will be freed. This means any
+modifications made locally after the call will not be seen by the remote
+chare; and the remote chare’s modifications will be lost after the
+remote method returns- Charm++ always uses call-by-value, even for
+arrays and structures.
+
+This also means the data must be copied on the sending side, and to be
+kept must be copied again at the receive side. Especially for large
+arrays, this is less efficient than messages, as described in the next
+section.
+
+Array parameters and other parameters can be combined in arbitrary ways,
+as:
+
+::
+
+     entry void doLine(float data[n],int n);
+     entry void doPlane(float data[n*n],int n);
+     entry void doSpace(int n,int m,int o,float data[n*m*o]);
+     entry void doGeneral(int nd,int dims[nd],float data[product(dims,nd)]);
+
+The array length expression between the square brackets can be any valid
+C++ expression, including a fixed constant, and may depend in any manner
+on any of the passed parameters or even on global functions or global
+data. The array length expression is evaluated exactly once per
+invocation, on the sending side only. Thus executing the doGeneral
+method above will invoke the (user-defined) product function exactly
+once on the sending processor.
+
+Marshalling User-Defined Structures and Classes
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The marshalling system uses the pup framework to copy data, meaning
+every user class that is marshalled needs either a pup routine, a
+“PUPbytes” declaration, or a working operator|. See the PUP description
+in Section :numref:`sec:pup` for more details on these
+routines.
+
+Any user-defined types in the argument list must be declared before
+including the “.decl.h” file. Any user-defined types must be fully
+defined before the entry method declaration that consumes it. This is
+typically done by including the header defining the type in the ``.ci``
+file. Alternatively, one may define it before including the ``.decl.h``
+file. As usual in C, it is often dramatically more efficient to pass a
+large structure by reference than by value.
+
+As an example, refer to the following code from
+``examples/charm++/PUP/HeapPUP``:
+
+::
+
+   // In HeapObject.h:
+
+   class HeapObject {
+    public:
+     int publicInt;
+
+     // ... other methods ...
+
+     void pup(PUP::er &p) {
+       // remember to pup your superclass if there is one
+       p|publicInt;
+       p|privateBool;
+       if (p.isUnpacking())
+         data = new float[publicInt];
+       PUParray(p, data, publicInt);
+     }
+
+    private:
+     bool privateBool;
+     float *data;
+   };
+
+   // In SimplePup.ci:
+
+   mainmodule SimplePUP {
+     include "HeapObject.h";
+
+     // ... other Chare declarations ...
+
+     array [1D] SimpleArray{
+       entry SimpleArray();
+       entry void acceptData(HeapObject &inData);
+     };
+   };
+
+   // In SimplePup.h:
+
+   #include "SimplePUP.decl.h"
+
+   // ... other definitions ...
+
+   class SimpleArray : public CBase_SimpleArray {
+    public:
+     void acceptData(HeapObject &inData) {
+       // ... code using marshalled parameter ...
+     }
+   };
+
+   // In SimplePup.C:
+
+   #include "SimplePUP.h"
+
+   main::main(CkArgMsg *m)
+   {
+     // normal object construction
+     HeapObject exampleObject(... parameters ...);
+
+     // normal chare array construction
+     CProxy_SimpleArray simpleProxy = CProxy_SimpleArray::ckNew(30);
+
+     // pass object to remote method invocation on the chare array
+     simpleProxy[29].acceptData(exampleObject);
+   }
+
+   #include "SimplePUP.def.h"
+
+Chare Objects
+~~~~~~~~~~~~~
+
+Chares are concurrent objects with methods that can be invoked remotely.
+These methods are known as entry methods. All chares must have a
+constructor that is an entry method, and may have any number of other
+entry methods. All chare classes and their entry methods are declared in
+the interface (``.ci``) file:
+
+::
+
+       chare ChareType
+       {
+           entry ChareType(parameters1);
+           entry void EntryMethodName(parameters2);
+       };
+
+Although it is *declared* in an interface file, a chare is a C++ object
+and must have a normal C++ *implementation* (definition) in addition. A
+chare class ``ChareType`` must inherit from the class
+``CBase_ChareType``, which is a special class that is generated by the
+Charm++ translator from the interface file. Note that C++ namespace
+constructs can be used in the interface file, as demonstrated in
+``examples/charm++/namespace``.
+
+To be concrete, the C++ definition of the chare above might have the
+following definition in a ``.h`` file:
+
+::
+
+      class ChareType : public CBase_ChareType {
+          // Data and member functions as in C++
+          public:
+              ChareType(parameters1);
+              void EntryMethodName2(parameters2);
+      };
+
+Each chare encapsulates data associated with medium-grained units of
+work in a parallel application. Chares can be dynamically created on any
+processor; there may be thousands of chares on a processor. The location
+of a chare is usually determined by the dynamic load balancing strategy.
+However, once a chare commences execution on a processor, it does not
+migrate to other processors [3]_. Chares do not have a default “thread
+of control”: the entry methods in a chare execute in a message driven
+fashion upon the arrival of a message [4]_.
+
+The entry method definition specifies a function that is executed
+*without interruption* when a message is received and scheduled for
+processing. Only one message per chare is processed at a time. Entry
+methods are defined exactly as normal C++ function members, except that
+they must have the return value void (except for the constructor entry
+method which may not have a return value, and for a *synchronous* entry
+method, which is invoked by a *threaded* method in a remote chare). Each
+entry method can either take no arguments, take a list of arguments that
+the runtime system can automatically pack into a message and send (see
+section :numref:`entry`), or take a single argument that is a pointer
+to a Charm++ message (see section :numref:`messages`).
+
+A chare’s entry methods can be invoked via *proxies* (see
+section :numref:`proxies`). Proxies to a chare of type ``chareType``
+have type ``CProxy_chareType``. By inheriting from the CBase parent
+class, each chare gets a ``thisProxy`` member variable, which holds a
+proxy to itself. This proxy can be sent to other chares, allowing them
+to invoke entry methods on this chare.
+
+.. _chare creation:
+
+Chare Creation
+^^^^^^^^^^^^^^
+
+Once you have declared and defined a chare class, you will want to
+create some chare objects to use. Chares are created by the ``ckNew``
+method, which is a static method of the chare’s proxy class:
+
+::
+
+      CProxy_chareType::ckNew(parameters, int destPE);
+
+The ``parameters`` correspond to the parameters of the chare’s
+constructor. Even if the constructor takes several arguments, all of the
+arguments should be passed in order to ``ckNew``. If the constructor
+takes no arguments, the parameters are omitted. By default, the new
+chare’s location is determined by the runtime system. However, this can
+be overridden by passing a value for ``destPE``, which specifies the PE
+where the chare will be created.
+
+The chare creation method deposits the *seed* for a chare in a pool of
+seeds and returns immediately. The chare will be created later on some
+processor, as determined by the dynamic load balancing strategy (or by
+``destPE``). When a chare is created, it is initialized by calling its
+constructor entry method with the parameters specified by ``ckNew``.
+
+Suppose we have declared a chare class ``C`` with a constructor that
+takes two arguments, an ``int`` and a ``double``.
+
+#. This will create a new chare of type C on any processor and return a
+   proxy to that chare:
+
+   ::
+
+         CProxy_C chareProxy = CProxy_C::ckNew(1, 10.0);
+
+#. This will create a new chare of type C on processor destPE and return
+   a proxy to that chare:
+
+   ::
+
+         CProxy_C chareProxy = CProxy_C::ckNew(1, 10.0, destPE);
+
+For an example of chare creation in a full application, see
+``examples/charm++/fib`` in the Charm++ software distribution, which
+calculates Fibonacci numbers in parallel.
+
+Method Invocation on Chares
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A message may be sent to a chare through a proxy object using the
+notation:
+
+::
+
+       chareProxy.EntryMethod(parameters)
+
+This invokes the entry method EntryMethod on the chare referred to by
+the proxy chareProxy. This call is asynchronous and non-blocking; it
+returns immediately after sending the message.
+
+Local Access
+^^^^^^^^^^^^
+
+You can get direct access to a local chare using the proxy’s ckLocal
+method, which returns an ordinary C++ pointer to the chare if it exists on
+the local processor, and NULL otherwise.
+
+::
+
+       C *c=chareProxy.ckLocal();
+       if (c==NULL) {
+           // object is remote; send message
+       } else {
+           // object is local; directly use members and methods of c
+       }
+
+.. _readonly:
+
+Read-only Data
+~~~~~~~~~~~~~~
+
+Since Charm++ does not allow global variables, it provides a special
+mechanism for sharing data amongst all objects. *Read-only* variables of
+simple data types or compound data types including messages and arrays
+are used to share information that is obtained only after the program
+begins execution and does not change after they are initialized in the
+dynamic scope of the ``main`` function of the mainchare. They are
+broadcast to every Charm++ Node (process) by the Charm++ runtime, and
+can be accessed in the same way as C++ “global” variables on any process.
+Compound data structures containing pointers can be made available as
+read-only variables using read-only messages(see
+section :numref:`messages`) or read-only arrays(see
+section :numref:`basic arrays`. Note that memory has to be
+allocated for read-only messages by using new to create the message in
+the ``main`` function of the mainchare.
+
+Read-only variables are declared by using the type modifier readonly,
+which is similar to const in C++. Read-only data is specified in the
+``.ci`` file (the interface file) as:
+
+::
+
+    readonly Type ReadonlyVarName;
+
+The variable ReadonlyVarName is declared to be a read-only variable of
+type Type. Type must be a single token and not a type expression.
+
+::
+
+    readonly message MessageType *ReadonlyMsgName;
+
+The variable ReadonlyMsgName is declared to be a read-only message of
+type MessageType. Pointers are not allowed to be readonly variables
+unless they are pointers to message types. In this case, the message
+will be initialized on every PE.
+
+::
+
+    readonly Type ReadonlyArrayName [arraysize];
+
+The variable ReadonlyArrayName is declared to be a read-only array of
+type Type with arraysize elements. Type must be a single token and not a
+type expression. The value of arraysize must be known at compile time.
+
+Read-only variables must be declared either as global or as public class
+static data in the C/C++ implementation files, and these declarations have
+the usual form:
+
+::
+
+    Type ReadonlyVarName;
+    MessageType *ReadonlyMsgName;
+    Type ReadonlyArrayName [arraysize];
+
+Similar declarations preceded by extern would appear in the ``.h`` file.
+
+*Note:* The current Charm++ translator cannot prevent assignments to
+read-only variables. The user must make sure that no assignments occur
+in the program outside of the mainchare constructor.
+
+For concrete examples for using read-only variables, please refer to
+examples such as ``examples/charm++/array`` and
+``examples/charm++/gaussSeidel3D``.
+
+Users can get the same functionality of readonly variables by making
+such variables members of Charm++ Node Group objects and constructing
+the Node Group in the mainchare’s main routine.
+
+.. _basic arrays:
+
+Chare Arrays
+------------
+
+Chare arrays are arbitrarily-sized, possibly-sparse collections of
+chares that are distributed across the processors. The entire array has
+a globally unique identifier of type CkArrayID, and each element has a
+unique index of type CkArrayIndex. A CkArrayIndex can be a single
+integer (i.e. a one-dimensional array), several integers (i.e. a
+multi-dimensional array), or an arbitrary string of bytes (e.g. a binary
+tree index).
+
+Array elements can be dynamically created and destroyed on any PE,
+migrated between PEs, and messages for the elements will still arrive
+properly. Array elements can be migrated at any time, allowing arrays to
+be efficiently load balanced. A chare array (or a subset of array
+elements) can receive a broadcast/multicast or contribute to a
+reduction.
+
+An example program can be found here: ``examples/charm++/array``.
+
+Declaring a One-dimensional Array
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can declare a one-dimensional (1D) chare array as:
+
+::
+
+   //In the .ci file:
+   array [1D] A {
+     entry A(parameters1);
+     entry void someEntry(parameters2);
+   };
+
+Array elements extend the system class CBase_ClassName, inheriting
+several fields:
+
+-  thisProxy: the proxy to the entire chare array that can be indexed to
+   obtain a proxy to a specific array element (e.g. for a 1D chare array
+   thisProxy[10]; for a 2D chare array thisProxy(10, 20))
+
+-  thisArrayID: the array’s globally unique identifier
+
+-  thisIndex: the element’s array index (an array element can obtain a
+   proxy to itself like this thisProxy[thisIndex])
+
+::
+
+   class A : public CBase_A {
+     public:
+       A(parameters1);
+
+       void someEntry(parameters2);
+   };
+
+Note that A must have a *migration constructor*, which is typically
+empty:
+
+::
+
+   //In the .C file:
+   A::A(void)
+   {
+     //... constructor code ...
+   }
+
+   A::someEntry(parameters2)
+   {
+     // ... code for someEntry ...
+   }
+
+See the section :numref:`arraymigratable` on migratable array
+elements for more information on the migration constructor that takes
+CkMigrateMessage \* as the argument.
+
+Declaring Multi-dimensional Arrays
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Charm++ supports multi-dimensional or user-defined indices. These array
+types can be declared as:
+
+::
+
+   //In the .ci file:
+   array [1D]  ArrayA { entry ArrayA(); entry void e(parameters);}
+   array [2D]  ArrayB { entry ArrayB(); entry void e(parameters);}
+   array [3D]  ArrayC { entry ArrayC(); entry void e(parameters);}
+   array [4D]  ArrayD { entry ArrayD(); entry void e(parameters);}
+   array [5D]  ArrayE { entry ArrayE(); entry void e(parameters);}
+   array [6D]  ArrayF { entry ArrayF(); entry void e(parameters);}
+   array [Foo] ArrayG { entry ArrayG(); entry void e(parameters);}
+   array [Bar<3>] ArrayH { entry ArrayH(); entry void e(parameters);}
+
+The declaration of ArrayG expects an array index of type
+CkArrayIndexFoo, which must be defined before including the ``.decl.h``
+file (see section :numref:`user-defined array index type` on
+user-defined array indices for more information).
+
+::
+
+   //In the .h file:
+   class ArrayA : public CBase_ArrayA { public: ArrayA(){} ...};
+   class ArrayB : public CBase_ArrayB { public: ArrayB(){} ...};
+   class ArrayC : public CBase_ArrayC { public: ArrayC(){} ...};
+   class ArrayD : public CBase_ArrayD { public: ArrayD(){} ...};
+   class ArrayE : public CBase_ArrayE { public: ArrayE(){} ...};
+   class ArrayF : public CBase_ArrayF { public: ArrayF(){} ...};
+   class ArrayG : public CBase_ArrayG { public: ArrayG(){} ...};
+   class ArrayH : public CBase_ArrayH { public: ArrayH(){} ...};
+
+The fields in thisIndex are different depending on the dimensionality of
+the chare array:
+
+-  1D array: thisIndex
+
+-  2D array (:math:`x`,\ :math:`y`): thisIndex.x, thisIndex.y
+
+-  3D array (:math:`x`,\ :math:`y`,\ :math:`z`): thisIndex.x,
+   thisIndex.y, thisIndex.z
+
+-  4D array (:math:`w`,\ :math:`x`,\ :math:`y`,\ :math:`z`):
+   thisIndex.w, thisIndex.x, thisIndex.y, thisIndex.z
+
+-  5D array (:math:`v`,\ :math:`w`,\ :math:`x`,\ :math:`y`,\ :math:`z`):
+   thisIndex.v, thisIndex.w, thisIndex.x, thisIndex.y, thisIndex.z
+
+-  6D array
+   (:math:`x_1`,\ :math:`y_1`,\ :math:`z_1`,\ :math:`x_2`,\ :math:`y_2`,\ :math:`z_2`):
+   thisIndex.x1, thisIndex.y1, thisIndex.z1, thisIndex.x2, thisIndex.y2,
+   thisIndex.z2
+
+-  Foo array: thisIndex
+
+-  Bar<3> array: thisIndex
+
+.. _basic array creation:
+
+Creating an Array
+~~~~~~~~~~~~~~~~~
+
+An array is created using the CProxy_Array::ckNew routine, which must be
+called from PE 0. To create an array from any PE, asynchronous array
+creation using a callback can be used. See
+section :numref:`asynchronous_array_creation` for asynchronous
+array creation. CProxy_Array::ckNew returns a proxy object, which can be
+kept, copied, or sent in messages. The following creates a 1D array
+containing elements indexed (0, 1, …, dimX-1):
+
+::
+
+   CProxy_ArrayA a1 = CProxy_ArrayA::ckNew(params, dimX);
+
+Likewise, a dense multidimensional array can be created by passing the
+extents at creation time to ckNew.
+
+::
+
+   CProxy_ArrayB a2 = CProxy_ArrayB::ckNew(params, dimX, dimY);
+   CProxy_ArrayC a3 = CProxy_ArrayC::ckNew(params, dimX, dimY, dimZ);
+   CProxy_ArrayD a4 = CProxy_ArrayC::ckNew(params, dimW, dimX, dimY, dimZ);
+   CProxy_ArrayE a5 = CProxy_ArrayC::ckNew(params, dimV, dimW, dimX, dimY, dimZ);
+   CProxy_ArrayF a6 = CProxy_ArrayC::ckNew(params, dimX1, dimY1, dimZ1, dimX2, dimY2, dimZ2);
+
+For user-defined arrays, this functionality cannot be used. The array
+elements must be inserted individually as described in
+section :numref:`dynamic_insertion`.
+
+During creation, the constructor is invoked on each array element. For
+more options when creating the array, see
+section :numref:`advanced array create`.
+
+Entry Method Invocation
+~~~~~~~~~~~~~~~~~~~~~~~
+
+To obtain a proxy to a specific element in chare array, the chare array
+proxy (e.g. thisProxy) must be indexed by the appropriate index call
+depending on the dimensionality of the array:
+
+-  1D array, to obtain a proxy to element :math:`i`:
+   thisProxy[:math:`i`] or thisProxy(\ :math:`i`)
+
+-  2D array, to obtain a proxy to element :math:`(i,j)`:
+   thisProxy(\ :math:`i`,\ :math:`j`)
+
+-  3D array, to obtain a proxy to element :math:`(i,j,k)`:
+   thisProxy(\ :math:`i`,\ :math:`j`,\ :math:`k`)
+
+-  4D array, to obtain a proxy to element :math:`(i,j,k,l)`:
+   thisProxy(\ :math:`i`,\ :math:`j`,\ :math:`k`,\ :math:`l`)
+
+-  5D array, to obtain a proxy to element :math:`(i,j,k,l,m)`:
+   thisProxy(\ :math:`i`,\ :math:`j`,\ :math:`k`,\ :math:`l`,\ :math:`m`)
+
+-  6D array, to obtain a proxy to element :math:`(i,j,k,l,m,n)`:
+   thisProxy(\ :math:`i`,\ :math:`j`,\ :math:`k`,\ :math:`l`,\ :math:`m`,\ :math:`n`)
+
+-  User-defined array, to obtain a proxy to element :math:`i`:
+   thisProxy[:math:`i`] or thisProxy(\ :math:`i`)
+
+To send a message to an array element, index the proxy and call the
+method name:
+
+::
+
+   a1[i].doSomething(parameters);
+   a3(x,y,z).doAnother(parameters);
+   aF[CkArrayIndexFoo(...)].doAgain(parameters);
+
+You may invoke methods on array elements that have not yet been created.
+The Charm++ runtime system will buffer the message until the element is
+created.  [5]_
+
+Messages are not guaranteed to be delivered in order. For instance, if a
+method is invoked on method A and then method B; it is possible that B
+is executed before A.
+
+::
+
+   a1[i].A();
+   a1[i].B();
+
+Messages sent to migrating elements will be delivered after the
+migrating element arrives on the destination PE. It is an error to send
+a message to a deleted array element.
+
+Broadcasts on Chare Arrays
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To broadcast a message to all the current elements of an array, simply
+omit the index (invoke an entry method on the chare array proxy):
+
+::
+
+   a1.doIt(parameters); //<- invokes doIt on each array element
+
+The broadcast message will be delivered to every existing array element
+exactly once. Broadcasts work properly even with ongoing migrations,
+insertions, and deletions.
+
+.. _reductions:
+
+Reductions on Chare Arrays
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A reduction applies a single operation (e.g. add, max, min, ...) to data
+items scattered across many processors and collects the result in one
+place. Charm++ supports reductions over the members of an array or
+group.
+
+The data to be reduced comes from a call to the member contribute
+method:
+
+::
+
+   void contribute(int nBytes, const void *data, CkReduction::reducerType type);
+
+This call contributes nBytes bytes starting at data to the reduction
+type (see Section :numref:`builtin_reduction`). Unlike sending a
+message, you may use data after the call to contribute. All members of
+the chare array or group must call contribute, and all of them must use
+the same reduction type.
+
+For example, if we want to sum each array/group member’s single integer
+myInt, we would use:
+
+::
+
+       // Inside any member method
+       int myInt=get_myInt();
+       contribute(sizeof(int),&myInt,CkReduction::sum_int);
+
+The built-in reduction types (see below) can also handle arrays of
+numbers. For example, if each element of a chare array has a pair of
+doubles forces[2], the corresponding elements of which are to be added
+across all elements, from each element call:
+
+::
+
+       double forces[2]=get_my_forces();
+       contribute(2*sizeof(double),forces,CkReduction::sum_double);
+
+Note that since C++ arrays (like forces[2]) are already pointers, we
+don’t use &forces.
+
+A slightly simpler interface is available for ``std::vector<T>``, since
+the class determines the size and count of the underlying type:
+
+::
+
+       CkCallback cb(...);
+       vector<double> forces(2);
+       get_my_forces(forces);
+       contribute(forces, CkReduction::sum_double, cb);
+
+Either of these will result in a ``double`` array of 2 elements, the
+first of which contains the sum of all forces[0] values, with the second
+element holding the sum of all forces[1] values of the chare array
+elements.
+
+Typically the client entry method of a reduction takes a single argument
+of type CkReductionMsg (see Section :numref:`reductionClients`).
+However, by giving an entry method the reductiontarget attribute in the
+``.ci`` file, you can instead use entry methods that take arguments of
+the same type as specified by the *contribute* call. When creating a
+callback to the reduction target, the entry method index is generated by
+``CkReductionTarget(ChareClass, method_name)`` instead of
+``CkIndex_ChareClass::method_name(...)``. For example, the code for a
+typed reduction that yields an ``int``, would look like this:
+
+::
+
+     // In the .ci file...
+     entry [reductiontarget] void done(int result);
+
+     // In some .C file:
+     // Create a callback that invokes the typed reduction client
+     // driverProxy is a proxy to the chare object on which
+     // the reduction target method "done" is called upon completion
+     // of the reduction
+     CkCallback cb(CkReductionTarget(Driver, done), driverProxy);
+
+     // Contribution to the reduction...
+     contribute(sizeof(int), &intData, CkReduction::sum_int, cb);
+
+     // Definition of the reduction client...
+     void Driver::done(int result)
+     {
+       CkPrintf("Reduction value: %d", result);
+     }
+
+This will also work for arrays of data
+elements(\ ``entry [reductiontarget] void done(int n, int result[n])``),
+and for any user-defined type with a PUP method (see
+:numref:`sec:pup`). If you know that the reduction will yield a
+particular number of elements, say 3 ``int``\ s, you can also specify a
+reduction target which takes 3 ``int``\ s and it will be invoked
+correctly.
+
+Reductions do not have to specify commutative-associative operations on
+data; they can also be used to signal the fact that all array/group
+members have reached a certain synchronization point. In this case, a
+simpler version of contribute may be used:
+
+::
+
+       contribute();
+
+In all cases, the result of the reduction operation is passed to the
+*reduction client*. Many different kinds of reduction clients can be
+used, as explained in Section :numref:`reductionClients`.
+
+Please refer to ``examples/charm++/reductions/typed_reduction`` for a
+working example of reductions in Charm++.
+
+Note that the reduction will complete properly even if chare array
+elements are *migrated* or *deleted* during the reduction. Additionally,
+when you create a new chare array element, it is expected to contribute
+to the next reduction not already in progress on that processor.
+
+.. _builtin_reduction:
+
+Built-in Reduction Types
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Charm++ includes several built-in reduction types, used to combine
+individual contributions. Any of them may be passed as an argument of
+type CkReduction::reducerType to contribute.
+
+The first four operations (``sum``, ``product``, ``max``, and ``min``)
+work on ``char``, ``short``, ``int``, ``long``, ``long long``,
+``float``, or ``double`` data as indicated by the suffix. The logical
+reductions (``and``, ``or``) only work on bool and integer data. All the
+built-in reductions work on either single numbers (pass a pointer) or
+arrays- just pass the correct number of bytes to contribute.
+
+#. CkReduction::nop : no operation performed.
+
+#. CkReduction::sum_char, sum_short, sum_int, sum_long, sum_long_long,
+   sum_uchar, sum_ushort, sum_uint, sum_ulong, sum_ulong_long,
+   sum_float, sum_double : the result will be the sum of the given
+   numbers.
+
+#. CkReduction::product_char, product_short, product_int, product_long,
+   product_long_long, product_uchar, product_ushort, product_uint,
+   product_ulong, product_ulong_long, product_float, product_double :
+   the result will be the product of the given numbers.
+
+#. CkReduction::max_char, max_short, max_int, max_long, max_long_long,
+   max_uchar, max_ushort, max_uint, max_ulong, max_ulong_long,
+   max_float, max_double : the result will be the largest of the given
+   numbers.
+
+#. CkReduction::min_char, min_short, min_int, min_long, min_long_long,
+   min_uchar, min_ushort, min_uint, min_ulong, min_ulong_long,
+   min_float, min_double : the result will be the smallest of the given
+   numbers.
+
+#. CkReduction::logical_and_bool, logical_and_int : the result will be
+   the logical AND of the given values.
+
+#. CkReduction::logical_or_bool, logical_or_int : the result will be the
+   logical OR of the given values.
+
+#. CkReduction::logical_xor_bool, logical_xor_int : the result will be
+   the logical XOR of the given values.
+
+#. CkReduction::bitvec_and_bool, bitvec_and_int : the result will be the
+   bitvector AND of the given values.
+
+#. CkReduction::bitvec_or_bool, bitvec_or_int : the result will be the
+   bitvector OR of the given values.
+
+#. CkReduction::bitvec_xor_bool, bitvec_xor_int : the result will be the
+   bitvector XOR of the given values.
+
+#. CkReduction::set : the result will be a verbatim concatenation of all
+   the contributed data, separated into CkReduction::setElement records.
+   The data contributed can be of any length, and can vary across array
+   elements or reductions. To extract the data from each element, see
+   the description below.
+
+#. CkReduction::concat : the result will be a byte-by-byte concatenation
+   of all the contributed data. The contributed elements are not
+   delimiter-separated.
+
+#. CkReduction::random : the result will be a single randomly selected
+   value of all of the contributed values.
+
+#. CkReduction::statistics : returns a CkReduction::statisticsElement
+   struct, containing summary statistics of the contributed data.
+   Specifically, the struct contains the following fields: int count,
+   double mean, and double m2, and the following functions: double
+   variance() and double stddev().
+
+CkReduction::set returns a collection of CkReduction::setElement
+objects, one per contribution. This class has the definition:
+
+::
+
+   class CkReduction::setElement
+   {
+   public:
+     int dataSize; //The length of the `data' array in bytes.
+     char data[1]; //A place holder that marks the start of the data array.
+     CkReduction::setElement *next(void);
+   };
+
+Example: Suppose you would like to contribute 3 integers from each array
+element. In the reduction method you would do the following:
+
+::
+
+   void ArrayClass::methodName (CkCallback &cb)
+   {
+     int result[3];
+     result[0] = 1;            // Copy the desired values into the result.
+     result[1] = 2;
+     result[2] = 3;
+     // Contribute the result to the reductiontarget cb.
+     contribute(3*sizeof(int), result, CkReduction::set, cb);
+   }
+
+Inside the reduction’s target method, the contributions can be accessed
+by using the ``CkReduction::setElement->next()`` iterator.
+
+::
+
+   void SomeClass::reductionTargetMethod (CkReductionMsg *msg)
+   {
+     // Get the initial element in the set.
+     CkReduction::setElement *current = (CkReduction::setElement*) msg->getData();
+     while(current != NULL) // Loop over elements in set.
+     {
+       // Get the pointer to the packed int's.
+       int *result = (int*) &current->data;
+       // Do something with result.
+       current = current->next(); // Iterate.
+     }
+   }
+
+The reduction set order is undefined. You should add a source field to
+the contributed elements if you need to know which array element gave a
+particular contribution. Additionally, if the contributed elements are
+of a complex data type, you will likely have to supply code for
+serializing/deserializing them. Consider using the PUP interface
+(§ :numref:`sec:pup`) to simplify your object serialization
+needs.
+
+If the outcome of your reduction is dependent on the order in which data
+elements are processed, or if your data is just too heterogeneous to be
+handled elegantly by the predefined types and you don’t want to
+undertake multiple reductions, you can use a tuple reduction or define
+your own custom reduction type.
+
+Tuple reductions allow performing multiple different reductions in the
+same message. The reductions can be on the same or different data, and
+the reducer type for each reduction can be set independently as well.
+The contributions that make up a single tuple reduction message are all
+reduced in the same order as each other. As an example, a chare array
+element can contribute to a gatherv-like operation using a tuple
+reduction that consists of two set reductions.
+
+::
+
+   int tupleSize = 2;
+   CkReduction::tupleElement tupleRedn[] = {
+     CkReduction::tupleElement(sizeof(int), &thisIndex, CkReduction::set),
+     CkReduction::tupleElement(sizeData, data, CkReduction::set)
+   };
+   CkReductionMsg* msg = CkReductionMsg::buildFromTuple(tupleRedn, tupleSize);
+   CkCallback allgathervCB(CkIndex_Foo::allgathervResult(0), thisProxy);
+   msg->setCallback(allgathervCB);
+   contribute(msg);
+
+The result of this reduction is a single CkReductionMsg that can be
+processed as multiple reductions:
+
+::
+
+   void Foo::allgathervResult (CkReductionMsg* msg)
+   {
+     int numReductions;
+     CkReduction::tupleElement* results;
+
+     msg->toTuple(&results, &numReductions);
+     CkReduction::setElement* currSrc  = (CkReduction::setElement*)results[0].data;
+     CkReduction::setElement* currData = (CkReduction::setElement*)results[1].data;
+
+     // ... process currSrc and currData
+
+     delete [] results;
+   }
+
+See the next section (Section :numref:`new_type_reduction`) for details
+on custom reduction types.
+
+Destroying Array Elements
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To destroy an array element - detach it from the array, call its
+destructor, and release its memory-invoke its Array destroy method, as:
+
+::
+
+   a1[i].ckDestroy();
+
+Note that this method can also be invoked remotely i.e. from a process
+different from the one on which the array element resides. You must
+ensure that no messages are sent to a deleted element. After destroying
+an element, you may insert a new element at its index.
+
+.. _sec:sdag:
+
+Structured Control Flow: Structured Dagger
+------------------------------------------
+
+Charm++ is based on the message-driven parallel programming paradigm. In
+contrast to many other approaches, Charm++ programmers encode entry
+points to their parallel objects, but do not explicitly wait (i.e.
+block) on the runtime to indicate completion of posted ‘receive’
+requests. Thus, a Charm++ object’s overall flow of control can end up
+fragmented across a number of separate methods, obscuring the sequence
+in which code is expected to execute. Furthermore, there are often
+constraints on when different pieces of code should execute relative to
+one another, related to data and synchronization dependencies.
+
+Consider one way of expressing these constraints using flags, buffers,
+and counters, as in the following example:
+
+::
+
+   // in .ci file
+   chare ComputeObject {
+     entry void ComputeObject();
+     entry void startStep();
+     entry void firstInput(Input i);
+     entry void secondInput(Input j);
+   };
+
+   // in C++ file
+   class ComputeObject : public CBase_ComputeObject {
+     int   expectedMessageCount;
+     Input first, second;
+
+   public:
+     ComputeObject() {
+       startStep();
+     }
+     void startStep() {
+       expectedMessageCount = 2;
+     }
+
+     void firstInput(Input i) {
+       first = i;
+       if (--expectedMessageCount == 0)
+         computeInteractions(first, second);
+       }
+     void recv_second(Input j) {
+       second = j;
+       if (--expectedMessageCount == 0)
+         computeInteractions(first, second);
+     }
+
+     void computeInteractions(Input a, Input b) {
+       // do computations using a and b
+       ...
+       // send off results
+       ...
+       // reset for next step
+       startStep();
+     }
+   };
+
+In each step, this object expects pairs of messages, and waits to
+process the incoming data until it has both of them. This sequencing is
+encoded across 4 different functions, which in real code could be much
+larger and more numerous, resulting in a spaghetti-code mess.
+
+Instead, it would be preferable to express this flow of control using
+structured constructs, such as loops. Charm++ provides such constructs
+for structured control flow across an object’s entry methods in a
+notation called Structured Dagger. The basic constructs of Structured
+Dagger (SDAG) provide for *program-order execution* of the entry methods
+and code blocks that they define. These definitions appear in the
+``.ci`` file definition of the enclosing chare class as a ‘body’ of an
+entry method following its signature.
+
+The most basic construct in SDAG is the ``serial`` (aka the ``atomic``)
+block. Serial blocks contain sequential C++ code. They’re also called
+atomic because the code within them executes without returning control
+to the Charm++ runtime scheduler, and thus avoiding interruption from
+incoming messages. The keywords atomic and serial are synonymous, and
+you can find example programs that use atomic. However, we recommend the
+use of serial and are considering the deprecation of the atomic keyword.
+Typically serial blocks hold the code that actually deals with incoming
+messages in a ``when`` statement, or to do local operations before a
+message is sent or after it’s received. The earlier example can be
+adapted to use serial blocks as follows:
+
+::
+
+   // in .ci file
+   chare ComputeObject {
+     entry void ComputeObject();
+     entry void startStep();
+     entry void firstInput(Input i) {
+       serial {
+         first = i;
+         if (--expectedMessageCount == 0)
+           computeInteractions(first, second);
+       }
+     };
+     entry void secondInput(Input j) {
+       serial {
+         second = j;
+         if (--expectedMessageCount == 0)
+           computeInteractions(first, second);
+       }
+     };
+   };
+
+   // in C++ file
+   class ComputeObject : public CBase_ComputeObject {
+     ComputeObject_SDAG_CODE
+     int   expectedMessageCount;
+     Input first, second;
+
+   public:
+     ComputeObject() {
+       startStep();
+     }
+     void startStep() {
+       expectedMessageCount = 2;
+     }
+
+     void computeInteractions(Input a, Input b) {
+       // do computations using a and b
+       . . .
+       // send off results
+       . . .
+       // reset for next step
+       startStep();
+     }
+   };
+
+Note that chare classes containing SDAG code must include a few
+additional declarations in addition to inheriting from their
+``CBase_Foo`` class, by incorporating the ``Foo_SDAG_CODE``
+generated-code macro in the class.
+
+Serial blocks can also specify a textual ‘label’ that will appear in
+traces, as follows:
+
+::
+
+     entry void firstInput(Input i) {
+       serial "process first" {
+         first = i;
+         if (--expectedMessageCount == 0)
+           computeInteractions(first, second);
+       }
+     };
+
+In order to control the sequence in which entry methods are processed,
+SDAG provides the ``when`` construct. These statements, also called
+triggers, indicate that we expect an incoming message of a particular
+type, and provide code to handle that message when it arrives. From the
+perspective of a chare object reaching a ``when`` statement, it is
+effectively a ‘blocking receive.’
+
+Entry methods defined by a ``when`` are not executed immediately when a
+message targeting them is delivered, but instead are held until control
+flow in the chare reaches a corresponding ``when`` clause. Conversely,
+when control flow reaches a ``when`` clause, the generated code checks
+whether a corresponding message has arrived: if one has arrived, it is
+processed; otherwise, control is returned to the Charm++ scheduler.
+
+The use of ``when`` substantially simplifies the example from above:
+
+::
+
+   // in .ci file
+   chare ComputeObject {
+     entry void ComputeObject();
+     entry void startStep() {
+       when firstInput(Input first)
+         when secondInput(Input second)
+           serial {
+             computeInteractions(first, second);
+           }
+     };
+     entry void firstInput(Input i);
+     entry void secondInput(Input j);
+   };
+
+   // in C++ file
+   class ComputeObject : public CBase_ComputeObject {
+     ComputeObject_SDAG_CODE
+
+   public:
+     ComputeObject() {
+       startStep();
+     }
+
+     void computeInteractions(Input a, Input b) {
+       // do computations using a and b
+       . . .
+       // send off results
+       . . .
+       // reset for next step
+       startStep();
+     }
+   };
+
+Like an ``if`` or ``while`` in C code, each ``when`` clause has a body
+made up of the statement or block following it. The variables declared
+as arguments to the entry method triggering the when are available in
+the scope of the body. By using the sequenced execution of SDAG code and
+the availability of parameters to when-defined entry methods in their
+bodies, the counter ``expectedMessageCount`` and the intermediate copies
+of the received input are eliminated. Note that the entry methods
+``firstInput`` and ``secondInput`` are still declared in the ``.ci``
+file, but their definition is in the SDAG code. The interface translator
+generates code to handle buffering and triggering them appropriately.
+
+For simplicity, ``when`` constructs can also specify multiple expected
+entry methods that all feed into a single body, by separating their
+prototypes with commas:
+
+::
+
+   entry void startStep() {
+     when firstInput(Input first),
+          secondInput(Input second)
+       serial {
+         computeInteractions(first, second);
+       }
+   };
+
+A single entry method is allowed to appear in more than one ``when``
+statement. If only one of those ``when`` statements has been triggered
+when the runtime delivers a message to that entry method, that ``when``
+statement is guaranteed to process it. If there is no trigger waiting
+for that entry method, then the next corresponding ``when`` to be
+reached will receive that message. If there is more than one ``when``
+waiting on that method, which one will receive it is not specified, and
+should not be relied upon. For an example of multiple ``when``
+statements handling the same entry method without reaching the
+unspecified case, see the CharmLU benchmark.
+
+To more finely control the correspondence between incoming messages and
+``when`` clauses associated with the target entry method, SDAG supports
+*matching* on reference numbers. Matching is typically used to denote an
+iteration of a program that executes asynchronously (without any sort of
+barrier or other synchronization between steps) or a particular piece of
+the problem being solved. Matching is requested by placing an expression
+denoting the desired reference number in square brackets between the
+entry method name and its parameter list. For parameter marshalled entry
+methods, the reference number expression will be compared for equality
+with the entry method’s first argument. For entry methods that accept an
+explicit message (§ :numref:`messages`), the reference number on the
+message can be set by calling the function
+``CkSetRefNum(void *msg, CMK_REFNUM_TYPE ref)``. Matching is used in the
+loop example below, and in
+``examples/charm++/jacobi2d-sdag/jacobi2d.ci``. Multiple ``when``
+triggers for an entry method with different matching reference numbers
+will not conflict - each will receive only corresponding messages.
+
+SDAG supports the ``for`` and ``while`` loop constructs mostly as if
+they appeared in plain C or C++ code. In the running example,
+``computeInteractions()`` calls ``startStep()`` when it is finished to
+start the next step. Instead of this arrangement, the loop structure can
+be made explicit:
+
+::
+
+   // in .ci file
+   chare ComputeObject {
+     entry void ComputeObject();
+     entry void runForever() {
+       while(true) {
+         when firstInput(Input first),
+              secondInput(Input second) serial {
+             computeInteractions(first, second);
+         }
+       }
+     };
+     entry void firstInput(Input i);
+     entry void secondInput(Input j);
+   };
+
+   // in C++ file
+   class ComputeObject : public CBase_ComputeObject {
+     ComputeObject_SDAG_CODE
+
+   public:
+     ComputeObject() {
+       runForever();
+     }
+
+     void computeInteractions(Input a, Input b) {
+       // do computations using a and b
+       . . .
+       // send off results
+       . . .
+     }
+   };
+
+If this code should instead run for a fixed number of iterations, we can
+instead use a for loop:
+
+::
+
+   // in .ci file
+   chare ComputeObject {
+     entry void ComputeObject();
+     entry void runForever() {
+       for(iter = 0; iter < n; ++iter) {
+         // Match to only accept inputs for the current iteration
+         when firstInput[iter](int a, Input first),
+              secondInput[iter](int b, Input second) serial {
+           computeInteractions(first, second);
+         }
+       }
+     };
+     entry void firstInput(int a, Input i);
+     entry void secondInput(int b, Input j);
+   };
+
+   // in C++ file
+   class ComputeObject : public CBase_ComputeObject {
+     ComputeObject_SDAG_CODE
+     int n, iter;
+
+   public:
+     ComputeObject() {
+       n = 10;
+       runForever();
+     }
+
+     void computeInteractions(Input a, Input b) {
+       // do computations using a and b
+       . . .
+       // send off results
+       . . .
+     }
+   };
+
+Note that ``int iter;`` is declared in the chare’s class definition and
+not in the ``.ci`` file. This is necessary because the Charm++ interface
+translator does not fully parse the declarations in the ``for`` loop
+header, because of the inherent complexities of C++.
+
+SDAG also supports conditional execution of statements and blocks with
+``if`` statements. The syntax of SDAG ``if`` statements matches that of
+C and C++. However, if one encounters a syntax error on correct-looking
+code in a loop or conditional statement, try assigning the condition
+expression to a boolean variable in a serial block preceding the
+statement and then testing that boolean’s value. This can be necessary
+because of the complexity of parsing C++ code.
+
+In cases where multiple tasks must be processed before execution
+continues, but with no dependencies or interactions among them, SDAG
+provides the ``overlap`` construct. Overlap blocks contain a series of
+SDAG statements within them which can occur in any order. Commonly these
+blocks are used to hold a series of ``when`` triggers which can be
+received and processed in any order. Flow of control doesn’t leave the
+overlap block until all the statements within it have been processed.
+
+In the running example, suppose each input needs to be preprocessed
+independently before the call to ``computeInteractions``. Since we don’t
+care which order they get processed in, and want it to happen as soon as
+possible, we can apply ``overlap``:
+
+::
+
+   // in .ci file
+   chare ComputeObject {
+     entry void ComputeObject();
+     entry void startStep() {
+       overlap {
+         when firstInput(Input i)
+           serial { first = preprocess(i); }
+         when secondInput(Input j)
+           serial { second = preprocess(j); }
+        }
+        serial {
+          computeInteractions(first, second);
+        }
+     };
+     entry void firstInput(Input i);
+     entry void secondInput(Input j);
+   };
+
+   // in C++ file
+   class ComputeObject : public CBase_ComputeObject {
+     ComputeObject_SDAG_CODE
+
+   public:
+     ComputeObject() {
+       startStep();
+     }
+
+     void computeInteractions(Input a, Input b) {
+       // do computations using a and b
+       . . .
+       // send off results
+       . . .
+       // reset for next step
+       startStep();
+     }
+   };
+
+Another construct offered by SDAG is the ``forall`` loop. These loops
+are used when the iterations of a loop can be performed independently
+and in any order. This is in contrast to a regular ``for`` loop, in
+which each iteration is executed sequentially. The loop iterations are
+executed entirely on the calling PE, so they do not run in parallel.
+However, they are executed concurrently, in that execution of different
+iterations can interleave at ``when`` statements, like any other SDAG
+code. SDAG statements following the ``forall`` loop will not execute
+until all iterations have completed. The ``forall`` loop can be seen as
+an ``overlap`` with an indexed set of otherwise identical statements in
+the body.
+
+The syntax of ``forall`` is
+
+::
+
+   forall [IDENT] (MIN:MAX,STRIDE) BODY
+
+The range from MIN to MAX is inclusive. In each iteration instance of
+``BODY``, the ``IDENT`` variable will take on one of the values in the
+specified range. The ``IDENT`` variable must be declared in the
+application C++ code as a member of the enclosing chare class.
+
+Use of ``forall`` is demonstrated through distributed parallel
+matrix-matrix multiply shown in ``examples/charm++/matmul/matmul.ci``
+
+The ``case`` Statement
+~~~~~~~~~~~~~~~~~~~~~~
+
+The ``case`` statement in SDAG expresses a disjunction over a set of
+``when`` clauses. In other words, if it is known that one dependency out
+of a set will be satisfied, but which one is not known, this statement
+allows the set to be specified and will execute the corresponding block
+based on which dependency ends up being fulfilled.
+
+The following is a basic example of the ``case`` statement. Note that
+the trigger ``b(), d()`` will only be fulfilled if both ``b()`` and
+``d()`` arrive. If only one arrives, then it will partially match, and
+the runtime will not “commit” to this branch until the second arrives.
+If another dependency fully matches, the partial match will be ignored
+and can be used to trigger another ``when`` later in the execution.
+
+::
+
+   case {
+     when a() { }
+     when b(), d() { }
+     when c() { }
+   }
+
+A full example of the ``case`` statement can be found
+``tests/charm++/sdag/case/caseTest.ci``.
+
+Usage Notes
+~~~~~~~~~~~
+
+SDAG Code Declaration
+^^^^^^^^^^^^^^^^^^^^^
+
+If you’ve added *Structured Dagger* code to your class, you must link in
+the code by adding “*className*\ \_SDAG_CODE” inside the class
+declaration in the .h file. This macro defines the entry points and
+support code used by *Structured Dagger*. Forgetting this results in a
+compile error (undefined SDAG entry methods referenced from the .def.h
+file).
+
+For example, an array named “Foo” that uses sdag code might contain:
+
+::
+
+   class Foo : public CBase_Foo {
+   public:
+       Foo_SDAG_CODE
+       Foo(...) {
+          ...
+       }
+       Foo(CkMigrateMessage *m) { }
+
+       void pup(PUP::er &p) {
+          ...
+       }
+       . . .
+   };
+
+Direct Calls to SDAG Entry Methods
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+An SDAG entry method that contains one or more when clause(s) cannot be
+directly called and will result in a runtime error with an error
+message. It has to be only called through a proxy. This is a runtime
+requirement that is enforced in order to prevent accidental calls to
+SDAG entry methods that are asynchronous in nature. Additionally, since
+they are called using a proxy, it enhances understandability and clarity
+as to not be confused for a regular function call that returns
+immediately.
+
+For example, in the first example discussed, it is invalid to call the
+SDAG entry method ``startStep`` directly as ``startStep();`` because it
+contains when clauses. It has to be only called using the proxy i.e.
+``computeObj.startStep();`` , where ``computeObj`` is the proxy to
+``ComputeObject``.
+
+.. _sec:pup:
+
+Serialization Using the PUP Framework
+-------------------------------------
+
+The PUP (Pack/Unpack) framework is a generic way to describe the data in
+an object and to use that description for serialization. The
+Charm++ system can use this description to pack the object into a
+message and unpack the message into a new object on another processor,
+to pack and unpack migratable objects for load balancing or
+checkpoint/restart-based fault tolerance. The PUP framework also
+includes support special for STL containers to ease development in C++.
+
+Like many C++ concepts, the PUP framework is easier to use than describe:
+
+::
+
+   class foo : public mySuperclass {
+    private:
+       double a;
+       int x;
+       char y;
+       unsigned long z;
+       float arr[3];
+    public:
+       ...other methods...
+
+       //pack/unpack method: describe my fields to charm++
+       void pup(PUP::er &p) {
+         mySuperclass::pup(p);
+         p|a;
+         p|x; p|y; p|z;
+         PUParray(p,arr,3);
+       }
+   };
+
+This class’s pup method describes the fields of the class to Charm++.
+This allows Charm++ to marshall parameters of type foo across
+processors, translate foo objects across processor architectures, read
+and write foo objects to files on disk, inspect and modify foo objects
+in the debugger, and checkpoint and restart programs involving foo
+objects.
+
+.. _sec:pupcontract:
+
+PUP contract
+~~~~~~~~~~~~
+
+Your object’s pup method must save and restore all your object’s data.
+As shown, you save and restore a class’s contents by writing a method
+called “pup” which passes all the parts of the class to an object of
+type PUP::er, which does the saving or restoring. This manual will often
+use “pup” as a verb, meaning “to save/restore the value of” or
+equivalently, “to call the pup method of”.
+
+Pup methods for complicated objects normally call the pup methods for
+their simpler parts. Since all objects depend on their immediate
+superclass, the first line of every pup method is a call to the
+superclass’s pup method—the only time you shouldn’t call your
+superclass’s pup method is when you don’t have a superclass. If your
+superclass has no pup method, you must pup the values in the superclass
+yourself.
+
+.. _sec:pupoperator:
+
+PUP operator
+^^^^^^^^^^^^
+
+The recommended way to pup any object ``a`` is to use ``p|a;``. This
+syntax is an operator ``|`` applied to the PUP::er ``p`` and the user
+variable ``a``.
+
+The ``p|a;`` syntax works wherever ``a`` is:
+
+-  A simple type, including char, short, int, long, float, or double. In
+   this case, ``p|a;`` copies the data in-place. This is equivalent to
+   passing the type directly to the PUP::er using ``p(a)``.
+
+-  Any object with a pup method. In this case, ``p|a;`` calls the
+   object’s pup method. This is equivalent to the statement a.pup(p);.
+
+-  A pointer to a PUP::able object, as described in
+   Section :numref:`sec:pup::able`. In this case, ``p|a;`` allocates
+   and copies the appropriate subclass.
+
+-  An object with a PUPbytes(myClass) declaration in the header. In this
+   case, ``p|a;`` copies the object as plain bytes, like memcpy.
+
+-  An object with a custom ``operator |`` defined. In this case,
+   ``p|a;`` calls the custom ``operator |``.
+
+See ``examples/charm++/PUP``
+
+For container types, you must simply pup each element of the container.
+For arrays, you can use the utility method PUParray, which takes the
+PUP::er, the array base pointer, and the array length. This utility
+method is defined for user-defined types T as:
+
+::
+
+       template<class T>
+       inline void PUParray(PUP::er &p,T *array,int length) {
+          for (int i=0;i<length;i++) p|array[i];
+       }
+
+.. _sec:pupstl:
+
+PUP STL Container Objects
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If the variable is from the C++ Standard Template Library, you can
+include operator\ ``|``\ ’s for STL containers such as vector, map, set,
+list, pair, and string, templated on anything, by including the header
+“pup_stl.h”.
+
+See ``examples/charm++/PUP/STLPUP``
+
+PUP Dynamic Data
+^^^^^^^^^^^^^^^^
+
+As usual in C++, pointers and allocatable objects usually require special
+handling. Typically this only requires a p.isUnpacking() conditional
+block, where you perform the appropriate allocation. See
+Section :numref:`sec:pupdynalloc` for more information and examples.
+
+If the object does not have a pup method, and you cannot add one or use
+PUPbytes, you can define an operator\ ``|`` to pup the object. For
+example, if myClass contains two fields a and b, the operator\ ``|``
+might look like:
+
+::
+
+     inline void operator|(PUP::er &p,myClass &c) {
+       p|c.a;
+       p|c.b;
+     }
+
+See ``examples/charm++/PUP/HeapPUP``
+
+.. _sec:pupbytes:
+
+PUP as bytes
+^^^^^^^^^^^^
+
+For classes and structs with many fields, it can be tedious and
+error-prone to list all the fields in the pup method. You can avoid this
+listing in two ways, as long as the object can be safely copied as raw
+bytes—this is normally the case for simple structs and classes without
+pointers.
+
+-  Use the ``PUPbytes(myClass)`` macro in your header file. This lets
+   you use the ``p|*myPtr;`` syntax to pup the entire class as
+   sizeof(myClass) raw bytes.
+
+-  Use ``p((void *)myPtr,sizeof(myClass));`` in the pup method. This is
+   a direct call to pup a set of bytes.
+
+-  Use ``p((char *)myCharArray,arraySize);`` in the pup method. This is
+   a direct call to pup a set of bytes. Other primitive types may also
+   be used.
+
+Note that pupping as bytes is just like using ‘memcpy’: it does nothing
+to the data other than copy it whole. For example, if the class contains
+any pointers, you must make sure to do any allocation needed, and pup
+the referenced data yourself.
+
+Pupping as bytes may prevent your pup method from ever being able to
+work across different machine architectures. This is currently an
+uncommon scenario, but heterogeneous architectures may become more
+common, so pupping as bytes is discouraged.
+
+.. _sec:pupoverhead:
+
+PUP overhead
+^^^^^^^^^^^^
+
+The PUP::er overhead is very small—one virtual function call for each
+item or array to be packed/unpacked. The actual packing/unpacking is
+normally a simple memory-to-memory binary copy.
+
+For arrays and vectors of builtin arithmetic types like “int" and
+“double", or of types declared as “PUPbytes”, PUParray uses an even
+faster block transfer, with one virtual function call per array or
+vector.
+
+Thus, if an object does not contain pointers, you should prefer
+declaring it as PUPbytes.
+
+For types of objects whose default constructors do more than necessary
+when an object will be unpacked from PUP, it is possible to tell the
+runtime system to call a more minimalistic alternative. This can apply
+to types used as both member variables of chares and as marshalled
+arguments to entry methods. A non-chare class can define a constructor
+that takes an argument of type ``PUP::reconstruct`` for this purpose.
+The runtime system code will call a ``PUP::reconstruct`` constructor in
+preference to a default constructor when it’s available. Where
+necessary, constructors taking ``PUP::reconstruct`` should call the
+constructors of members variables with ``PUP::reconstruct`` if
+applicable to that member.
+
+.. _sec:pupmodes:
+
+PUP modes
+^^^^^^^^^
+
+Charm++ uses your pup method to both pack and unpack, by passing
+different types of PUP::ers to it. The method p.isUnpacking() returns
+true if your object is being unpacked—that is, your object’s values are
+being restored. Your pup method must work properly in sizing, packing,
+and unpacking modes; and to save and restore properly, the same fields
+must be passed to the PUP::er, in the exact same order, in all modes.
+This means most pup methods can ignore the pup mode.
+
+Three modes are used, with three separate types of PUP::er: sizing,
+which only computes the size of your data without modifying it; packing,
+which reads/saves values out of your data; and unpacking, which
+writes/restores values into your data. You can determine exactly which
+type of PUP::er was passed to you using the p.isSizing(), p.isPacking(),
+and p.isUnpacking() methods. However, sizing and packing should almost
+always be handled identically, so most programs should use
+p.isUnpacking() and !p.isUnpacking(). Any program that calls
+p.isPacking() and does not also call p.isSizing() is probably buggy,
+because sizing and packing must see exactly the same data.
+
+The p.isDeleting() flag indicates the object will be deleted after
+calling the pup method. This is normally only needed for pup methods
+called via the C or f90 interface, as provided by AMPI or the other
+frameworks. Other Charm++ array elements, marshalled parameters, and
+other C++ interface objects have their destructor called when they are
+deleted, so the p.isDeleting() call is not normally required—instead,
+memory should be deallocated in the destructor as usual.
+
+More specialized modes and PUP::ers are described in
+section :numref:`sec:PUP:CommonPUPers`.
+
+.. _sec:lifecycle:
+
+PUP Usage Sequence
+~~~~~~~~~~~~~~~~~~
+
+.. figure:: fig/pup.png
+   :name: fig:pup
+   :width: 6in
+
+   Method sequence of an object with a pup method.
+
+Typical method invocation sequence of an object with a pup method is
+shown in Figure :numref:`fig:pup`. As usual in C++, objects are
+constructed, do some processing, and are then destroyed.
+
+Objects can be created in one of two ways: they can be created using a
+normal constructor as usual; or they can be created using their pup
+constructor. The pup constructor for Charm++ array elements and
+PUP::able objects is a “migration constructor” that takes a single
+“CkMigrateMessage \*"; for other objects, such as parameter marshalled
+objects, the pup constructor has no parameters. The pup constructor is
+always followed by a call to the object’s pup method in ``isUnpacking``
+mode.
+
+Once objects are created, they respond to regular user methods and
+remote entry methods as usual. At any time, the object pup method can be
+called in ``isSizing`` or ``isPacking`` mode. User methods and sizing or
+packing pup methods can be called repeatedly over the object lifetime.
+
+Finally, objects are destroyed by calling their destructor as usual.
+
+.. _arraymigratable:
+
+Migratable Array Elements using PUP
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Array objects can migrate from one PE to another. For example, the load
+balancer (see section :numref:`lbFramework`) might migrate array
+elements to better balance the load between processors. For an array
+element to be migratable, it must implement a pup method. The standard
+PUP contract (see section :numref:`sec:pupcontract`) and constraints
+wrt to serializing data apply. The one exception for chare , group and
+node group types is that since the runtime system will be the one to
+invoke their PUP routines, the runtime will automatically call PUP on
+the generated CBase\_ superclasses so users do not need to call PUP on
+generated superclasses.
+
+A simple example for an array follows:
+
+::
+
+   //In the .h file:
+   class A2 : public CBase_A2 {
+   private: //My data members:
+       int nt;
+       unsigned char chr;
+       float flt[7];
+       int numDbl;
+       double *dbl;
+   public:
+       //...other declarations
+
+       virtual void pup(PUP::er &p);
+   };
+
+   //In the .C file:
+   void A2::pup(PUP::er &p)
+   {
+       // The runtime will automatically call CBase_A2::pup()
+       p|nt;
+       p|chr;
+       p(flt,7);
+       p|numDbl;
+       if (p.isUnpacking()) dbl=new double[numDbl];
+       p(dbl,numDbl);
+   }
+
+The default assumption, as used in the example above, for the object
+state at PUP time is that a chare, and its member objects, could be
+migrated at any time while it is inactive, i.e. not executing an entry
+method. Actual migration time can be controlled (see
+section :numref:`lbFramework`) to be less frequent. If migration
+timing is fully user controlled, e.g., at the end of a synchronized load
+balancing step, then PUP implementation can be simplified to only
+transport “live” ephemeral data matching the object state which
+coincides with migration. More intricate state based PUPing, for objects
+whose memory footprint varies substantially with computation phase, can
+be handled by explicitly maintaining the object’s phase in a member
+variable and implementing phase conditional logic in the PUP method (see
+section :numref:`sec:pupdynalloc`).
+
+Marshalling User Defined Data Types via PUP
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Parameter marshalling requires serialization and is therefore
+implemented using the PUP framework. User defined data types passed as
+parameters must abide by the standard PUP contract (see section
+:numref:`sec:pupcontract`).
+
+A simple example of using PUP to marshall user defined data types
+follows:
+
+::
+
+   class Buffer {
+   public:
+   //...other declarations
+     void pup(PUP::er &p) {
+       // remember to pup your superclass if there is one
+       p|size;
+       if (p.isUnpacking())
+         data = new int[size];
+       PUParray(p, data, size);
+     }
+
+   private:
+     int size;
+     int *data;
+   };
+
+
+   // In some .ci file
+   entry void process(Buffer &buf);
+
+For efficiency, arrays are always copied as blocks of bytes and passed
+via pointers. This means classes that need their pup routines to be
+called, such as those with dynamically allocated data or virtual methods
+cannot be passed as arrays-use STL vectors to pass lists of complicated
+user-defined classes. For historical reasons, pointer-accessible
+structures cannot appear alone in the parameter list (because they are
+confused with messages).
+
+The order of marshalling operations on the send side is:
+
+-  Call “p\ ``|``\ a” on each marshalled parameter with a sizing
+   PUP::er.
+
+-  Compute the lengths of each array.
+
+-  Call “p\ ``|``\ a” on each marshalled parameter with a packing
+   PUP::er.
+
+-  memcpy each arrays’ data.
+
+The order of marshalling operations on the receive side is:
+
+-  Create an instance of each marshalled parameter using its default
+   constructor.
+
+-  Call “p\ ``|``\ a” on each marshalled parameter using an unpacking
+   PUP::er.
+
+-  Compute pointers into the message for each array.
+
+Finally, very large structures are most efficiently passed via messages,
+because messages are an efficient, low-level construct that minimizes
+copying and overhead; but very complicated structures are often most
+easily passed via marshalling, because marshalling uses the high-level
+pup framework.
+
+See ``examples/charm++/PUP/HeapPUP``
+
+.. _loadbalancing:
+
+Load Balancing
+--------------
+
+Load balancing in Charm++ is enabled by its ability to place, or
+migrate, chares or chare array elements. Typical application usage to
+exploit this feature will construct many more chares than processors,
+and enable their runtime migration.
+
+Iterative applications, which are commonplace in physical simulations,
+are the most suitable target for Charm++’s measurement based load
+balancing techniques. Such applications may contain a series of
+time-steps, and/or iterative solvers that run to convergence. For such
+computations, typically, the heuristic principle that we call “principle
+of persistence” holds: the computational loads and communication
+patterns between objects (chares) tend to persist over multiple
+iterations, even in dynamic applications. In such cases, the recent past
+is a good predictor of the near future. Measurement-based chare
+migration strategies are useful in this context. Currently these apply
+to chare-array elements, but they may be extended to chares in the
+future.
+
+For applications without such iterative structure, or with iterative
+structure, but without predictability (i.e. where the principle of
+persistence does not apply), Charm++ supports “seed balancers” that move
+“seeds” for new chares among processors (possibly repeatedly) to achieve
+load balance. These strategies are currently available for both chares
+and chare-arrays. Seed balancers were the original load balancers
+provided in Charm since the late 80’s. They are extremely useful for
+state-space search applications, and are also useful in other
+computations, as well as in conjunction with migration strategies.
+
+For iterative computations when there is a correlation between
+iterations/steps, but either it is not strong, or the machine
+environment is not predictable (due to noise from OS interrupts on small
+time steps, or time-shared desktop machines), one can use a combination
+of the two kinds of strategies. The baseline load balancing is provided
+by migration strategies, but in each iteration one also spawns off work
+in the form of chares that can run on any processor. The seed balancer
+will handle such work as it arises.
+
+Examples are in ``examples/charm++/load_balancing`` and
+``tests/charm++/load_balancing``
+
+.. _lbFramework:
+
+Measurement-based Object Migration Strategies
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In Charm++, objects (except groups, nodegroups) can migrate from
+processor to processor at runtime. Object migration can potentially
+improve the performance of the parallel program by migrating objects
+from overloaded processors to underloaded ones.
+
+Charm++ implements a generic, measurement-based load balancing framework
+which automatically instruments all Charm++ objects, collects
+computation load and communication structure during execution and stores
+them into a load balancing database. Charm++ then provides a collection
+of load balancing strategies whose job it is to decide on a new mapping
+of objects to processors based on the information from the database.
+Such measurement based strategies are efficient when we can reasonably
+assume that objects in a Charm++ application tend to exhibit temporal
+correlation in their computation and communication patterns, i.e. future
+can be to some extent predicted using the historical measurement data,
+allowing effective measurement-based load balancing without
+application-specific knowledge.
+
+Two key terms in the Charm++ load balancing framework are:
+
+-  Load balancing database provides the interface of almost all load
+   balancing calls. On each processor, it stores the load balancing
+   instrumented data and coordinates the load balancing manager and
+   balancer. It is implemented as a Chare Group called LBDatabase.
+
+-  Load balancer or strategy takes the load balancing database and
+   produces the new mapping of the objects. In Charm++, it is
+   implemented as Chare Group inherited from BaseLB. Three kinds of
+   schemes are implemented: (a) centralized load balancers, (b) fully
+   distributed load balancers and (c) hierarchical load balancers.
+
+.. _lbStrategy:
+
+Available Load Balancing Strategies
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Load balancing can be performed in either a centralized, a fully
+distributed, or an hierarchical fashion.
+
+In centralized approaches, the entire machine’s load and communication
+structure are accumulated to a single point, typically processor 0,
+followed by a decision making process to determine the new distribution
+of Charm++ objects. Centralized load balancing requires synchronization
+which may incur an overhead and delay. However, due to the fact that the
+decision process has a high degree of the knowledge about the entire
+platform, it tends to be more accurate.
+
+In distributed approaches, load data is only exchanged among neighboring
+processors. There is no global synchronization. However, they will not,
+in general, provide an immediate restoration for load balance - the
+process is iterated until the load balance can be achieved.
+
+In hierarchical approaches, processors are divided into independent
+autonomous sets of processor groups and these groups are organized in
+hierarchies, thereby decentralizing the load balancing task. Different
+strategies can be used to balance the load on processors inside each
+processor group, and processors across groups in a hierarchical fashion.
+
+Listed below are some of the available non-trivial centralized load
+balancers and their brief descriptions:
+
+-  **GreedyLB**: Uses a greedy algorithm that always assigns the
+   heaviest object to the least loaded processor.
+
+-  **GreedyRefineLB**: Uses a greedy algorithm that assigns the heaviest
+   object to the least loaded processor when the benefit outweighs the
+   migration cost, otherwise leaves the object on its current processor.
+   It takes an optional command-line argument *+LBPercentMoves*,which
+   specifies the percentage of migrations that can be tolerated.
+
+-  **TopoCentLB**: Extends the greedy algorithm to take processor
+   topology into account.
+
+-  **RefineLB**: Moves objects away from the most overloaded processors
+   to reach average, limits the number of objects migrated.
+
+-  **RefineSwapLB**: Moves objects away from the most overloaded
+   processors to reach average. In case it cannot migrate an object from
+   an overloaded processor to an underloaded processor, it swaps objects
+   to reduce the load on the overloaded processor. This strategy limits
+   the number of objects migrated.
+
+-  **RefineTopoLB**: Same idea as in RefineLB, but takes processor
+   topology into account.
+
+-  **BlockLB**: This strategy does a blocked distribution of objects to
+   processors.
+
+-  **ComboCentLB**: A special load balancer that can be used to combine
+   any number of centralized load balancers mentioned above.
+
+Listed below are some of the communication-aware load balancers:
+
+-  **MetisLB**: Uses `METIS <http://glaros.dtc.umn.edu/gkhome/metis/metis/overview>`__
+   to partition the object communication graph.
+
+-  **ScotchLB**: Uses the `SCOTCH <http://www.labri.fr/perso/pelegrin/scotch/>`__
+   library for partitioning the object
+   communication graph, while also taking object load imbalance into
+   account.
+
+-  **GreedyCommLB**: Extends the greedy algorithm to take the
+   communication graph into account.
+
+-  **RefineCommLB**: Same idea as in RefineLB, but takes communication
+   into account.
+
+Listed below are the distributed load balancers:
+
+-  **NeighborLB**: A neighborhood load balancer in which each processor
+   tries to average out its load only among its neighbors.
+
+-  **WSLB**: A load balancer for workstation clusters, which can detect
+   load changes on desktops (and other timeshared processors) and adjust
+   load without interfering with other’s use of the desktop.
+
+-  **DistributedLB**: A load balancer which uses partial information
+   about underloaded and overloaded processors in the system to do
+   probabilistic transfer of load. This is a refinement based strategy.
+
+An example of a hierarchical strategy can be found in:
+
+-  **HybridLB**: This calls GreedyLB at the lower level and RefineLB at
+   the root.
+
+Listed below are load balancers for debugging purposes:
+
+-  **RandCentLB**: Randomly assigns objects to processors;
+
+-  **RotateLB**: This strategy moves objects to the next available PE
+   every time it is called. It is useful for debugging PUP routines and
+   other migration related bugs.
+
+Users can choose any load balancing strategy they think is appropriate
+for their application. We recommend using GreedyRefineLB with
+applications in general. For applications where the cost of migrating
+objects is very high, say, due to frequent load balancing to handle
+frequent load changes or due to size of data in the object being large,
+a strategy which favors migration minimization at the cost of balance
+(eg: RefineLB) is more suitable. DistributedLB and HybridLB are suitable
+for large number of nodes. Communication-aware load balancers like
+MetisLB and ScotchLB are suitable for communication intensive
+applications. RotateLB and RandCentLB are more useful for debugging
+object migrations. The compiler and runtime options are described in
+section :numref:`lbOption`.
+
+**Metabalancer to automatically schedule load balancing**
+
+Metabalancer can be invoked to automatically decide when to invoke the
+load balancer, given the load-balancing strategy. Metabalancer uses a
+linear prediction model to set the load balancing period based on
+observed load imbalance.
+
+The runtime option *+MetaLB* can be used to invoke this feature to
+automatically invoke the load balancing strategy based on the imbalance
+observed. This option needs to be specified alongside the *+balancer*
+option to specify the load balancing strategy to use. Metabalancer
+relies on the AtSync() calls specified in Section :numref:`lbarray`
+to collect load statistics.
+
+*+MetaLBModelDir* ``<path-to-model>`` can be used to invoke the
+Metabalancer feature to automatically decide which load balancing
+strategy to invoke. A model trained on a generic representative load
+imbalance benchmark can be found in ``charm/src/ck-ldb/rf_model``.
+Metabalancer makes a decision on which load balancing strategy to invoke
+out of a subset of strategies, namely GreedyLB, RefineLB, HybridLB,
+DistributedLB, MetisLB and ScotchLB. For using the model based
+prediction in Metabalancer, Charm++ needs to be built with all the above
+load balancing strategies, including ScotchLB that relies on the
+external partitioning library SCOTCH specified in the
+Section :numref:`lbOption`.
+
+.. _lbarray:
+
+Load Balancing Chare Arrays
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The load balancing framework is well integrated with chare array
+implementation - when a chare array is created, it automatically
+registers its elements with the load balancing framework. The
+instrumentation of compute time (WALL/CPU time) and communication
+pattern is done automatically and APIs are provided for users to trigger
+the load balancing. To use the load balancer, you must make your array
+elements migratable (see migration section above) and choose a load
+balancing strategy (see the section :numref:`lbStrategy` for a
+description of available load balancing strategies).
+
+There are three different ways to use load balancing for chare arrays to
+meet different needs of the applications. These methods are different in
+how and when a load balancing phase starts. The three methods are:
+**periodic load balancing mode**, **at sync mode** and **manual mode**.
+
+In *periodic load balancing mode*, a user specifies only how often load
+balancing is to occur, using +LBPeriod runtime option to specify the
+time interval.
+
+In *at sync mode*, the application invokes the load balancer explicitly
+at appropriate (generally at a pre-existing synchronization boundary) to
+trigger load balancing by inserting a function call (AtSync) in the
+application source code.
+
+In the prior two load balancing modes, users do not need to worry about
+how to start load balancing. However, in one scenario, those automatic
+load balancers will fail to work - when array elements are created by
+dynamic insertion. This is because the above two load balancing modes
+require an application to have fixed the number of objects at the time
+of load balancing. The array manager needs to maintain a head count of
+local array elements for the local barrier. In this case, the
+application must use the *manual mode* to trigger load balancer.
+
+The detailed APIs of these three methods are described as follows:
+
+#. **Periodical load balancing mode**: In the default setting, load
+   balancing happens whenever the array elements are ready, with an
+   interval of 1 second. It is desirable for the application to set a
+   larger interval using +LBPeriod runtime option. For example
+   “+LBPeriod 5.0” can be used to start load balancing roughly every 5
+   seconds. By default, array elements may be asked to migrate at any
+   time, provided that they are not in the middle of executing an entry
+   method. The array element’s variable usesAtSync being false
+   attributes to this default behavior.
+
+#. **At sync mode**: Using this method, elements can be migrated only at
+   certain points in the execution when the application invokes
+   AtSync(). In order to use the at sync mode, one should set usesAtSync
+   to true in the array element constructor. When an element is ready to
+   migrate, call AtSync()  [6]_. When all local elements call AtSync,
+   the load balancer is triggered. Once all migrations are completed,
+   the load balancer calls the virtual function
+   ArrayElement::ResumeFromSync() on each of the array elements. This
+   function can be redefined in the application.
+
+   Note that the minimum time for AtSync() load balancing to occur is
+   controlled by the LBPeriod. Unusually high frequency load balancing
+   (more frequent than 500ms) will perform better if this value is set
+   via +LBPeriod or SetLBPeriod() to a number shorter than your load
+   balancing interval.
+
+   Note that *AtSync()* is not a blocking call, it just gives a hint to
+   load balancing that it is time for load balancing. During the time
+   between *AtSync* and *ResumeFromSync*, the object may be migrated.
+   One can choose to let objects continue working with incoming
+   messages, however keep in mind the object may suddenly show up in
+   another processor and make sure no operations that could possibly
+   prevent migration be performed. This is the automatic way of doing
+   load balancing where the application does not need to define
+   ResumeFromSync().
+
+   The more commonly used approach is to force the object to be idle
+   until load balancing finishes. The user places an AtSync call at the
+   end of some iteration and when all elements reach that call load
+   balancing is triggered. The objects can start executing again when
+   ResumeFromSync() is called. In this case, the user redefines
+   ResumeFromSync() to trigger the next iteration of the application.
+   This manual way of using the at sync mode results in a barrier at
+   load balancing (see example here :numref:`lbexample`).
+
+#. **Manual mode**: The load balancer can be programmed to be started
+   manually. To switch to the manual mode, the application calls
+   *TurnManualLBOn()* on every processor to prevent the load balancer
+   from starting automatically. *TurnManualLBOn()* should be called as
+   early as possible in the program. It could be called at the
+   initialization part of the program, for example from a global
+   variable constructor, or in an initproc call
+   (Section :numref:`initproc`). It can also be called in the
+   constructor of a static array or before the *doneInserting* call for
+   a dynamic array. It can be called multiple times on one processor,
+   but only the last one takes effect.
+
+   The function call *CkStartLB()* starts load balancing immediately.
+   This call should be made at only one place on only one processor.
+   This function is not blocking, the object will continue to process
+   messages and the load balancing, when triggered, happens in the
+   background.
+
+   *TurnManualLBOff()* turns off manual load balancing and switches back
+   to the automatic load balancing mode.
+
+.. _lbmigobj:
+
+Migrating objects
+~~~~~~~~~~~~~~~~~
+
+Load balancers migrate objects automatically. For an array element to
+migrate, user can refer to Section :numref:`arraymigratable` for how
+to write a “pup” for an array element.
+
+In general one needs to pack the whole snapshot of the member data in an
+array element in the pup subroutine. This is because the migration of
+the object may happen at any time. In certain load balancing schemes
+where the user explicitly controls when load balancing occurs, the user
+may choose to pack only a part of the data and may skip temporary data.
+
+An array element can migrate by calling the migrateMe(destination
+processor) member function- this call must be the last action in an
+element entry method. The system can also migrate array elements for
+load balancing (see the section :numref:`lbarray`).
+
+To migrate your array element to another processor, the Charm++ runtime
+will:
+
+-  Call your ckAboutToMigrate method
+
+-  Call your pup method with a sizing PUP::er to determine how big a
+   message it needs to hold your element.
+
+-  Call your pup method again with a packing PUP::er to pack your
+   element into a message.
+
+-  Call your element’s destructor (deleting the old copy).
+
+-  Send the message (containing your element) across the network.
+
+-  Call your element’s migration constructor on the new processor.
+
+-  Call your pup method on with an unpacking PUP::er to unpack the
+   element.
+
+-  Call your ckJustMigrated method
+
+Migration constructors, then, are normally empty- all the unpacking and
+allocation of the data items is done in the element’s pup routine.
+Deallocation is done in the element destructor as usual.
+
+Other utility functions
+~~~~~~~~~~~~~~~~~~~~~~~
+
+There are several utility functions that can be called in applications
+to configure the load balancer, etc. These functions are:
+
+-  **LBTurnInstrumentOn()** and **LBTurnInstrumentOff()**: are plain C
+   functions to control the load balancing statistics instrumentation on
+   or off on the calling processor. No implicit broadcast or
+   synchronization exists in these functions. Fortran interface:
+   **FLBTURNINSTRUMENTON()** and **FLBTURNINSTRUMENTOFF()**.
+
+-  **setMigratable(bool migratable)**: is a member function of array
+   element. This function can be called in an array element constructor
+   to tell the load balancer whether this object is migratable or
+   not [7]_.
+
+-  **LBSetPeriod(double s)**: this function can be called anywhere (even
+   in Charm++ initnodes or initprocs) to specify the load balancing
+   period time in seconds. It tells load balancer not to start next load
+   balancing in less than :math:`s` seconds. This can be used to prevent
+   load balancing from occurring too often in *automatic without sync
+   mode*. Here is how to use it:
+
+   ::
+
+      // if used in an array element
+      LBDatabase *lbdb = getLBDB();
+      lbdb->SetLBPeriod(5.0);
+
+      // if used outside of an array element
+      LBSetPeriod(5.0);
+
+   Alternatively, one can specify +LBPeriod {seconds} at command line.
+
+.. _lbOption:
+
+Compiler and runtime options to use load balancing module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Load balancing strategies are implemented as libraries in Charm++. This
+allows programmers to easily experiment with different existing
+strategies by simply linking a pool of strategy modules and choosing one
+to use at runtime via a command line option.
+
+**Note:** linking a load balancing module is different from activating
+it:
+
+-  link an LB module: is to link a Load Balancer module(library) at
+   compile time. You can link against multiple LB libraries as
+   candidates.
+
+-  activate an LB: is to actually ask the runtime to create an LB
+   strategy and start it. You can only activate load balancers that have
+   been linked at compile time.
+
+Below are the descriptions about the compiler and runtime options:
+
+#. **compile time options:**
+
+   -  | *-module NeighborLB -module GreedyCommLB ...*
+      | links the modules NeighborLB, GreedyCommLB etc into an
+        application, but these load balancers will remain inactive at
+        execution time unless overridden by other runtime options.
+
+   -  | *-module CommonLBs*
+      | links a special module CommonLBs which includes some commonly
+        used Charm++ built-in load balancers. The commonly used load
+        balancers include
+        ``DummyLB, GreedyLB, GreedyRefineLB, CommLB, RandCentLB, RefineLB, RefineCommLB, RotateLB, DistributedLB, HybridLB, ComboCentLB, RefineSwapLB, NeighborLB, OrbLB, BlockLB, GreedyCommLB``
+
+   -  | *-balancer GreedyCommLB*
+      | links the load balancer GreedyCommLB and invokes it at runtime.
+
+   -  | *-balancer GreedyCommLB -balancer RefineLB*
+      | invokes GreedyCommLB at the first load balancing step and
+        RefineLB in all subsequent load balancing steps.
+
+   -  | *-balancer ComboCentLB:GreedyLB,RefineLB*
+      | You can create a new combination load balancer made of multiple
+        load balancers. In the above example, GreedyLB and RefineLB
+        strategies are applied one after the other in each load
+        balancing step.
+
+   The list of existing load balancers is given in Section
+   :numref:`lbStrategy`. Note: you can have multiple -module \*LB
+   options. LB modules are linked into a program, but they are not
+   activated automatically at runtime. Using -balancer A at compile time
+   will activate load balancer A automatically at runtime. Having
+   -balancer A implies -module A, so you don’t have to write -module A
+   again, although that is not invalid. Using CommonLBs is a convenient
+   way to link against the commonly used existing load balancers.
+
+   The SCOTCH-based load balancer(s) use an external partitioning
+   library requiring 3rd party software:
+
+   SCOTCH can be downloaded from:
+   http://www.labri.fr/perso/pelegrin/scotch/
+
+   Use the *-incdir and -libdir* build time option to add your
+   installation of any third party libraries you wish to use to the
+   Charm++ search paths.
+
+#. **Building individual load balancers**
+
+   Load balancers can be built individually by changing the current
+   working directory to the *tmp* subdirectory of your build and making
+   them by name.
+
+   ::
+
+       cd netlrts-linux-x86_64/tmp
+       make PhasebyArrayLB
+
+#. **Write and use your own load balancer**
+
+   Refer Section :numref:`lbWriteNewLB` for writing a new load
+   balancer. Compile it in the form of library and name it
+   *libmoduleFooLB.a* where *FooLB* is the new load balancer. Add the
+   path to the library and link the load balancer into an application
+   using *-module FooLB*.
+
+   You can create a library by modifying the Makefile in the following
+   way. This will create *libmoduleFooLB.a*.
+
+   .. code-block:: makefile
+
+      libmoduleFooLB.a: FooLB.o
+        $(CHARMC) -o libmoduleFooLB.a FooLB.o
+
+   To include this balancer in your application, the Makefile can be
+   changed in the following way
+
+   .. code-block:: makefile
+
+      $(TARGET): $(OBJECTS)
+        $(CHARMC) -o $(TARGET) -L/path-to-the-lib $(OBJS) -module FooLB
+
+#. **runtime options:**
+
+   Runtime balancer selection options are similar to the compile time
+   options as described above, but they can be used to override those
+   compile time options.
+
+   -  | *+balancer help*
+      | displays all available balancers that have been linked in.
+
+   -  | *+balancer GreedyCommLB*
+      | invokes GreedyCommLB
+
+   -  | *+balancer GreedyCommLB +balancer RefineLB*
+      | invokes GreedyCommLB at the first load balancing step and
+        RefineLB in all subsequent load balancing steps.
+
+   -  | *+balancer ComboCentLB:GreedyLB,RefineLB*
+      | same as the example in the -balancer compile time option.
+
+   Note: +balancer option works only if you have already linked the
+   corresponding load balancers module at compile time. Giving +balancer
+   with a wrong LB name will result in a runtime error. When you have
+   used -balancer A as compile time option, you do not need to use
+   +balancer A again to activate it at runtime. However, you can use
+   +balancer B to override the compile time option and choose to
+   activate B instead of A.
+
+#. **Handling the case that no load balancer is activated by users**
+
+   When no balancer is linked by users, but the program counts on a load
+   balancer because it used *AtSync()* and expect *ResumeFromSync()* to
+   be called to continue, a special load balancer called *NullLB* will
+   be automatically created to run the program. This default load
+   balancer calls *ResumeFromSync()* after *AtSync()*. It keeps a
+   program from hanging after calling *AtSync()*. *NullLB* will be
+   suppressed if another load balancer is created.
+
+#. **Other useful runtime options**
+
+   There are a few other runtime options for load balancing that may be
+   useful:
+
+   -  | *+LBDebug {verbose level}*
+      | {verbose level} can be any positive integer number. 0 is to turn
+        off the verbose. This option asks load balancer to output load
+        balancing information to stdout. The bigger the verbose level
+        is, the more verbose the output is.
+
+   -  | *+LBPeriod {seconds}*
+      | {Seconds} can be any float number. This option sets the minimum
+        period time in seconds between two consecutive load balancing
+        steps. The default value is 1 second. That is to say that a load
+        balancing step will not happen until 1 second after the last
+        load balancing step.
+
+   -  | *+LBSameCpus*
+      | This option simply tells load balancer that all processors are
+        of same speed. The load balancer will then skip the measurement
+        of CPU speed at runtime. This is the default.
+
+   -  | *+LBTestPESpeed*
+      | This option tells the load balancer to test the speed of all
+        processors at runtime. The load balancer may use this
+        measurement to perform speed-aware load balancing.
+
+   -  | *+LBObjOnly*
+      | This tells load balancer to ignore processor background load
+        when making migration decisions.
+
+   -  | *+LBSyncResume*
+      | After load balancing step, normally a processor can resume
+        computation once all objects are received on that processor,
+        even when other processors are still working on migrations. If
+        this turns out to be a problem, that is when some processors
+        start working on computation while the other processors are
+        still busy migrating objects, then this option can be used to
+        force a global barrier on all processors to make sure that
+        processors can only resume computation after migrations are
+        completed on all processors.
+
+   -  | *+LBOff*
+      | This option turns off load balancing instrumentation of both CPU
+        and communication usage at startup time.
+
+   -  | *+LBCommOff*
+      | This option turns off load balancing instrumentation of
+        communication at startup time. The instrument of CPU usage is
+        left on.
+
+.. _seedlb:
+
+Seed load balancers - load balancing Chares at creation time
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Seed load balancing involves the movement of object creation messages,
+or "seeds", to create a balance of work across a set of processors. This
+seed load balancing scheme is used to balance chares at creation time.
+After the chare constructor is executed on a processor, the seed
+balancer does not migrate it. Depending on the movement strategy,
+several seed load balancers are available now. Examples can be found
+``examples/charm++/NQueen``.
+
+#. | *random*
+   | A strategy that places seeds randomly when they are created and
+     does no movement of seeds thereafter. This is used as the default
+     seed load balancer.
+
+#. | *neighbor*
+   | A strategy which imposes a virtual topology on the processors, load
+     exchange happens among neighbors only. The overloaded processors
+     initiate the load balancing and send work to its neighbors when it
+     becomes overloaded. The default topology is mesh2D, one can use
+     command line option to choose other topology such as ring, mesh3D
+     and dense graph.
+
+#. | *spray*
+   | A strategy which imposes a spanning tree organization on the
+     processors, results in communication via global reduction among all
+     processors to compute global average load via periodic reduction.
+     It uses averaging of loads to determine how seeds should be
+     distributed.
+
+#. | *workstealing*
+   | A strategy that the idle processor requests a random processor and
+     steal chares.
+
+Other strategies can also be explored by following the simple API of the
+seed load balancer.
+
+**Compile and run time options for seed load balancers**
+
+To choose a seed load balancer other than the default *rand* strategy,
+use link time command line option **-balance foo**.
+
+When using neighbor seed load balancer, one can also specify the virtual
+topology at runtime. Use **+LBTopo topo**, where *topo* can be one of:
+(a) ring, (b) mesh2d, (c) mesh3d and (d) graph.
+
+To write a seed load balancer, name your file as *cldb.foo.c*, where
+*foo* is the strategy name. Compile it in the form of library under
+charm/lib, named as *libcldb-foo.a*, where *foo* is the strategy name
+used above. Now one can use **-balance foo** as compile time option to
+**charmc** to link with the *foo* seed load balancer.
+
+.. _lbexample:
+
+Simple Load Balancer Usage Example - Automatic with Sync LB
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A simple example of how to use a load balancer in sync mode in one’s
+application is presented below.
+
+::
+
+   /*** lbexample.ci ***/
+   mainmodule lbexample {
+     readonly CProxy_Main mainProxy;
+     readonly int nElements;
+
+     mainchare Main {
+       entry Main(CkArgMsg *m);
+       entry void done(void);
+     };
+
+     array [1D] LBExample {
+       entry LBExample(void);
+       entry void doWork();
+     };
+   };
+
+——————————————————————————-
+
+::
+
+   /*** lbexample.C ***/
+   #include <stdio.h>
+   #include "lbexample.decl.h"
+
+   /*readonly*/ CProxy_Main mainProxy;
+   /*readonly*/ int nElements;
+
+   #define MAX_WORK_CNT 50
+   #define LB_INTERVAL 5
+
+   /*mainchare*/
+   class Main : public CBase_Main
+   {
+   private:
+     int count;
+   public:
+     Main(CkArgMsg* m)
+     {
+       /*....Initialization....*/
+       mainProxy = thisProxy;
+       CProxy_LBExample arr = CProxy_LBExample::ckNew(nElements);
+       arr.doWork();
+     };
+
+     void done(void)
+     {
+       count++;
+       if(count==nElements){
+         CkPrintf("All done");
+         CkExit();
+       }
+     };
+   };
+
+   /*array [1D]*/
+   class LBExample : public CBase_LBExample
+   {
+   private:
+     int workcnt;
+   public:
+     LBExample()
+     {
+       workcnt=0;
+       /* May initialize some variables to be used in doWork */
+       //Must be set to true to make AtSync work
+       usesAtSync = true;
+     }
+
+     LBExample(CkMigrateMessage *m) { /* Migration constructor -- invoked when chare migrates */ }
+
+     /* Must be written for migration to succeed */
+     void pup(PUP::er &p){
+       p|workcnt;
+       /* There may be some more variables used in doWork */
+     }
+
+     void doWork()
+     {
+       /* Do work proportional to the chare index to see the effects of LB */
+
+       workcnt++;
+       if(workcnt==MAX_WORK_CNT)
+         mainProxy.done();
+
+       if(workcnt%LB_INTERVAL==0)
+         AtSync();
+       else
+         doWork();
+     }
+
+     void ResumeFromSync(){
+       doWork();
+     }
+   };
+
+   #include "lbexample.def.h"
+
+Processor-Aware Chare Collections
+---------------------------------
+
+So far, we have discussed chares separately from the underlying hardware
+resources to which they are mapped. However, for writing lower-level
+libraries or optimizing application performance it is sometimes useful
+to create chare collections where a single chare is mapped per specified
+resource used in the run. The group  [8]_ and node group constructs
+provide this facility by creating a collection of chares with a single
+chare (or branch) on each PE (in the case of groups) or process (for
+node groups).
+
+.. _sec:group:
+
+Group Objects
+~~~~~~~~~~~~~
+
+Groups have a definition syntax similar to normal chares, and they have
+to inherit from the system-defined class CBase_ClassName, where
+ClassName is the name of the group’s C++ class  [9]_.
+
+Group Definition
+^^^^^^^^^^^^^^^^
+
+In the interface (``.ci``) file, we declare
+
+::
+
+   group Foo {
+     // Interface specifications as for normal chares
+
+     // For instance, the constructor ...
+     entry Foo(parameters1);
+
+     // ... and an entry method
+     entry void someEntryMethod(parameters2);
+   };
+
+The definition of the ``Foo`` class is given in the ``.h`` file, as
+follows:
+
+::
+
+   class Foo : public CBase_Foo {
+     // Data and member functions as in C++
+     // Entry functions as for normal chares
+
+     public:
+       Foo(parameters1);
+       void someEntryMethod(parameters2);
+   };
+
+.. _sec:groups/creation:
+
+Group Creation
+^^^^^^^^^^^^^^
+
+Groups are created using ckNew like chares and chare arrays. Given the
+declarations and definitions of group ``Foo`` from above, we can create
+a group in the following manner:
+
+::
+
+   CProxy_Foo fooProxy = CProxy_Foo::ckNew(parameters1);
+
+One can also use ckNew to get a CkGroupID as shown below:
+
+::
+
+   CkGroupID fooGroupID = CProxy_Foo::ckNew(parameters1);
+
+A CkGroupID is useful to specify dependence in group creations using
+CkEntryOptions. For example, in the following code, the creation of
+group ``GroupB`` on each PE depends on the creation of ``GroupA`` on
+that PE.
+
+::
+
+   // Create GroupA
+   CkGroupID groupAID = CProxy_GroupA::ckNew(parameters1);
+
+   // Create GroupB. However, for each PE, do this only
+   // after GroupA has been created on it
+
+   // Specify the dependency through a `CkEntryOptions' object
+   CkEntryOptions opts;
+   opts.setGroupDepID(groupAId);
+
+   // The last argument to `ckNew' is the `CkEntryOptions' object from above
+   CkGroupID groupBID = CProxy_GroupB::ckNew(parameters2, opts);
+
+Note that there can be several instances of each group type. In such a
+case, each instance has a unique group identifier, and its own set of
+branches.
+
+Method Invocation on Groups
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+An asynchronous entry method can be invoked on a particular branch of a
+group through a proxy of that group. If we have a group with a proxy
+``fooProxy`` and we wish to invoke entry method ``someEntryMethod`` on
+that branch of the group which resides on PE ``somePE``, we would
+accomplish this with the following syntax:
+
+::
+
+   fooProxy[somePE].someEntryMethod(parameters);
+
+This call is asynchronous and non-blocking; it returns immediately after
+sending the message. A message may be broadcast to all branches of a
+group (i.e., to all PEs) using the notation :
+
+::
+
+   fooProxy.anotherEntryMethod(parameters);
+
+This invokes entry method anotherEntryMethod with the given parameters
+on all branches of the group. This call is also asynchronous and
+non-blocking, and it, too, returns immediately after sending the
+message.
+
+Recall that each PE hosts a branch of every instantiated group.
+Sequential objects, chares and other groups can gain access to this
+*PE-local* branch using ckLocalBranch():
+
+::
+
+   GroupType *g=groupProxy.ckLocalBranch();
+
+This call returns a regular C++ pointer to the actual object (not a proxy)
+referred to by the proxy groupProxy. Once a proxy to the local branch of
+a group is obtained, that branch can be accessed as a regular C++ object.
+Its public methods can return values, and its public data is readily
+accessible.
+
+Let us end with an example use-case for groups. Suppose that we have a
+task-parallel program in which we dynamically spawn new chares.
+Furthermore, assume that each one of these chares has some data to send
+to the mainchare. Instead of creating a separate message for each
+chare’s data, we create a group. When a particular chare finishes its
+work, it reports its findings to the local branch of the group. When all
+the chares on a PE have finished their work, the local branch can send a
+single message to the main chare. This reduces the number of messages
+sent to the mainchare from the number of chares created to the number of
+processors.
+
+For a more concrete example on how to use groups, please refer to
+``examples/charm++/histogram_group``. It presents a parallel
+histogramming operation in which chare array elements funnel their bin
+counts through a group, instead of contributing directly to a reduction
+across all chares.
+
+NodeGroup Objects
+~~~~~~~~~~~~~~~~~
+
+The *node group* construct is similar to the group construct discussed
+above. Rather than having one chare per PE, a node group is a collection
+of chares with one chare per *process*, or *logical node*. Therefore,
+each logical node hosts a single branch of the node group. As with
+groups, node groups can be addressed via globally unique identifiers.
+Nonetheless, there are significant differences in the semantics of node
+groups as compared to groups and chare arrays. When an entry method of a
+node group is executed on one of its branches, it executes on *some* PE
+within the logical node. Also, multiple entry method calls can execute
+concurrently on a single node group branch. This makes node groups
+significantly different from groups and requires some care when using
+them.
+
+NodeGroup Declaration
+^^^^^^^^^^^^^^^^^^^^^
+
+Node groups are defined in a similar way to groups.  [10]_ For example,
+in the interface file, we declare:
+
+::
+
+    nodegroup NodeGroupType {
+     // Interface specifications as for normal chares
+    };
+
+In the ``.h`` file, we define NodeGroupType as follows:
+
+::
+
+    class NodeGroupType : public CBase_NodeGroupType {
+     // Data and member functions as in C++
+     // Entry functions as for normal chares
+    };
+
+Like groups, NodeGroups are identified by a globally unique identifier
+of type CkGroupID. Just as with groups, this identifier is common to all
+branches of the NodeGroup, and can be obtained from the inherited data
+member thisgroup. There can be many instances corresponding to a single
+NodeGroup type, and each instance has a different identifier, and its
+own set of branches.
+
+Method Invocation on NodeGroups
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+As with chares, chare arrays and groups, entry methods are invoked on
+NodeGroup branches via proxy objects. An entry method may be invoked on
+a *particular* branch of a nodegroup by specifying a *logical node
+number* argument to the square bracket operator of the proxy object. A
+broadcast is expressed by omitting the square bracket notation. For
+completeness, example syntax for these two cases is shown below:
+
+::
+
+    // Invoke `someEntryMethod' on the i-th logical node of
+    // a NodeGroup whose proxy is `myNodeGroupProxy':
+    myNodeGroupProxy[i].someEntryMethod(parameters);
+
+    // Invoke `someEntryMethod' on all logical nodes of
+    // a NodeGroup whose proxy is `myNodeGroupProxy':
+    myNodeGroupProxy.someEntryMethod(parameters);
+
+It is worth restating that when an entry method is invoked on a
+particular branch of a nodegroup, it may be executed by *any* PE in that
+logical node. Thus two invocations of a single entry method on a
+particular branch of a NodeGroup may be executed *concurrently* by two
+different PEs in the logical node. If this could cause data races in
+your program, please consult § :numref:`sec:nodegroups/exclusive`
+(below).
+
+.. _sec:nodegroups/exclusive:
+
+NodeGroups and exclusive Entry Methods
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Node groups may have exclusive entry methods. The execution of an
+exclusive entry method invocation is *mutually exclusive* with those of
+all other exclusive entry methods invocations. That is, an exclusive
+entry method invocation is not executed on a logical node as long as
+another exclusive entry method is executing on it. More explicitly, if a
+method M of a nodegroup NG is marked exclusive, it means that while an
+instance of M is being executed by a PE within a logical node, no other
+PE within that logical node will execute any other *exclusive* methods.
+However, PEs in the logical node may still execute *non-exclusive* entry
+method invocations. An entry method can be marked exclusive by tagging
+it with the exclusive attribute, as explained in
+§ :numref:`attributes`.
+
+Accessing the Local Branch of a NodeGroup
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The local branch of a NodeGroup NG, and hence its member fields and
+methods, can be accessed through the method NG\*
+CProxy_NG::ckLocalBranch() of its proxy. Note that accessing data
+members of a NodeGroup branch in this manner is *not* thread-safe by
+default, although you may implement your own mutual exclusion schemes to
+ensure safety. One way to ensure safety is to use node-level locks,
+which are described in the Converse manual.
+
+NodeGroups can be used in a similar way to groups so as to implement
+lower-level optimizations such as data sharing and message reduction.
+
+Initializations at Program Startup
+----------------------------------
+
+.. _initnode:
+.. _initproc:
+
+initnode and initproc Routines
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some registration routines need be executed
+exactly once before the computation begins. You may choose to declare a
+regular C++ subroutine initnode in the .ci file to ask Charm++ to execute
+the routine exactly once on *every logical node* before the computation
+begins, or to declare a regular C++ subroutine initproc to be executed
+exactly once on *every PE*.
+
+::
+
+   module foo {
+       initnode void fooNodeInit(void);
+       initproc void fooProcInit(void);
+       chare bar {
+           ...
+           initnode void barNodeInit(void);
+           initproc void barProcInit(void);
+       };
+   };
+
+This code will execute the routines fooNodeInit and static
+bar::barNodeInit once on every logical node and fooProcInit and
+bar::barProcInit on every PE before the main computation starts.
+Initnode calls are always executed before initproc calls. Both init
+calls (declared as static member functions) can be used in chares, chare
+arrays and groups.
+
+Note that these routines should only implement registration and startup
+functionality, and not parallel computation, since the Charm++ run time
+system will not have started up fully when they are invoked. In order to
+begin the parallel computation, you should use a mainchare instead,
+which gets executed on only PE 0.
+
+Event Sequence During Charm++ Startup
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+At startup, every Charm++ program performs the following actions, in
+sequence:
+
+#. Module Registration: all modules given in the .ci files are
+   registered in the order of their specification in the linking stage
+   of program compilation. For example, if you specified
+   “``-module A -module B``” while linking your Charm++ program, then
+   module ``A`` is registered before module ``B`` at runtime.
+
+#. initnode, initproc Calls: all initnode and initproc functions are
+   invoked before the creation of Charm++ data structures, and before
+   the invocation of any mainchares’ main() methods.
+
+#. readonly Variables: readonly variables are initialized on PE 0 in the
+   mainchare, following program order as given in the ``main()`` method.
+   After initialization, they are broadcast to all other PEs making them
+   available in the constructors groups, chares, chare arrays, etc. (see
+   below.)
+
+#. Group and NodeGroup Creation: on PE 0, constructors of these objects
+   are invoked in program order. However, on all other PEs, their
+   creation is triggered by messages. Since message order is not
+   guaranteed in Charm++ program, constructors of groups and nodegroups
+   should **not** depend on other Group or NodeGroup objects on a PE.
+   However, if your program structure requires it, you can explicitly
+   specify that the creation of certain Groups/NodeGroups depends on the
+   creation of others, as described in
+   § :numref:`sec:groups/creation`. In addition, since those
+   objects are initialized after the initialization of readonly
+   variables, readonly variables can be used in the constructors of
+   Groups and NodeGroups.
+
+#. Charm++ Array Creation: the order in which array constructors are
+   called on PEs is similar to that described for groups and nodegroups,
+   above. Therefore, the creation of one array should **not** depend on
+   other arrays. As Array objects are initialized last, their
+   constructors can use readonly variables and local branches of Group
+   or NodeGroup objects.
+
+Advanced Programming Techniques
+===============================
+
+Optimizing Entry Method Invocation
+----------------------------------
+
+.. _messages:
+
+Messages
+~~~~~~~~
+
+Although Charm++ supports automated parameter marshalling for entry
+methods, you can also manually handle the process of packing and
+unpacking parameters by using messages. A message encapsulates all the
+parameters sent to an entry method. Since the parameters are already
+encapsulated, sending messages is often more efficient than parameter
+marshalling, and can help to avoid unnecessary copying. Moreover, assume
+that the receiver is unable to process the contents of the message at
+the time that it receives it. For example, consider a tiled matrix
+multiplication program, wherein each chare receives an :math:`A`-tile
+and a :math:`B`-tile before computing a partial result for
+:math:`C = A \times B`. If we were using parameter marshalled entry
+methods, a chare would have to copy the first tile it received, in order
+to save it for when it has both the tiles it needs. Then, upon receiving
+the second tile, the chare would use the second tile and the first
+(saved) tile to compute a partial result. However, using messages, we
+would just save a *pointer* to the message encapsulating the tile
+received first, instead of the tile data itself.
+
+**Managing the memory buffer associated with a message.** As suggested
+in the example above, the biggest difference between marshalled
+parameters and messages is that an entry method invocation is assumed to
+*keep* the message that it is passed. That is, the Charm++ runtime
+system assumes that code in the body of the invoked entry method will
+explicitly manage the memory associated with the message that it is
+passed. Therefore, in order to avoid leaking memory, the body of an
+entry method must either delete the message that it is receives, or save
+a pointer to it, and delete it a later point in the execution of the
+code.
+
+Moreover, in the Charm++ execution model, once you pass a message buffer
+to the runtime system (via an asynchronous entry method invocation), you
+should *not* reuse the buffer. That is, after you have passed a message
+buffer into an asynchronous entry method invocation, you shouldn’t
+access its fields, or pass that same buffer into a second entry method
+invocation. Note that this rule doesn’t preclude the *single reuse* of
+an input message - consider an entry method invocation :math:`i_1`,
+which receives as input the message buffer :math:`m_1`. Then,
+:math:`m_1` may be passed to an asynchronous entry method invocation
+:math:`i_2`. However, once :math:`i_2` has been issued with :math:`m_1`
+as its input parameter, :math:`m_1` cannot be used in any further entry
+method invocations.
+
+Several kinds of message are available. Regular Charm++ messages are
+objects of *fixed size*. One can have messages that contain pointers or
+variable length arrays (arrays with sizes specified at runtime) and
+still have these pointers as valid when messages are sent across
+processors, with some additional coding. Also available is a mechanism
+for assigning *priorities* to a message regardless of its type. A
+detailed discussion of priorities appears later in this section.
+
+Message Types
+^^^^^^^^^^^^^
+
+**Fixed-Size Messages.** The simplest type of message is a *fixed-size*
+message. The size of each data member of such a message should be known
+at compile time. Therefore, such a message may encapsulate primitive
+data types, user-defined data types that *don’t* maintain pointers to
+memory locations, and *static* arrays of the aforementioned types.
+
+**Variable-Size Messages.** Very often, the size of the data contained
+in a message is not known until runtime. For such scenarios, you can use
+variable-size (*varsize*) messages. A *varsize* message can encapsulate
+several arrays, each of whose size is determined at run time. The space
+required for these encapsulated, variable length arrays is allocated
+with the entire message comprises a contiguous buffer of memory.
+
+**Packed Messages.** A *packed* message is used to communicate
+non-linear data structures via messages. However, we defer a more
+detailed description of their use to
+§ :numref:`sec:messages/packed_msgs`.
+
+Using Messages In Your Program
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There are five steps to incorporating a (fixed or varsize) message type
+in your Charm++ program: (1) Declare message type in .ci file; (2)
+Define message type in .h file; (3) Allocate message; (4) Pass message
+to asynchronous entry method invocation and (5) Deallocate message to
+free associated memory resources.
+
+**Declaring Your Message Type.** Like all other entities involved in
+asynchronous entry method invocation, messages must be declared in the
+``.ci`` file. This allows the Charm++ translator to generate support
+code for messages. Message declaration is straightforward for fixed-size
+messages. Given a message of type ``MyFixedSizeMsg``, simply include the
+following in the .ci file:
+
+::
+
+    message MyFixedSizeMsg;
+
+For varsize messages, the .ci declaration must also include the names
+and types of the variable-length arrays that the message will
+encapsulate. The following example illustrates this requirement. In it,
+a message of type ``MyVarsizeMsg``, which encapsulates three
+variable-length arrays of different types, is declared:
+
+::
+
+    message MyVarsizeMsg {
+      int arr1[];
+      double arr2[];
+      MyPointerlessStruct arr3[];
+    };
+
+**Defining Your Message Type.** Once a message type has been declared to
+the Charm++ translator, its type definition must be provided. Your
+message type must inherit from a specific generated base class. If the
+type of your message is ``T``, then ``class T`` must inherit from
+``CMessage_T``. This is true for both fixed and varsize messages. As an
+example, for our fixed size message type ``MyFixedSizeMsg`` above, we
+might write the following in the .h file:
+
+::
+
+   class MyFixedSizeMsg : public CMessage_MyFixedSizeMsg {
+     int var1;
+     MyPointerlessStruct var2;
+     double arr3[10];
+
+     // Normal C++ methods, constructors, etc. go here
+   };
+
+In particular, note the inclusion of the static array of ``double``\ s,
+``arr3``, whose size is known at compile time to be that of ten
+``double``\ s. Similarly, for our example varsize message of type
+``MyVarsizeMsg``, we would write something like:
+
+::
+
+   class MyVarsizeMsg : public CMessage_MyVarsizeMsg {
+     // variable-length arrays
+     int *arr1;
+     double *arr2;
+     MyPointerlessStruct *arr3;
+
+     // members that are not variable-length arrays
+     int x,y;
+     double z;
+
+     // Normal C++ methods, constructors, etc. go here
+   };
+
+Note that the .h definition of the class type must contain data members
+whose names and types match those specified in the .ci declaration. In
+addition, if any of data members are private or protected, it should
+declare class CMessage_MyVarsizeMsg to be a friend class. Finally, there
+are no limitations on the member methods of message classes, except that
+the message class may not redefine operators ``new`` or ``delete``.
+
+Thus the mtype class declaration should be similar to:
+
+**Creating a Message.** With the .ci declaration and .h definition in
+place, messages can be allocated and used in the program. Messages are
+allocated using the C++ new operator:
+
+::
+
+    MessageType *msgptr =
+     new [(int sz1, int sz2, ... , int priobits=0)] MessageType[(constructor arguments)];
+
+The arguments enclosed within the square brackets are optional, and are
+used only when allocating messages with variable length arrays or
+prioritized messages. These arguments are not specified for fixed size
+messages. For instance, to allocate a message of our example message
+``MyFixedSizeMsg``, we write:
+
+::
+
+   MyFixedSizeMsg *msg = new MyFixedSizeMsg(<constructor args>);
+
+In order to allocate a varsize message, we must pass appropriate values
+to the arguments of the overloaded new operator presented previously.
+Arguments sz1, sz2, ... denote the size (in number of elements) of the
+memory blocks that need to be allocated and assigned to the pointers
+(variable-length arrays) that the message contains. The priobits
+argument denotes the size of a bitvector (number of bits) that will be
+used to store the message priority. So, if we wanted to create
+``MyVarsizeMsg`` whose ``arr1``, ``arr2`` and ``arr3`` arrays contain
+10, 20 and 7 elements of their respective types, we would write:
+
+::
+
+   MyVarsizeMsg *msg = new (10, 20, 7) MyVarsizeMsg(<constructor args>);
+
+Further, to add a 32-bit priority bitvector to this message, we would
+write:
+
+::
+
+   MyVarsizeMsg *msg = new (10, 20, 7, sizeof(uint32_t)*8) VarsizeMessage;
+
+Notice the last argument to the overloaded new operator, which specifies
+the number of bits used to store message priority. The section on
+prioritized execution (§ :numref:`prioritized message passing`)
+describes how priorities can be employed in your program.
+
+Another version of the overloaded new operator allows you to pass in an
+array containing the size of each variable-length array, rather than
+specifying individual sizes as separate arguments. For example, we could
+create a message of type ``MyVarsizeMsg`` in the following manner:
+
+::
+
+   int sizes[3];
+   sizes[0] = 10;               // arr1 will have 10 elements
+   sizes[1] = 20;               // arr2 will have 20 elements
+   sizes[2] = 7;                // arr3 will have 7 elements
+
+   MyVarsizeMsg *msg = new(sizes, 0) MyVarsizeMsg(<constructor args>); // 0 priority bits
+
+**Sending a Message.** Once we have a properly allocated message, we can
+set the various elements of the encapsulated arrays in the following
+manner:
+
+::
+
+     msg->arr1[13] = 1;
+     msg->arr2[5] = 32.82;
+     msg->arr3[2] = MyPointerlessStruct();
+     // etc.
+
+And pass it to an asynchronous entry method invocation, thereby sending
+it to the corresponding chare:
+
+::
+
+   myChareArray[someIndex].foo(msg);
+
+When a message is *sent*, i.e. passed to an asynchronous entry method
+invocation, the programmer relinquishes control of it; the space
+allocated for the message is freed by the runtime system. However, when
+a message is *received* at an entry point, it is *not* freed by the
+runtime system. As mentioned at the start of this section, received
+messages may be reused or deleted by the programmer. Finally, messages
+are deleted using the standard C++ delete operator.
+
+.. _message packing:
+
+Message Packing
+^^^^^^^^^^^^^^^
+
+The Charm++ interface translator generates implementation for three
+static methods for the message class CMessage_mtype. These methods have
+the prototypes:
+
+::
+
+       static void* alloc(int msgnum, size_t size, int* array, int priobits);
+       static void* pack(mtype*);
+       static mtype* unpack(void*);
+
+One may choose not to use the translator-generated methods and may
+override these implementations with their own alloc, pack and unpack
+static methods of the mtype class. The alloc method will be called when
+the message is allocated using the C++ new operator. The programmer never
+needs to explicitly call it. Note that all elements of the message are
+allocated when the message is created with new. There is no need to call
+new to allocate any of the fields of the message. This differs from a
+packed message where each field requires individual allocation. The
+alloc method should actually allocate the message using CkAllocMsg,
+whose signature is given below:
+
+::
+
+   void *CkAllocMsg(int msgnum, int size, int priobits);
+
+For varsize messages, these static methods ``alloc``, ``pack``, and
+``unpack`` are generated by the interface translator. For example, these
+methods for the VarsizeMessage class above would be similar to:
+
+::
+
+   // allocate memory for varmessage so charm can keep track of memory
+   static void* alloc(int msgnum, size_t size, int* array, int priobits)
+   {
+     int totalsize, first_start, second_start;
+     // array is passed in when the message is allocated using new (see below).
+     // size is the amount of space needed for the part of the message known
+     // about at compile time.  Depending on their values, sometimes a segfault
+     // will occur if memory addressing is not on 8-byte boundary, so altered
+     // with ALIGN8
+     first_start = ALIGN8(size);  // 8-byte align with this macro
+     second_start = ALIGN8(first_start + array[0]*sizeof(int));
+     totalsize = second_start + array[1]*sizeof(double);
+     VarsizeMessage* newMsg =
+       (VarsizeMessage*) CkAllocMsg(msgnum, totalsize, priobits);
+     // make firstArray point to end of newMsg in memory
+     newMsg->firstArray = (int*) ((char*)newMsg + first_start);
+     // make secondArray point to after end of firstArray in memory
+     newMsg->secondArray = (double*) ((char*)newMsg + second_start);
+
+     return (void*) newMsg;
+   }
+
+   // returns pointer to memory containing packed message
+   static void* pack(VarsizeMessage* in)
+   {
+     // set firstArray an offset from the start of in
+     in->firstArray = (int*) ((char*)in->firstArray - (char*)in);
+     // set secondArray to the appropriate offset
+     in->secondArray = (double*) ((char*)in->secondArray - (char*)in);
+     return in;
+   }
+
+   // returns new message from raw memory
+   static VarsizeMessage* VarsizeMessage::unpack(void* inbuf)
+   {
+     VarsizeMessage* me = (VarsizeMessage*)inbuf;
+     // return first array to absolute address in memory
+     me->firstArray = (int*) ((size_t)me->firstArray + (char*)me);
+     // likewise for secondArray
+     me->secondArray = (double*) ((size_t)me->secondArray + (char*)me);
+     return me;
+   }
+
+The pointers in a varsize message can exist in two states. At creation,
+they are valid C++ pointers to the start of the arrays. After packing,
+they become offsets from the address of the pointer variable to the
+start of the pointed-to data. Unpacking restores them to pointers.
+
+.. _sec:messages/packed_msgs:
+
+Custom Packed Messages
+''''''''''''''''''''''
+
+In many cases, a message must store a *non-linear* data structure using
+pointers. Examples of these are binary trees, hash tables etc. Thus, the
+message itself contains only a pointer to the actual data. When the
+message is sent to the same processor, these pointers point to the
+original locations, which are within the address space of the same
+processor. However, when such a message is sent to other processors,
+these pointers will point to invalid locations.
+
+Thus, the programmer needs a way to “serialize” these messages *only if*
+the message crosses the address-space boundary. Charm++ provides a way
+to do this serialization by allowing the developer to override the
+default serialization methods generated by the Charm++ interface
+translator. Note that this low-level serialization has nothing to do
+with parameter marshalling or the PUP framework described later.
+
+Packed messages are declared in the ``.ci`` file the same way as
+ordinary messages:
+
+::
+
+   message PMessage;
+
+Like all messages, the class PMessage needs to inherit from
+CMessage_PMessage and should provide two *static* methods: pack and
+unpack. These methods are called by the Charm++ runtime system, when the
+message is determined to be crossing address-space boundary. The
+prototypes for these methods are as follows:
+
+::
+
+   static void *PMessage::pack(PMessage *in);
+   static PMessage *PMessage::unpack(void *in);
+
+Typically, the following tasks are done in pack method:
+
+-  Determine size of the buffer needed to serialize message data.
+
+-  Allocate buffer using the CkAllocBuffer function. This function takes
+   in two parameters: input message, and size of the buffer needed, and
+   returns the buffer.
+
+-  Serialize message data into buffer (along with any control
+   information needed to de-serialize it on the receiving side.
+
+-  Free resources occupied by message (including message itself.)
+
+On the receiving processor, the unpack method is called. Typically, the
+following tasks are done in the unpack method:
+
+-  Allocate message using CkAllocBuffer function. *Do not use new to
+   allocate message here. If the message constructor has to be called,
+   it can be done using the in-place new operator.*
+
+-  De-serialize message data from input buffer into the allocated
+   message.
+
+-  Free the input buffer using CkFreeMsg.
+
+Here is an example of a packed-message implementation:
+
+::
+
+   // File: pgm.ci
+   mainmodule PackExample {
+     ...
+     message PackedMessage;
+     ...
+   };
+
+   // File: pgm.h
+   ...
+   class PackedMessage : public CMessage_PackedMessage
+   {
+     public:
+       BinaryTree<char> btree; // A non-linear data structure
+       static void* pack(PackedMessage*);
+       static PackedMessage* unpack(void*);
+       ...
+   };
+   ...
+
+   // File: pgm.C
+   ...
+   void*
+   PackedMessage::pack(PackedMessage* inmsg)
+   {
+     int treesize = inmsg->btree.getFlattenedSize();
+     int totalsize = treesize + sizeof(int);
+     char *buf = (char*)CkAllocBuffer(inmsg, totalsize);
+     // buf is now just raw memory to store the data structure
+     int num_nodes = inmsg->btree.getNumNodes();
+     memcpy(buf, &num_nodes, sizeof(int));  // copy numnodes into buffer
+     buf = buf + sizeof(int);               // don't overwrite numnodes
+     // copies into buffer, give size of buffer minus header
+     inmsg->btree.Flatten((void*)buf, treesize);
+     buf = buf - sizeof(int);              // don't lose numnodes
+     delete inmsg;
+     return (void*) buf;
+   }
+
+   PackedMessage*
+   PackedMessage::unpack(void* inbuf)
+   {
+     // inbuf is the raw memory allocated and assigned in pack
+     char* buf = (char*) inbuf;
+     int num_nodes;
+     memcpy(&num_nodes, buf, sizeof(int));
+     buf = buf + sizeof(int);
+     // allocate the message through Charm RTS
+     PackedMessage* pmsg =
+       (PackedMessage*)CkAllocBuffer(inbuf, sizeof(PackedMessage));
+     // call "inplace" constructor of PackedMessage that calls constructor
+     // of PackedMessage using the memory allocated by CkAllocBuffer,
+     // takes a raw buffer inbuf, the number of nodes, and constructs the btree
+     pmsg = new ((void*)pmsg) PackedMessage(buf, num_nodes);
+     CkFreeMsg(inbuf);
+     return pmsg;
+   }
+   ...
+   PackedMessage* pm = new PackedMessage();  // just like always
+   pm->btree.Insert('A');
+   ...
+
+While serializing an arbitrary data structure into a flat buffer, one
+must be very wary of any possible alignment problems. Thus, if possible,
+the buffer itself should be declared to be a flat struct. This will
+allow the C++ compiler to ensure proper alignment of all its member
+fields.
+
+.. _attributes:
+
+Entry Method Attributes
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Charm++ provides a handful of special attributes that entry methods may
+have. In order to give a particular entry method an attribute, you must
+specify the keyword for the desired attribute in the attribute list of
+that entry method’s ``.ci`` file declaration. The syntax for this is as
+follows:
+
+::
+
+   entry [attribute1, ..., attributeN] void EntryMethod(parameters);
+
+Charm++ currently offers the following attributes that one may assign to
+an entry method: threaded, sync, exclusive, nokeep, notrace, appwork,
+immediate, expedited, inline, local, python, reductiontarget, aggregate.
+
+threaded
+   entry methods run in their own non-preemptible threads. These entry
+   methods may perform blocking operations, such as calls to a sync
+   entry method, or explicitly suspending themselves. For more details,
+   refer to section :numref:`threaded`.
+
+sync
+   entry methods are special in that calls to them are blocking-they do
+   not return control to the caller until the method finishes execution
+   completely. Sync methods may have return values; however, they may
+   only return messages or data types that have the PUP method
+   implemented. Callers must run in a thread separate from the runtime
+   scheduler, e.g. a threaded entry methods. Calls expecting a return
+   value will receive it as the return from the proxy invocation:
+
+   ::
+
+       ReturnMsg* m;
+       m = A[i].foo(a, b, c);
+
+   For more details, refer to section :numref:`sync`.
+
+exclusive
+   entry methods should only exist on NodeGroup objects. One such entry
+   method will not execute while some other exclusive entry methods
+   belonging to the same NodeGroup object are executing on the same
+   node. In other words, if one exclusive method of a NodeGroup object
+   is executing on node N, and another one is scheduled to run on the
+   same node, the second exclusive method will wait to execute until the
+   first one finishes. An example can be found in
+   ``tests/charm++/pingpong``.
+
+nokeep
+   entry methods take only a message as their lone argument, and the
+   memory buffer for this message is managed by the Charm++ runtime
+   system rather than by the user. This means that the user has to
+   guarantee that the message will not be buffered for later usage or be
+   freed in the user code. Additionally, users are not allowed to modify
+   the contents of a nokeep message, since for a broadcast the same
+   message can be reused for all entry method invocations on each PE. If
+   a user frees the message or modifies its contents, a runtime error
+   may result. An example can be found in
+   ``examples/charm++/histogram_group``.
+
+notrace
+   entry methods will not be traced during execution. As a result, they
+   will not be considered and displayed in Projections for performance
+   analysis. Additionally, ``immediate`` entry methods are by default
+   ``notrace`` and will not be traced during execution.
+
+appwork
+   this entry method will be marked as executing application work. It
+   will be used for performance analysis.
+
+immediate
+   entry methods are executed in an “immediate” fashion as they skip the
+   message scheduling while other normal entry methods do not. Immediate
+   entry methods can only be associated with NodeGroup objects,
+   otherwise a compilation error will result. If the destination of such
+   entry method is on the local node, then the method will be executed
+   in the context of the regular PE regardless the execution mode of
+   Charm++ runtime. However, in the SMP mode, if the destination of the
+   method is on the remote node, then the method will be executed in the
+   context of the communication thread. For that reason, immediate entry
+   methods should be used for code that is performance critical and does
+   not take too long in terms of execution time because long running
+   entry methods can delay communication by occupying the communication
+   thread for entry method execution rather than remote communication.
+
+   Such entry methods can be useful for implementing
+   multicasts/reductions as well as data lookup when such operations are
+   on the performance critical path. On a certain Charm++ PE, skipping
+   the normal message scheduling prevents the execution of immediate
+   entry methods from being delayed by entry functions that could take a
+   long time to finish. Immediate entry methods are implicitly
+   “exclusive” on each node, meaning that one execution of immediate
+   message will not be interrupted by another. Function
+   CmiProbeImmediateMsg() can be called in user codes to probe and
+   process immediate messages periodically. Also note that ``immediate``
+   entry methods are by default ``notrace`` and are not traced during
+   execution. An example of ``immediate`` entry method can be found in
+   ``examples/charm++/immediateEntryMethod``.
+
+expedited
+   entry methods skip the priority-based message queue in Charm++
+   runtime. It is useful for messages that require prompt processing
+   when adding the immediate attribute to the message does not apply.
+   Compared with the immediate attribute, the expedited attribute
+   provides a more general solution that works for all types of Charm++
+   objects, i.e. Chare, Group, NodeGroup and Chare Array. However,
+   expedited entry methods will still be scheduled in the lower-level
+   Converse message queue, and be processed in the order of message
+   arrival. Therefore, they may still suffer from delays caused by long
+   running entry methods. An example can be found in
+   ``examples/charm++/satisfiability``.
+
+inline
+   entry methods will be called as a normal C++ member function if the
+   message recipient happens to be on the same PE. The call to the
+   function will happen inline, and control will return to the calling
+   function after the inline method completes. Because of this, these
+   entry methods need to be re-entrant as they could be called multiple
+   times recursively. Parameters to the inline method will be passed by
+   reference to avoid any copying, packing, or unpacking of the
+   parameters. This makes inline calls effective when large amounts of
+   data are being passed, and copying or packing the data would be an
+   expensive operation. Perfect forwarding has been implemented to allow
+   for seamless passing of both lvalue and rvalue references. Note that
+   calls with rvalue references must take place in the same translation
+   unit as the .decl.h file to allow for the appropriate template
+   instantiations. Alternatively, the method can be made templated and
+   referenced from multiple translation units via ``CK_TEMPLATES_ONLY``.
+   An explicit instantiation of all lvalue references is provided for
+   compatibility with existing code. If the recipient resides on a
+   different PE, a regular message is sent with the message arguments
+   packed up using PUP, and inline has no effect. An example “inlineem”
+   can be found in ``tests/charm++/megatest``.
+
+local
+   entry methods are equivalent to normal function calls: the entry
+   method is always executed immediately. This feature is available only
+   for Group objects and Chare Array objects. The user has to guarantee
+   that the recipient chare element resides on the same PE. Otherwise,
+   the application will abort with a failure. If the local entry method
+   uses parameter marshalling, instead of marshalling input parameters
+   into a message, it will pass them directly to the callee. This
+   implies that the callee can modify the caller data if method
+   parameters are passed by pointer or reference. The above description
+   of perfect forwarding for inline entry methods also applies to local
+   entry methods. Furthermore, input parameters are not required to be
+   PUPable. Considering that these entry methods always execute
+   immediately, they are allowed to have a non-void return value. An
+   example can be found in ``examples/charm++/hello/local``.
+
+python
+   entry methods are enabled to be called from python scripts as
+   explained in chapter :numref:`python`. Note that the object owning
+   the method must also be declared with the keyword python. Refer to
+   chapter :numref:`python` for more details.
+
+reductiontarget
+   entry methods can be used as the target of reductions while taking
+   arguments of the same type specified in the contribute call rather
+   than a message of type CkReductionMsg. See
+   section :numref:`reductions` for more information.
+
+aggregate
+   data sent to this entry method will be aggregated into larger
+   messages before being sent, to reduce fine-grained overhead. The
+   aggregation is handled by the Topological Routing and Aggregation
+   Module (TRAM). The argument to this entry method must be a single
+   fixed-size object. More details on TRAM are given in the `TRAM
+   section <http://charm.cs.illinois.edu/manuals/html/libraries/manual-1p.html#TRAM>`__
+   of the libraries manual.
+
+Controlling Delivery Order
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+By default, Charm++ processes the messages sent in roughly FIFO order
+when they arrive at a PE. For most programs, this behavior is fine.
+However, for optimal performance, some programs need more explicit
+control over the order in which messages are processed. Charm++ allows
+you to adjust delivery order on a per-message basis.
+
+An example program demonstrating how to modify delivery order for
+messages and parameter marshaling can be found in
+``examples/charm++/prio``.
+
+.. _queueing strategies:
+
+Queueing Strategies
+^^^^^^^^^^^^^^^^^^^
+
+The order in which messages are processed in the recipient’s queue can
+be set by explicitly setting the queuing strategy using one the
+following constants. These constants can be applied when sending a
+message or invoking an entry method using parameter marshaling:
+
+-  ``CK_QUEUEING_FIFO``: FIFO ordering
+
+-  ``CK_QUEUEING_LIFO``: LIFO ordering
+
+-  ``CK_QUEUEING_IFIFO``: FIFO ordering with *integer* priority
+
+-  ``CK_QUEUEING_ILIFO``: LIFO ordering with *integer* priority
+
+-  ``CK_QUEUEING_BFIFO``: FIFO ordering with *bitvector* priority
+
+-  ``CK_QUEUEING_BLIFO``: LIFO ordering with *bitvector* priority
+
+-  ``CK_QUEUEING_LFIFO``: FIFO ordering with *long integer* priority
+
+-  ``CK_QUEUEING_LLIFO``: FIFO ordering with *long integer* priority
+
+Parameter Marshaling
+^^^^^^^^^^^^^^^^^^^^
+
+For parameter marshaling, the queueingtype can be set for
+CkEntryOptions, which is passed to an entry method invocation as the
+optional last parameter.
+
+::
+
+     CkEntryOptions opts1, opts2;
+     opts1.setQueueing(CK_QUEUEING_FIFO);
+     opts2.setQueueing(CK_QUEUEING_LIFO);
+
+     chare.entry_name(arg1, arg2, opts1);
+     chare.entry_name(arg1, arg2, opts2);
+
+When the message with opts1 arrives at its destination, it will be
+pushed onto the end of the message queue as usual. However, when the
+message with opts2 arrives, it will be pushed onto the *front* of the
+message queue.
+
+.. _messages-1:
+
+Messages
+^^^^^^^^
+
+| For messages, the CkSetQueueing function can be used to change the
+  order in which messages are processed, where queueingtype is one of
+  the above constants.
+| void CkSetQueueing(MsgType message, int queueingtype)
+
+The first two options, CK_QUEUEING_FIFO and CK_QUEUEING_LIFO, are used
+as follows:
+
+::
+
+     MsgType *msg1 = new MsgType ;
+     CkSetQueueing(msg1, CK_QUEUEING_FIFO);
+
+     MsgType *msg2 = new MsgType ;
+     CkSetQueueing(msg2, CK_QUEUEING_LIFO);
+
+Similar to the parameter marshalled case described above, msg1 will be
+pushed onto the end of the message queue, while msg2 will be pushed onto
+the *front* of the message queue.
+
+.. _prioritized message passing:
+
+Prioritized Execution
+^^^^^^^^^^^^^^^^^^^^^
+
+The basic FIFO and LIFO strategies are sufficient to approximate
+parallel breadth-first and depth-first explorations of a problem space,
+but they do not allow more fine-grained control. To provide that degree
+of control, Charm++ also allows explicit prioritization of messages.
+
+The other six queueing strategies involve the use of priorities . There
+are two kinds of priorities which can be attached to a message: *integer
+priorities* and *bitvector priorities* . These correspond to the *I* and
+*B* queueing strategies, respectively. In both cases, numerically lower
+priorities will be dequeued and delivered before numerically greater
+priorities. The FIFO and LIFO queueing strategies then control the
+relative order in which messages of the same priority will be delivered.
+
+| To attach a priority field to a message, one needs to set aside space
+  in the message’s buffer while allocating the message . To achieve
+  this, the size of the priority field in bits should be specified as a
+  placement argument to the new operator, as described in
+  section :numref:`memory allocation`. Although the
+  size of the priority field is specified in bits, it is always padded
+  to an integral number of ``int``\ s. A pointer to the priority part of
+  the message buffer can be obtained with this call:
+| void \*CkPriorityPtr(MsgType msg)
+
+Integer priorities are quite straightforward. One allocates a message
+with an extra integer parameter to “new” (see the first line of the
+example below), which sets aside enough space (in bits) in the message
+to hold the priority. One then stores the priority in the message.
+Finally, one informs the system that the message contains an integer
+priority using CkSetQueueing:
+
+::
+
+     MsgType *msg = new (8*sizeof(int)) MsgType;
+     *(int*)CkPriorityPtr(msg) = prio;
+     CkSetQueueing(msg, CK_QUEUEING_IFIFO);
+
+Bitvector Prioritization
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Bitvector priorities are arbitrary-length bit-strings representing
+fixed-point numbers in the range 0 to 1. For example, the bit-string
+“001001” represents the number .001001. As with integer priorities,
+higher numbers represent lower priorities. However, bitvectors can be of
+arbitrary length, and hence the priority numbers they represent can be
+of arbitrary precision.
+
+Arbitrary-precision priorities are often useful in AI search-tree
+applications. Suppose we have a heuristic suggesting that tree node
+:math:`N_1` should be searched before tree node :math:`N_2`. We
+therefore designate that node :math:`N_1` and its descendants will use
+high priorities, and that node :math:`N_2` and its descendants will use
+lower priorities. We have effectively split the range of possible
+priorities in two. If several such heuristics fire in sequence, we can
+easily split the priority range in two enough times that no significant
+bits remain, and the search begins to fail for lack of meaningful
+priorities to assign. The solution is to use arbitrary-precision
+priorities, i.e. bitvector priorities.
+
+To assign a bitvector priority, two methods are available. The first is
+to obtain a pointer to the priority field using CkPriorityPtr, and then
+manually set the bits using the bit-setting operations inherent to C. To
+achieve this, one must know the format of the bitvector, which is as
+follows: the bitvector is represented as an array of unsigned integers.
+The most significant bit of the first integer contains the first bit of
+the bitvector. The remaining bits of the first integer contain the next
+31 bits of the bitvector. Subsequent integers contain 32 bits each. If
+the size of the bitvector is not a multiple of 32, then the last integer
+contains 0 bits for padding in the least-significant bits of the
+integer.
+
+The second way to assign priorities is only useful for those who are
+using the priority range-splitting described above. The root of the tree
+is assigned the null priority-string. Each child is assigned its
+parent’s priority with some number of bits concatenated. The net effect
+is that the entire priority of a branch is within a small epsilon of the
+priority of its root.
+
+It is possible to utilize unprioritized messages, integer priorities,
+and bitvector priorities in the same program. The messages will be
+processed in roughly the following order :
+
+-  Among messages enqueued with bitvector priorities, the messages are
+   dequeued according to their priority. The priority “0000...” is
+   dequeued first, and “1111...” is dequeued last.
+
+-  Unprioritized messages are treated as if they had the priority
+   “1000...” (which is the “middle” priority, it lies exactly halfway
+   between “0000...” and “1111...”).
+
+-  Integer priorities are converted to bitvector priorities. They are
+   normalized so that the integer priority of zero is converted to
+   “1000...” (the “middle” priority). To be more specific, the
+   conversion is performed by adding 0x80000000 to the integer, and then
+   treating the resulting 32-bit quantity as a 32-bit bitvector
+   priority.
+
+-  Among messages with the same priority, messages are dequeued in FIFO
+   order or LIFO order, depending upon which queuing strategy was used.
+
+Additionally, long integer priorities can be specified by the *L*
+strategy.
+
+A final reminder about prioritized execution: Charm++ processes messages
+in *roughly* the order you specify; it never guarantees that it will
+deliver the messages in *precisely* the order you specify. Thus, the
+correctness of your program should never depend on the order in which
+the runtime delivers messages. However, it makes a serious attempt to be
+“close”, so priorities can strongly affect the efficiency of your
+program.
+
+Skipping the Queue
+^^^^^^^^^^^^^^^^^^
+
+Some operations that one might want to perform are sufficiently
+latency-sensitive that they should never wait in line behind other
+messages. The Charm++ runtime offers two attributes for entry methods,
+expedited and immediate, to serve these needs. For more information on
+these attributes, see Section :numref:`attributes` and the example in
+``tests/charm++/megatest/immediatering.ci``.
+
+.. _nocopyapi:
+
+Zero Copy Messaging API
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Apart from using messages, Charm++ also provides APIs to avoid sender
+and receiver side copies. On RDMA enabled networks like GNI, Verbs, PAMI
+and OFI, these internally make use of one-sided communication by using
+the underlying Remote Direct Memory Access (RDMA) enabled network. For
+large arrays (few 100 KBs or more), the cost of copying during
+marshalling the message can be quite high. Using these APIs can help not
+only save the expensive copy operation but also reduce the application’s
+memory footprint by avoiding data duplication. Saving these costs for
+large arrays proves to be a significant optimization in achieving faster
+message send and receive times in addition to overall improvement in
+performance because of lower memory consumption. On the other hand,
+using these APIs for small arrays can lead to a drop in performance due
+to the overhead associated with one-sided communication. The overhead is
+mainly due to additional small messages required for sending the
+metadata message and the acknowledgment message on completion.
+
+For within process data-transfers, this API uses regular memcpy to
+achieve zerocopy semantics. Similarly, on CMA-enabled machines, in a few
+cases, this API takes advantage of CMA to perform inter-process
+intra-physical host data transfers. This API is also functional on
+non-RDMA enabled networks like regular ethernet, except that it does not
+avoid copies and behaves like a regular Charm++ entry method invocation.
+
+There are two APIs that provide Zero copy semantics in Charm++:
+
+-  Zero Copy Direct API
+
+-  Zero Copy Entry Method Send API
+
+Zero Copy Direct API
+^^^^^^^^^^^^^^^^^^^^
+
+The Zero copy Direct API allows users to explicitly invoke a standard
+set of methods on predefined buffer information objects to avoid copies.
+Unlike the Entry Method API which calls the zero copy operation for
+every zero copy entry method invocation, the direct API provides a more
+flexible interface by allowing the user to exploit the persistent nature
+of iterative applications to perform zero copy operations using the same
+buffer information objects across iteration boundaries. It is also more
+beneficial than the Zero copy entry method API because unlike the entry
+method API, which avoids just the sender side copy, the Zero copy Direct
+API avoids both sender and receiver side copies.
+
+To send an array using the zero copy Direct API, define a CkNcpyBuffer
+object on the sender chare specifying the pointer, size, a CkCallback
+object and an optional mode parameter.
+
+::
+
+   CkCallback srcCb(CkIndex_Ping1::sourceDone, thisProxy[thisIndex]);
+   // CkNcpyBuffer object representing the source buffer
+   CkNcpyBuffer source(arr1, arr1Size * sizeof(int), srcCb, CK_BUFFER_REG);
+
+When used inside a CkNcpyBuffer object that represents the source buffer
+information, the callback is specified to notify about the safety of
+reusing the buffer and indicates that the get or put call has been
+completed. In those cases where the application can determine safety of
+reusing the buffer through other synchronization mechanisms, the
+callback is not entirely useful and in such cases,
+``CkCallback::ignore`` can be passed as the callback parameter. The
+optional mode operator is used to determine the network registration
+mode for the buffer. It is only relevant on networks requiring explicit
+memory registration for performing RDMA operations. These networks
+include GNI, OFI and Verbs. When the mode is not specified by the user,
+the default mode is considered to be ``CK_BUFFER_REG``
+
+Similarly, to receive an array using the Zero copy Direct API, define
+another CkNcpyBuffer object on the receiver chare object specifying the
+pointer, the size, a CkCallback object and an optional mode parameter.
+When used inside a CkNcpyBuffer object that represents the destination
+buffer, the callback is specified to notify the completion of data
+transfer into the CkNcpyBuffer buffer. In those cases where the
+application can determine data transfer completion through other
+synchronization mechanisms, the callback is not entirely useful and in
+such cases, ``CkCallback::ignore`` can be passed as the callback
+parameter.
+
+::
+
+   CkCallback destCb(CkIndex_Ping1::destinationDone, thisProxy[thisIndex]);
+   // CkNcpyBuffer object representing the destination buffer
+   CkNcpyBuffer dest(arr2, arr2Size * sizeof(int), destCb, CK_BUFFER_REG);
+
+Once the source CkNcpyBuffer and destination CkNcpyBuffer objects have
+been defined on the sender and receiver chares, to perform a get
+operation, send the source CkNcpyBuffer object to the receiver chare.
+This can be done using a regular entry method invocation as shown in the
+following code snippet, where the sender, arrProxy[0] sends its source
+object to the receiver chare, arrProxy[1].
+
+::
+
+   // On Index 0 of arrProxy chare array
+   arrProxy[1].recvNcpySrcObj(source);
+
+After receiving the sender’s source CkNcpyBuffer object, the receiver
+can perform a get operation on its destination CkNcpyBuffer object by
+passing the source object as an argument to the runtime defined get
+method as shown in the following code snippet.
+
+::
+
+   // On Index 1 of arrProxy chare array
+   // Call get on the local destination object passing the source object
+   dest.get(source);
+
+This call performs a get operation, reading the remote source buffer
+into the local destination buffer.
+
+Similarly, a receiver’s destination CkNcpyBuffer object can be sent to
+the sender for the sender to perform a put on its source object by
+passing the source CkNcpyBuffer object as an argument to the runtime
+defined put method as shown in in the code snippet.
+
+::
+
+   // On Index 1 of arrProxy chare array
+   arrProxy[0].recvNcpyDestObj(dest);
+
+::
+
+   // On Index 0 of arrProxy chare array
+   // Call put on the local source object passing the destination object
+   source.put(dest);
+
+After the completion of either a get or a put, the callbacks specified
+in both the objects are invoked. Within the CkNcpyBuffer source
+callback, ``sourceDone()``, the buffer can be safely modified or freed
+as shown in the following code snippet.
+
+::
+
+   // Invoked by the runtime on source (Index 0)
+   void sourceDone() {
+       // update the buffer to the next pointer
+       updateBuffer();
+   }
+
+Similarly, inside the CkNcpyBuffer destination callback,
+``destinationDone()``, the user is guaranteed that the data transfer is
+complete into the destination buffer and the user can begin operating on
+the newly available data as shown in the following code snippet.
+
+::
+
+   // Invoked by the runtime on destination (Index 1)
+   void destinationDone() {
+       // received data, begin computing
+       computeValues();
+   }
+
+The callback methods can also take a pointer to a ``CkDataMsg`` message.
+This message can be used to access the original buffer information
+object i.e. the ``CkNcpyBuffer`` objects used for the zero copy
+transfer. The buffer information object available in the callback allows
+access to all its information including the buffer pointer and the
+arbitrary reference pointer set using the method ``setRef``. It is
+important to note that only the source ``CkNcpyBuffer`` object is
+accessible using the ``CkDataMsg`` in the source callback and similarly,
+the destination ``CkNcpyBuffer`` object is accessible using the
+``CkDataMsg`` in the destination callback. The following code snippet
+illustrates the accessing of the original buffer pointer in the callback
+method by casting the ``data`` field of the ``CkDataMsg`` object into a
+``CkNcpyBuffer`` object.
+
+::
+
+   // Invoked by the runtime on source (Index 0)
+   void sourceDone(CkDataMsg *msg) {
+       // Cast msg->data to a CkNcpyBuffer to get the source buffer information object
+       CkNcpyBuffer *source = (CkNcpyBuffer *)(msg->data);
+
+       // access buffer pointer and free it
+       free(source->ptr);
+   }
+
+The following code snippet illustrates the usage of the ``setRef``
+method.
+
+::
+
+   const void *refPtr = &index;
+   CkNcpyBuffer source(arr1, arr1Size * sizeof(int), srcCb, CK_BUFFER_REG);
+   source.setRef(refPtr);
+
+Similar to the buffer pointer, the user set arbitrary reference pointer
+can be also accessed in the callback method. This is shown in the next
+code snippet.
+
+::
+
+   // Invoked by the runtime on source (Index 0)
+   void sourceDone(CkDataMsg *msg) {
+       // update the buffer to the next pointer
+       updateBuffer();
+
+       // Cast msg->data to a CkNcpyBuffer
+       CkNcpyBuffer *src = (CkNcpyBuffer *)(msg->data);
+
+       // access buffer pointer and free it
+       free(src->ptr);
+
+       // get reference pointer
+       const void *refPtr = src->ref;
+   }
+
+The usage of ``CkDataMsg`` and ``setRef`` in order to access the
+original pointer and the arbitrary reference pointer is illustrated in
+``examples/charm++/zerocopy/direct_api/unreg/simple_get``
+
+Both the source and destination buffers are of the same type i.e.
+CkNcpyBuffer. What distinguishes a source buffer from a destination
+buffer is the way the get or put call is made. A valid get call using
+two CkNcpyBuffer objects ``obj1`` and ``obj2`` is performed as
+``obj1.get(obj2)``, where ``obj1`` is the local destination buffer
+object and ``obj2`` is the remote source buffer object that was passed
+to this PE. Similarly, a valid put call using two CkNcpyBuffer objects
+``obj1`` and ``obj2`` is performed as ``obj1.put(obj2)``, where ``obj1``
+is the local source buffer object and ``obj2`` is the remote destination
+buffer object that was passed to this PE.
+
+In addition to the callbacks, the return values of get and put also
+indicate the completion of data transfer between the buffers. When the
+source and destination buffers are within the same process or on
+different processes within the same CMA-enabled physical node, the
+zerocopy data transfer happens immediately without an asynchronous RDMA
+call. In such cases, both the methods, get and put return an enum value
+of CkNcpyStatus::complete. This value of the API indicates the
+completion of the zerocopy data transfer. On the other hand, in the case
+of an asynchronous RDMA call, the data transfer is not immediate and the
+return enum value of the get and put methods is
+CkNcpyStatus::incomplete. This indicates that the data transfer is
+in-progress and not necessarily complete. Use of CkNcpyStatus in an
+application is illustrated in
+``examples/charm++/zerocopy/direct_api/reg/simple_get``.
+
+Since callbacks in Charm++ allow to store a reference number, these
+callbacks passed into CkNcpyBuffer can be set with a reference number
+using the method ``cb.setRefNum(num)``. Upon callback invocation, these
+reference numbers can be used to identify the buffers that were passed
+into the CkNcpyBuffer objects. Upon callback invocation, the reference
+number of the callback can be accessed using the ``CkDataMsg`` argument
+of the callback function. For a callback using a ``CkDataMsg *msg``, the
+reference number is obtained by using the method ``CkGetRefNum(msg);``.
+This is illustrated in
+``examples/charm++/zerocopy/direct_api/unreg/simple_get``. specifically
+useful where there is an indexed collection of buffers, where the
+reference number can be used to index the collection.
+
+Note that the CkNcpyBuffer objects can be either statically declared or
+be dynamically allocated. Additionally, the objects are also reusable
+across iteration boundaries i.e. after sending the CkNcpyBuffer object,
+the remote PE can use the same object to perform get or put. This
+pattern of using the same objects across iterations is demonstrated in
+``examples/charm++/zerocopy/direct_api/reg/pingpong``.
+
+This API is demonstrated in ``examples/charm++/zerocopy/direct_api``
+
+Memory Registration and Modes of Operation
+''''''''''''''''''''''''''''''''''''''''''
+
+There are four modes of operation for the Zero Copy Direct API. These
+modes act as control switches on networks that require memory
+registration like GNI, OFI and Verbs, in order to perform RDMA
+operations . They dictate the functioning of the API providing flexible
+options based on user requirement. On other networks, where network
+memory management is not necessary (Netlrts) or is internally handled by
+the lower layer networking API (PAMI, MPI), these switches are still
+supported to maintain API consistency by all behaving in the similar
+default mode of operation.
+
+``CK_BUFFER_REG``:
+
+
+``CK_BUFFER_REG`` is the default mode that is used when no mode is
+passed. This mode doesn’t distinguish between non-network and network
+data transfers. When this mode is passed, the buffer is registered
+immediately and this can be used for both non-network sends (memcpy) and
+network sends without requiring an extra message being sent by the
+runtime system for the latter case. This mode is demonstrated in
+``examples/charm++/zerocopy/direct_api/reg``
+
+``CK_BUFFER_UNREG``:
+
+
+When this mode is passed, the buffer is initially unregistered and it
+is registered only for network transfers where registration is
+absolutely required. For example, if the target buffer is on the same PE
+or same logical node (or process), since the get internally performs a
+memcpy, registration is avoided for non-network transfers. On the other
+hand, if the target buffer resides on a remote PE on a different logical
+node, the get is implemented through an RDMA call requiring
+registration. In such a case, there is a small message sent by the RTS
+to register and perform the RDMA operation. This mode is demonstrated in
+``examples/charm++/zerocopy/direct_api/unreg``
+
+``CK_BUFFER_PREREG``:
+
+
+This mode is only beneficial by implementations that use
+pre-registered memory pools. In Charm++, GNI and Verbs machine layers
+use pre-registered memory pools for avoiding registration costs. On
+other machine layers, this mode is supported, but it behaves similar to
+``CK_BUFFER_REG``. A custom allocator, ``CkRdmaAlloc`` can be used to
+allocate a buffer from a pool of pre-registered memory to avoid the
+expensive malloc and memory registration costs. For a buffer allocated
+through ``CkRdmaAlloc``, the mode ``CK_BUFFER_PREREG`` should be passed
+to indicate the use of a mempooled buffer to the RTS. A buffer allocated
+with ``CkRdmaAlloc`` can be deallocated by calling a custom deallocator,
+``CkRdmaFree``. Although the allocator ``CkRdmaAlloc`` and deallocator,
+``CkRdmaFree`` are beneficial on GNI and Verbs, the allocators are
+functional on other networks and allocate regular memory similar to a
+``malloc`` call. Importantly, it should be noted that with the
+``CK_BUFFER_PREREG`` mode, the allocated buffer’s pointer should be used
+without any offsets. Using a buffer pointer with an offset will cause a
+segmentation fault. This mode is demonstrated in
+``examples/charm++/zerocopy/direct_api/prereg``
+
+``CK_BUFFER_NOREG``:
+
+
+This mode is used for just storing pointer information without any
+actual networking or registration information. It cannot be used for
+performing any zerocopy operations. This mode was added as it was useful
+for implementing a runtime system feature.
+
+Memory De-registration
+''''''''''''''''''''''
+
+Similar to memory registration, there is a method available to
+de-register memory after the completion of the operations. This allows
+for other buffers to use the registered memory as machines/networks are
+limited by the maximum amount of registered or pinned memory. Registered
+memory can be de-registered by calling the ``deregisterMem()`` method on
+the CkNcpyBuffer object.
+
+Other Methods
+'''''''''''''
+
+In addition to ``deregisterMem()``, there are other methods in a
+CkNcpyBuffer object that offer other utilities. The
+``init(const void *ptr, size_t cnt, CkCallback &cb, unsigned short int mode=CK_BUFFER_UNREG)``
+method can be used to re-initialize the CkNcpyBuffer object to new
+values similar to the ones that were passed in the constructor. For
+example, after using a CkNcpyBuffer object called ``srcInfo``, the user
+can re-initialize the same object with other values. This is shown in
+the following code snippet.
+
+::
+
+   // initialize src with new values
+   src.init(ptr, 200, newCb, CK_BUFFER_REG);
+
+Additionally, the user can use another method ``registerMem`` in order
+to register a buffer that has been de-registered. Note that it is not
+required to call ``registerMem`` after a new initialization using
+``init`` as ``registerMem`` is internally called on every new
+initialization. The usage of ``registerMem`` is illustrated in the
+following code snippet. Additionally, also note that following
+de-registration, if intended to register again, it is required to call
+``registerMem`` even in the ``CK_BUFFER_PREREG`` mode when the buffer is
+allocated from a preregistered mempool. This is required to set the
+registration memory handles and will not incur any registration costs.
+
+::
+
+   // register previously de-registered buffer
+   src.registerMem();
+
+Zero Copy Entry Method Send API
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The Zero copy Entry Method Send API only allows the user to only avoid
+the sender side copy without avoiding the receiver side copy. It
+offloads the user from the responsibility of making additional calls to
+support zero copy semantics. It extends the capability of the existing
+entry methods with slight modifications in order to send large buffers
+without a copy.
+
+To send an array using the zero copy message send API, specify the array
+parameter in the .ci file with the nocopy specifier.
+
+::
+
+   entry void foo (int size, nocopy int arr[size]);
+
+While calling the entry method from the .C file, wrap the array i.e the
+pointer in a CkSendBuffer wrapper.
+
+::
+
+   arrayProxy[0].foo(500000, CkSendBuffer(arrPtr));
+
+Until the RDMA operation is completed, it is not safe to modify the
+buffer. To be notified on completion of the RDMA operation, pass an
+optional callback object in the CkSendBuffer wrapper associated with the
+specific nocopy array.
+
+::
+
+   CkCallback cb(CkIndex_Foo::zerocopySent(NULL), thisProxy[thisIndex]);
+   arrayProxy[0].foo(500000, CkSendBuffer(arrPtr, cb));
+
+The callback will be invoked on completion of the RDMA operation
+associated with the corresponding array. Inside the callback, it is safe
+to overwrite the buffer sent via the zero copy entry method send API and
+this buffer can be accessed by dereferencing the CkDataMsg received in
+the callback.
+
+::
+
+   //called when RDMA operation is completed
+   void zerocopySent(CkDataMsg *m)
+   {
+     //get access to the pointer and free the allocated buffer
+     void *ptr = *((void **)(m->data));
+     free(ptr);
+     delete m;
+   }
+
+The RDMA call is associated with a nocopy array rather than the entry
+method. In the case of sending multiple nocopy arrays, each RDMA call is
+independent of the other. Hence, the callback applies to only the array
+it is attached to and not to all the nocopy arrays passed in an entry
+method invocation. On completion of the RDMA call for each array, the
+corresponding callback is separately invoked.
+
+As an example, for an entry method with two nocopy array parameters,
+each called with the same callback, the callback will be invoked twice:
+on completing the transfer of each of the two nocopy parameters.
+
+For multiple arrays to be sent via RDMA, declare the entry method in the
+.ci file as:
+
+::
+
+   entry void foo (int size1, nocopy int arr1[size1], int size2, nocopy double arr2[size2]);
+
+In the .C file, it is also possible to have different callbacks
+associated with each nocopy array.
+
+::
+
+   CkCallback cb1(CkIndex_Foo::zerocopySent1(NULL), thisProxy[thisIndex]);
+   CkCallback cb2(CkIndex_Foo::zerocopySent2(NULL), thisProxy[thisIndex]);
+   arrayProxy[0].foo(500000, CkSendBuffer(arrPtr1, cb1), 1024000, CkSendBuffer(arrPtr2, cb2));
+
+This API is demonstrated in
+``examples/charm++/zerocopy/entry_method_api`` and
+``tests/charm++/pingpong``
+
+It should be noted that calls to entry methods with nocopy specified
+parameters are currently only supported for point to point operations
+and not for collective operations. Additionally, there is also no
+support for migration of chares that have pending RDMA transfer
+requests.
+
+It should also be noted that the benefit of this API can be seen for
+large arrays on only RDMA enabled networks. On networks which do not
+support RDMA and for within process sends (which uses shared memory),
+the API is functional but doesn’t show any performance benefit as it
+behaves like a regular entry method that copies its arguments.
+
+Table :numref:`tab:rdmathreshold` displays the
+message size thresholds for the zero copy entry method send API on
+popular systems and build architectures. These results were obtained by
+running ``examples/charm++/zerocopy/entry_method_api/pingpong`` in
+non-SMP mode on production builds. For message sizes greater than or
+equal to the displayed thresholds, the zero copy API is found to perform
+better than the regular message send API. For network layers that are
+not pamilrts, gni, verbs, ofi or mpi, the generic implementation is
+used.
+
+.. table:: Message Size Thresholds for which Zero Copy Entry API performs better than Regular API
+   :name: tab:rdmathreshold
+
+   ============================= =============== ====================== =============== ========== ==========
+   Machine                       Network         Build Architecture     Intra Processor Intra Host Inter Host
+   ============================= =============== ====================== =============== ========== ==========
+   Blue Gene/Q (Vesta)           PAMI            ``pamilrts-bluegeneq`` 4 MB            32 KB      256 KB
+   Cray XC30 (Edison)            Aries           ``gni-crayxc``         1 MB            2 MB       2 MB
+   Cray XC30 (Edison)            Aries           ``mpi-crayxc``         256 KB          8 KB       32 KB
+   Dell Cluster (Golub)          Infiniband      ``verbs-linux-x86_64`` 128 KB          2 MB       1 MB
+   Dell Cluster (Golub)          Infiniband      ``mpi-linux-x86_64``   128 KB          32 KB      64 KB
+   Intel Cluster (Bridges)       Intel Omni-Path ``ofi-linux-x86_64``   64 KB           32 KB      32 KB
+   Intel KNL Cluster (Stampede2) Intel Omni-Path ``ofi-linux-x86_64``   1 MB            64 KB      64 KB
+   ============================= =============== ====================== =============== ========== ==========
+
+.. _callbacks:
+
+Callbacks
+---------
+
+Callbacks provide a generic way to store the information required to
+invoke a communication target, such as a chare’s entry method, at a
+future time. Callbacks are often encountered when writing library code,
+where they provide a simple way to transfer control back to a client
+after the library has finished. For example, after finishing a
+reduction, you may want the results passed to some chare’s entry method.
+To do this, you would create an object of type CkCallback with the
+chare’s CkChareID and entry method index, and pass this callback object
+to the reduction library.
+
+.. _sec:callbacks/creating:
+
+Creating a CkCallback Object
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are several different types of CkCallback objects; the type of the
+callback specifies the intended behavior upon invocation of the
+callback. Callbacks must be invoked with the Charm++ message of the type
+specified when creating the callback. If the callback is being passed
+into a library which will return its result through the callback, it is
+the user’s responsibility to ensure that the type of the message
+delivered by the library is the same as that specified in the callback.
+Messages delivered through a callback are not automatically freed by the
+Charm RTS. They should be freed or stored for future use by the user.
+
+Callbacks that target chares require an “entry method index”, an integer
+that identifies which entry method will be called. An entry method index
+is the Charm++ version of a function pointer. The entry method index can
+be obtained using the syntax:
+
+::
+
+   int myIdx = CkIndex_ChareName::EntryMethod(parameters);
+
+Here, ChareName is the name of the chare (group, or array) containing
+the desired entry method, EntryMethod is the name of that entry method,
+and parameters are the parameters taken by the method. These parameters
+are only used to resolve the proper EntryMethod; they are otherwise
+ignored.
+
+Under most circumstances, entry methods to be invoked through a
+CkCallback must take a single message pointer as argument. As such, if
+the entry method specified in the callback is not overloaded, using NULL
+in place of parameters will suffice in fully specifying the intended
+target. If the entry method is overloaded, a message pointer of the
+appropriate type should be defined and passed in as a parameter when
+specifying the entry method. The pointer does not need to be initialized
+as the argument is only used to resolve the target entry method.
+
+The intended behavior upon a callback’s invocation is specified through
+the choice of callback constructor used when creating the callback.
+Possible constructors are:
+
+#. CkCallback(void (\*CallbackFn)(void \*, void \*), void \*param) - When
+   invoked, the callback will pass param and the result message to the
+   given C function, which should have a prototype like:
+
+   ::
+
+      void myCallbackFn(void *param, void *message)
+
+   This function will be called on the processor where the callback was
+   created, so param is allowed to point to heap-allocated data. Hence,
+   this constructor should be used only when it is known that the
+   callback target (which by definition here is just a C-like function)
+   will be on the same processor as from where the constructor was
+   called. Of course, you are required to free any storage referenced by
+   param.
+
+#. CkCallback(CkCallback::ignore) - When invoked, the callback will do
+   nothing. This can be useful if a Charm++ library requires a callback,
+   but you don’t care when it finishes, or will find out some other way.
+
+#. CkCallback(CkCallback::ckExit) - When invoked, the callback will call
+   CkExit(), ending the Charm++ program.
+
+#. CkCallback(int ep, const CkChareID &id) - When invoked, the callback
+   will send its message to the given entry method (specified by the
+   entry point index - ep) of the given Chare (specified by the chare
+   id). Note that a chare proxy will also work in place of a chare id:
+
+   ::
+
+       CkCallback myCB(CkIndex_myChare::myEntry(NULL), myChareProxy);
+
+#. CkCallback(int ep, const CkArrayID &id) - When invoked, the callback
+   will broadcast its message to the given entry method of the given
+   array. An array proxy will work in the place of an array id.
+
+#. CkCallback(int ep, const CkArrayIndex &idx, const CkArrayID &id) -
+   When invoked, the callback will send its message to the given entry
+   method of the given array element.
+
+#. CkCallback(int ep, const CkGroupID &id) - When invoked, the callback
+   will broadcast its message to the given entry method of the given
+   group.
+
+#. CkCallback(int ep, int onPE, const CkGroupID &id) - When invoked, the
+   callback will send its message to the given entry method of the given
+   group member.
+
+One final type of callback, CkCallbackResumeThread(), can only be used
+from within threaded entry methods. This callback type is discussed in
+section :numref:`sec:ckcallbackresumethread`.
+
+.. _libraryInterface:
+
+CkCallback Invocation
+~~~~~~~~~~~~~~~~~~~~~
+
+A properly initialized CkCallback object stores a global destination
+identifier, and as such can be freely copied, marshalled, and sent in
+messages. Invocation of a CkCallback is done by calling the function
+send on the callback with the result message as an argument. As an
+example, a library which accepts a CkCallback object from the user and
+then invokes it to return a result may have the following interface:
+
+::
+
+   //Main library entry point, called by asynchronous users:
+   void myLibrary(...library parameters...,const CkCallback &cb)
+   {
+     ..start some parallel computation, store cb to be passed to myLibraryDone later...
+   }
+
+   //Internal library routine, called when computation is done
+   void myLibraryDone(...parameters...,const CkCallback &cb)
+   {
+     ...prepare a return message...
+     cb.send(msg);
+   }
+
+A CkCallback will accept any message type, or even NULL. The message is
+immediately sent to the user’s client function or entry point. A library
+which returns its result through a callback should have a clearly
+documented return message type. The type of the message returned by the
+library must be the same as the type accepted by the entry method
+specified in the callback.
+
+As an alternative to “send”, the callback can be used in a *contribute*
+collective operation. This will internally invoke the “send” method on
+the callback when the contribute operation has finished.
+
+For examples of how to use the various callback types, please see
+``tests/charm++/megatest/callback.C``
+
+.. _sec:ckcallbackresumethread:
+
+Synchronous Execution with CkCallbackResumeThread
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Threaded entry methods can be suspended and resumed through the
+*CkCallbackResumeThread* class. *CkCallbackResumeThread* is derived from
+*CkCallback* and has specific functionality for threads. This class
+automatically suspends the thread when the destructor of the callback is
+called. A suspended threaded client will resume when the “send” method
+is invoked on the associated callback. It can be used in situations when
+the return value is not needed, and only the synchronization is
+important. For example:
+
+::
+
+   // Call the "doWork" method and wait until it has completed
+   void mainControlFlow() {
+     ...perform some work...
+     // call a library
+     doWork(...,CkCallbackResumeThread());
+     // or send a broadcast to a chare collection
+     myProxy.doWork(...,CkCallbackResumeThread());
+     // callback goes out of scope; the thread is suspended until doWork calls 'send' on the callback
+
+     ...some more work...
+   }
+
+Alternatively, if doWork returns a value of interest, this can be
+retrieved by passing a pointer to *CkCallbackResumeThread*. This pointer
+will be modified by *CkCallbackResumeThread* to point to the incoming
+message. Notice that the input pointer has to be cast to *(void*&)*:
+
+::
+
+   // Call the "doWork" method and wait until it has completed
+   void mainControlFlow() {
+     ...perform some work...
+     MyMessage *mymsg;
+     myProxy.doWork(...,CkCallbackResumeThread((void*&)mymsg));
+     // The thread is suspended until doWork calls send on the callback
+
+     ...some more work using "mymsg"...
+   }
+
+Notice that the instance of *CkCallbackResumeThread* is constructed as
+an anonymous parameter to the “doWork” call. This insures that the
+callback is destroyed as soon as the function returns, thereby
+suspending the thread.
+
+It is also possible to allocate a *CkCallbackResumeThread* on the heap
+or on the stack. We suggest that programmers avoid such usage, and favor
+the anonymous instance construction shown above. For completeness, we
+still present the code for heap and stack allocation of
+CkCallbackResumeThread callbacks below.
+
+For heap allocation, the user must explicitly “delete” the callback in
+order to suspend the thread.
+
+::
+
+   // Call the "doWork" method and wait until it has completed
+   void mainControlFlow() {
+     ...perform some work...
+     CkCallbackResumeThread cb = new CkCallbackResumeThread();
+     myProxy.doWork(...,cb);
+     ...do not suspend yet, continue some more work...
+     delete cb;
+     // The thread suspends now
+
+     ...some more work after the thread resumes...
+   }
+
+For a callback that is allocated on the stack, its destructor will be
+called only when the callback variable goes out of scope. In this
+situation, the function “thread_delay” can be invoked on the callback to
+force the thread to suspend. This also works for heap allocated
+callbacks.
+
+::
+
+   // Call the "doWork" method and wait until it has completed
+   void mainControlFlow() {
+     ...perform some work...
+     CkCallbackResumeThread cb;
+     myProxy.doWork(...,cb);
+     ...do not suspend yet, continue some more work...
+     cb.thread_delay();
+     // The thread suspends now
+
+     ...some more work after the thread is resumed...
+   }
+
+| In all cases a *CkCallbackResumeThread* can be used to suspend a
+  thread only once.
+| (See Main.cpp of `Barnes-Hut
+  MiniApp <http://charmplusplus.org/miniApps/#barnes>`__ for a complete
+  example).
+| *Deprecated usage*: in the past, “thread_delay” was used to retrieve
+  the incoming message from the callback. While that is still allowed
+  for backward compatibility, its usage is deprecated. The old usage is
+  subject to memory leaks and dangling pointers.
+
+| Callbacks can also be tagged with reference numbers which can be
+  matched inside SDAG code. When the callback is created, the creator
+  can set the refnum and the runtime system will ensure that the message
+  invoked on the callback’s destination will have that refnum. This
+  allows the receiver of the final callback to match the messages based
+  on the refnum value. (See
+  ``examples/charm++/examples/charm++/ckcallback`` for a complete
+  example).
+
+Waiting for Completion
+----------------------
+
+.. _threaded:
+
+Threaded Entry Methods
+~~~~~~~~~~~~~~~~~~~~~~
+
+Typically, entry methods run in the same thread of execution as the
+Charm++ scheduler. This prevents them from undertaking any actions that
+would cause their thread to block, as blocking would prevent the
+receiving and processing of incoming messages.
+
+However, entry methods with the threaded attribute run in their own
+user-level nonpreemptible thread, and are therefore able to block
+without interrupting the runtime system. This allows them to undertake
+blocking operations or explicitly suspend themselves, which is necessary
+to use some Charm++ features, such as sync entry methods and futures.
+
+For details on the threads API available to threaded entry methods, see
+chapter 3 of the Converse programming manual. The use of threaded entry
+methods is demonstrated in an example program located in
+``examples/charm++/threaded_ring``.
+
+.. _sync:
+
+Sync Entry Methods
+~~~~~~~~~~~~~~~~~~
+
+Generally, entry methods are invoked asynchronously and return ``void``.
+Therefore, while an entry method may send data back to its invoker, it
+can only do so by invoking another asynchronous entry method on the
+chare object that invoked it.
+
+However, it is possible to use sync entry methods, which have blocking
+semantics. The data returned by the invocation of such an entry method
+is available at the call site when it returns from blocking. This
+returned data can either be in the form of a Charm++ message or any type
+that has the PUP method implemented. Because the caller of a sync entry
+method will block, it must execute in a thread separate from the
+scheduler; that is, it must be a threaded entry method (*cf.*
+§ :numref:`threaded`, above). If a sync entry method returns a value,
+it is provided as the return value from the invocation on the proxy
+object:
+
+::
+
+    ReturnMsg* m;
+    m = A[i].foo(a, b, c);
+
+An example of the use of sync entry methods is given in
+``tests/charm++/sync_square``.
+
+Futures
+~~~~~~~
+
+Similar to Multilisp and other functional programming languages,
+Charm++ provides the abstraction of *futures*. In simple terms, a
+*future* is a contract with the runtime system to evaluate an expression
+asynchronously with the calling program. This mechanism promotes the
+evaluation of expressions in parallel as several threads concurrently
+evaluate the futures created by a program.
+
+In some ways, a future resembles lazy evaluation. Each future is
+assigned to a particular thread (or to a chare, in Charm++) and,
+eventually, its value is delivered to the calling program. Once a future
+is created, a *reference* is returned immediately. However, if the
+*value* calculated by the future is needed, the calling program blocks
+until the value is available.
+
+Charm++ provides all the necessary infrastructure to use futures by
+means of the following functions:
+
+::
+
+    CkFuture CkCreateFuture(void)
+    void CkReleaseFuture(CkFuture fut)
+    int CkProbeFuture(CkFuture fut)
+    void *CkWaitFuture(CkFuture fut)
+    void  CkSendToFuture(CkFuture fut, void *msg)
+
+To illustrate the use of all these functions, a Fibonacci example in
+Charm++ using futures in presented below:
+
+::
+
+   chare fib {
+     entry fib(bool amIroot, int n, CkFuture f);
+     entry  [threaded] void run(bool amIroot, int n, CkFuture f);
+   };
+
+::
+
+   void  fib::run(bool amIRoot, int n, CkFuture f) {
+      if (n < THRESHOLD)
+       result = seqFib(n);
+     else {
+       CkFuture f1 = CkCreateFuture();
+       CkFuture f2 = CkCreateFuture();
+       CProxy_fib::ckNew(0, n-1, f1);
+       CProxy_fib::ckNew(0, n-2, f2);
+       ValueMsg * m1 = (ValueMsg *) CkWaitFuture(f1);
+       ValueMsg * m2 = (ValueMsg *) CkWaitFuture(f2);
+       result = m1->value + m2->value;
+       delete m1; delete m2;
+     }
+     if (amIRoot) {
+       CkPrintf("The requested Fibonacci number is : %d\n", result);
+       CkExit();
+     } else {
+       ValueMsg *m = new ValueMsg();
+       m->value = result;
+       CkSendToFuture(f, m);
+     }
+   }
+
+The constant *THRESHOLD* sets a limit value for computing the Fibonacci
+number with futures or just with the sequential procedure. Given value
+*n*, the program creates two futures using *CkCreateFuture*. Those
+futures are used to create two new chares that will carry out the
+computation. Next, the program blocks until the two component values of
+the recurrence have been evaluated. Function *CkWaitFuture* is used for
+that purpose. Finally, the program checks whether or not it is the root
+of the recursive evaluation. The very first chare created with a future
+is the root. If a chare is not the root, it must indicate that its
+future has finished computing the value. *CkSendToFuture* is meant to
+return the value for the current future.
+
+Other functions complete the API for futures. *CkReleaseFuture* destroys
+a future. *CkProbeFuture* tests whether the future has already finished
+computing the value of the expression.
+
+The Converse version of future functions can be found in the :ref:`conv-futures`
+section.
+
+.. _sec-completion:
+
+Completion Detection
+~~~~~~~~~~~~~~~~~~~~
+
+Completion detection is a method for automatically detecting completion
+of a distributed process within an application. This functionality is
+helpful when the exact number of messages expected by individual objects
+is not known. In such cases, the process must achieve global consensus
+as to the number of messages produced and the number of messages
+consumed. Completion is reached within a distributed process when the
+participating objects have produced and consumed an equal number of
+events globally. The number of global events that will be produced and
+consumed does not need to be known, just the number of producers is
+required.
+
+The completion detection feature is implemented in Charm++ as a module,
+and therefore is only included when “``-module completion``” is
+specified when linking your application.
+
+First, the detector should be constructed. This call would typically
+belong in application startup code (it initializes the group that keeps
+track of completion):
+
+::
+
+   CProxy_CompletionDetector detector = CProxy_CompletionDetector::ckNew();
+
+When it is time to start completion detection, invoke the following
+method of the library on *all* branches of the completion detection
+group:
+
+::
+
+   void start_detection(int num_producers,
+                        CkCallback start,
+                        CkCallback all_produced,
+                        CkCallback finish,
+                        int prio);
+
+The ``num_producers`` parameter is the number of objects (chares) that
+will produce elements. So if every chare array element will produce one
+event, then it would be the size of the array.
+
+The ``start`` callback notifies your program that it is safe to begin
+producing and consuming (this state is reached when the module has
+finished its internal initialization).
+
+The ``all_produced`` callback notifies your program when the client has
+called ``done`` with arguments summing to ``num_producers``.
+
+The ``finish`` callback is invoked when completion has been detected
+(all objects participating have produced and consumed an equal number of
+elements globally).
+
+The ``prio`` parameter is the priority with which the completion
+detector will run. This feature is still under development, but it
+should be set below the application’s priority if possible.
+
+For example, the call
+
+::
+
+   detector.start_detection(10,
+                            CkCallback(CkIndex_chare1::start_test(), thisProxy),
+                            CkCallback(CkIndex_chare1::produced_test(), thisProxy),
+                            CkCallback(CkIndex_chare1::finish_test(), thisProxy),
+                            0);
+
+sets up completion detection for 10 producers. Once initialization is
+done, the callback associated with the ``start_test`` method will be
+invoked. Once all 10 producers have called ``done`` on the completion
+detector, the ``produced_test`` method will be invoked. Furthermore,
+when the system detects completion, the callback associated with
+``finish_test`` will be invoked. Finally, the priority given to the
+completion detection library is set to 0 in this case.
+
+Once initialization is complete (the “start” callback is triggered),
+make the following call to the library:
+
+::
+
+   void CompletionDetector::produce(int events_produced)
+   void CompletionDetector::produce() // 1 by default
+
+For example, within the code for a chare array object, you might make
+the following call:
+
+::
+
+   detector.ckLocalBranch()->produce(4);
+
+Once all the “events” that this chare is going to produce have been sent
+out, make the following call:
+
+::
+
+   void CompletionDetector::done(int producers_done)
+   void CompletionDetector::done() // 1 by default
+
+::
+
+   detector.ckLocalBranch()->done();
+
+At the same time, objects can also consume produced elements, using the
+following calls:
+
+::
+
+   void CompletionDetector::consume(int events_consumed)
+   void CompletionDetector::consume() // 1 by default
+
+::
+
+   detector.ckLocalBranch()->consume();
+
+Note that an object may interleave calls to ``produce()`` and
+``consume()``, i.e. it could produce a few elements, consume a few, etc.
+When it is done producing its elements, it should call ``done()``, after
+which cannot ``produce()`` any more elements. However, it can continue
+to ``consume()`` elements even after calling ``done()``. When the
+library detects that, globally, the number of produced elements equals
+the number of consumed elements, and all producers have finished
+producing (i.e. called ``done()``), it will invoke the ``finish``
+callback. Thereafter, ``start_detection`` can be called again to restart
+the process.
+
+.. _sec:qd:
+
+Quiescence Detection
+~~~~~~~~~~~~~~~~~~~~
+
+In Charm++, quiescence is defined as the state in which no processor is
+executing an entry point, no messages are awaiting processing, and there
+are no messages in-flight. Charm++ provides two facilities for detecting
+quiescence: CkStartQD and CkWaitQD. CkStartQD registers with the system
+a callback that is to be invoked the next time quiescence is detected.
+Note that if immediate messages are used, QD cannot be used. CkStartQD
+has two variants which expect the following arguments:
+
+#. A CkCallback object. The syntax of this call looks like:
+
+   ::
+
+        CkStartQD(const CkCallback& cb);
+
+   Upon quiescence detection, the specified callback is called with no
+   parameters. Note that using this variant, you could have your program
+   terminate after quiescence is detected, by supplying the above method
+   with a CkExit callback (§ :numref:`sec:callbacks/creating`).
+
+#. An index corresponding to the entry function that is to be called,
+   and a handle to the chare on which that entry function should be
+   called. The syntax of this call looks like this:
+
+   ::
+
+       CkStartQD(int Index,const CkChareID* chareID);
+
+   To retrieve the corresponding index of a particular entry method, you
+   must use a static method contained within the (charmc-generated)
+   CkIndex object corresponding to the chare containing that entry
+   method. The syntax of this call is as follows:
+
+   ::
+
+      myIdx=CkIndex_ChareClass::entryMethod(parameters);
+
+   where ChareClass is the