mirror of
https://github.com/nwchemgit/nwchem.git
synced 2026-07-29 06:35:39 -04:00
270 lines
8.6 KiB
TeX
270 lines
8.6 KiB
TeX
\label{sec:ma}
|
|
|
|
The Memoray Allocator (MA) is used to allocate data that will generally not be directly
|
|
shared with other processes, such as workspace for a particular local
|
|
calculation or for replication of very small sets of data. The MA tool
|
|
is a library of routines that comprises a dynamic memory allocator
|
|
for use by C, FORTRAN, or mixed-language applications. It provides
|
|
both heap and stack memory management disciplines, debugging and
|
|
verification support (for detecting memory leaks, for example), usage
|
|
statistics, and quantitative memory availability information.
|
|
|
|
Applications written in FORTRAN
|
|
require this sort of library because the language does not
|
|
support dynamic memory allocation. Applications written in C can benefit from
|
|
using MA instead of the ordinary {\tt malloc()} and {\tt free()}
|
|
routines because of the extra features MA provides, which include both heap and
|
|
stack memory management disciplines, debugging and verification
|
|
support, usage statistics, and quantitative memory availability
|
|
information. MA is designed to be portable across a large variety of
|
|
platforms.
|
|
|
|
Detailed information on specific routines is available in the MA man pages.
|
|
This can be accessed by means of the command, {\tt man ma}. (Note: this
|
|
will work only if the local environmental variable {\tt MANPATH} includes
|
|
the path {\tt \$(NWCHEM\_TOP)/src/man/ma/man}. See Section \ref{sec:envar}
|
|
for information on system and environmental requirements for running NWChem.)
|
|
The following subsections present a summary list of the MA routines, and
|
|
a brief discussion of the implementation of this feature.
|
|
|
|
\subsubsection{MA Data Types}
|
|
|
|
All MA memory must be explicitly assigned a specific type by defining each
|
|
data item in units of integer, logical,
|
|
double precision, or character words. The type of data is specified
|
|
in arguments using predefined Fortran parameters (or macros in C).
|
|
These parameters are available in the \verb+include+ files \verb+mafdecls.fh+ in
|
|
Fortran and in \verb+macdecls.h+ in C. The parameters are typed as follows:
|
|
|
|
\begin{description}
|
|
\item{\verb+MT_INT+} --- integer
|
|
\item{\verb+MT_DBL+} --- double precision
|
|
\item{\verb+MT_LOG+} --- logical
|
|
\item{\verb+MT_CHAR+} --- character\verb+*+1
|
|
\end{description}
|
|
|
|
\subsubsection{Implementation}
|
|
|
|
To access required MA definitions, C applications should include
|
|
{\tt macdecls.h} and FORTRAN applications should include
|
|
{\tt mafdecls.fh}. These are public header files for a dynamic memory
|
|
allocator, and are included in the \verb+.../src/ma+ subdirectory of the
|
|
NWChem directory tree. The files contain the type declarations
|
|
and parameter declarations for the datatype constants, and define
|
|
needed functions and variable types.
|
|
|
|
The memory allocator uses the following memory layout definitions:
|
|
\begin{itemize}
|
|
\item segment = heap\_region stack\_region
|
|
\item region = block block block \ldots
|
|
\item block = AD gap1 guard1 client\_space guard2 gap2
|
|
\end{itemize}
|
|
|
|
A segment of memory is obtained from the OS upon initialization. The
|
|
low end of the segment is managed as a heap. The heap region grows
|
|
from low addresses to high addresses. The high end of the segment is
|
|
managed as a stack. The stack region grows from high addresses to low
|
|
addresses.
|
|
|
|
Each region consists of a series of contiguous blocks, one per
|
|
allocation request, and possibly some unused space. Blocks in the
|
|
heap region are either in use by the client (allocated and not yet
|
|
deallocated) or not in use by the client (allocated and already
|
|
deallocated). A block on the rightmost end of the heap region becomes
|
|
part of the unused space upon deallocation. Blocks in the stack
|
|
region are always in use by the client, because when a stack block is
|
|
deallocated, it becomes part of the unused space.
|
|
|
|
A block consists of the client space, i.e., the range of memory
|
|
available for use by the application. Guard words adjacent to each end
|
|
of the client space to help detect improper memory access by the
|
|
client. Bookkeeping information is stored(?) in an "allocation descriptor" AD
|
|
Two gaps, each zero or more bytes long, are defined to satisfy alignment constraints
|
|
(specifically, to ensure that AD and client\_space are aligned
|
|
properly).
|
|
|
|
|
|
|
|
\subsubsection{List of MA routines}
|
|
|
|
All MA routines are shown below, grouped by category and listed
|
|
alphabetically within each category. The FORTRAN interface is given
|
|
here. Information on the the C interface are available in the \verb+man+ pages.
|
|
(The \verb+man+ pages also contain more
|
|
detailed information on the
|
|
arguments for these routines.)
|
|
|
|
Initialization:
|
|
\begin{itemize}
|
|
\item {\tt MA\_init(datatype, nominal\_stack, nominal\_heap)}
|
|
\begin{itemize}
|
|
\item integer datatype
|
|
\item integer nominal\_stack
|
|
\item integer nominal\_heap
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_sizeof(datatype1, nelem1, datatype2)}
|
|
\begin{itemize}
|
|
\item integer datatype1
|
|
\item integer nelem1
|
|
\item integer datatype2
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_sizeof\_overhead(datatype)}
|
|
\begin{itemize}
|
|
\item integer datatype
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_initialized()}
|
|
|
|
\end{itemize}
|
|
|
|
Allocation:
|
|
\begin{itemize}
|
|
\item {\tt MA\_alloc\_get(datatype, nelem, name, memhandle, index)}
|
|
\begin{itemize}
|
|
\item integer datatype
|
|
\item integer nelem
|
|
\item character*(*) name
|
|
\item integer memhandle
|
|
\item integer index
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_allocate\_heap(datatype, nelem, name, memhandle)}
|
|
\begin{itemize}
|
|
\item integer datatype
|
|
\item integer nelem
|
|
\item character*(*) name
|
|
\item integer memhandle
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_get\_index(memhandle, index)}
|
|
\begin{itemize}
|
|
\item integer memhandle
|
|
\item integer index
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_get\_pointer()} --- C only
|
|
\item {\tt MA\_inquire\_avail(datatype)}
|
|
\begin{itemize}
|
|
\item integer datatype
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_inquire\_heap(datatype)}
|
|
\begin{itemize}
|
|
\item integer datatype
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_inquire\_stack(datatype)}
|
|
\begin{itemize}
|
|
\item integer datatype
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_push\_get(datatype, nelem, name, memhandle, index)}
|
|
\begin{itemize}
|
|
\item integer datatype
|
|
\item integer nelem
|
|
\item character*(*) name
|
|
\item integer memhandle
|
|
\item integer index
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_push\_stack(datatype, nelem, name, memhandle)}
|
|
\begin{itemize}
|
|
\item integer datatype
|
|
\item integer nelem
|
|
\item character*(*) name
|
|
\item integer memhandle
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
Deallocation:
|
|
\begin{itemize}
|
|
\item {\tt MA\_chop\_stack(memhandle)}
|
|
\begin{itemize}
|
|
\item integer memhandle
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_free\_heap(memhandle)}
|
|
\begin{itemize}
|
|
\item integer memhandle
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_pop\_stack(memhandle)}
|
|
\begin{itemize}
|
|
\item integer memhandle
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
Debugging:
|
|
\begin{itemize}
|
|
\item {\tt MA\_set\_auto\_verify(value)}
|
|
\begin{itemize}
|
|
\item logical value
|
|
\item integer ivalue
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_set\_error\_print(value)}
|
|
\begin{itemize}
|
|
\item logical value
|
|
\item integer ivalue
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_set\_hard\_fail(value)}
|
|
\begin{itemize}
|
|
\item logical value
|
|
\item integer ivalue
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_summarize\_allocated\_blocks}
|
|
\item {\tt MA\_verify\_allocator\_stuff()}
|
|
\end{itemize}
|
|
|
|
Iteration Over Allocated Blocks:
|
|
\begin{itemize}
|
|
\item {\tt MA\_get\_next\_memhandle(ithandle, memhandle)}
|
|
\begin{itemize}
|
|
\item integer ithandle
|
|
\item integer memhandle
|
|
\end{itemize}
|
|
|
|
\item {\tt MA\_init\_memhandle\_iterator(ithandle)}
|
|
\begin{itemize}
|
|
\item integer ithandle
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
Statistics:
|
|
\begin{itemize}
|
|
\item {\tt MA\_print\_stats(oprintroutines)}
|
|
\begin{itemize}
|
|
\item logical printroutines
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
|
|
\subsubsection{MA Errors}
|
|
|
|
Errors considered fatal by MA result in program termination. Errors
|
|
considered nonfatal by MA cause the MA routine to return an error
|
|
value to the caller. For most boolean functions, false is returned
|
|
upon failure and true is returned upon success. (The boolean
|
|
functions for which the return value means something other than
|
|
success or failure are {\tt MA\_set\_auto\_verify()}, {\tt
|
|
MA\_set\_error\_print()}, and {\tt MA\_set\_hard\_fail()}.) Integer
|
|
functions return zero upon failure; depending on the function, zero
|
|
may or may not be distinguishable as an exceptional value.
|
|
|
|
An application can force MA to treat all errors as fatal via
|
|
{\tt MA\_set\_hard\_fail()}.
|
|
|
|
If a fatal error occurs, an error message is printed on the standard
|
|
error (stderr). By default, error messages are also printed for
|
|
nonfatal errors. An application can force MA to print or not print
|
|
error messages for nonfatal errors via {\tt MA\_set\_error\_print()}.
|
|
|
|
|