add doxygen docs and convert MyPage template class from header only to header plus implementation
This commit is contained in:
@ -410,24 +410,27 @@ WARN_LOGFILE = "../doxygen-warn.log"
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = @LAMMPS_SOURCE_DIR@/utils.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/utils.h \
|
||||
@LAMMPS_SOURCE_DIR@/library.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/library.h \
|
||||
@LAMMPS_SOURCE_DIR@/lammps.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/lammps.h \
|
||||
@LAMMPS_SOURCE_DIR@/lmptype.h \
|
||||
@LAMMPS_SOURCE_DIR@/pointers.h \
|
||||
@LAMMPS_SOURCE_DIR@/atom.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/atom.h \
|
||||
@LAMMPS_SOURCE_DIR@/input.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/input.h \
|
||||
@LAMMPS_SOURCE_DIR@/tokenizer.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/tokenizer.h \
|
||||
@LAMMPS_SOURCE_DIR@/text_file_reader.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/text_file_reader.h \
|
||||
@LAMMPS_SOURCE_DIR@/potential_file_reader.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/potential_file_reader.h \
|
||||
INPUT = @LAMMPS_SOURCE_DIR@/utils.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/utils.h \
|
||||
@LAMMPS_SOURCE_DIR@/library.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/library.h \
|
||||
@LAMMPS_SOURCE_DIR@/lammps.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/lammps.h \
|
||||
@LAMMPS_SOURCE_DIR@/lmptype.h \
|
||||
@LAMMPS_SOURCE_DIR@/pointers.h \
|
||||
@LAMMPS_SOURCE_DIR@/atom.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/atom.h \
|
||||
@LAMMPS_SOURCE_DIR@/input.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/input.h \
|
||||
@LAMMPS_SOURCE_DIR@/tokenizer.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/tokenizer.h \
|
||||
@LAMMPS_SOURCE_DIR@/text_file_reader.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/text_file_reader.h \
|
||||
@LAMMPS_SOURCE_DIR@/potential_file_reader.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/potential_file_reader.h \
|
||||
@LAMMPS_SOURCE_DIR@/my_page.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/my_page.h \
|
||||
@LAMMPS_SOURCE_DIR@/my_pool_chunk.h \
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
|
||||
@ -53,7 +53,7 @@ command, e.g. ``src/force.cpp`` and the :cpp:class:`LAMMPS_NS::Force`
|
||||
class. They are discussed in the next section.
|
||||
|
||||
A small number of C++ classes and utility functions are implemented with
|
||||
only a ``.h`` file. Examples are the Pointer class and the mergesort function.
|
||||
only a ``.h`` file. Examples are the Pointer class or the MyPool class.
|
||||
|
||||
LAMMPS class topology
|
||||
=====================
|
||||
@ -1102,3 +1102,12 @@ A file that would be parsed by the reader code fragment looks like this:
|
||||
:project: progguide
|
||||
:members:
|
||||
|
||||
|
||||
----------
|
||||
|
||||
Memory pool classes
|
||||
===================
|
||||
|
||||
.. doxygenclass:: LAMMPS_NS::MyPage
|
||||
:project: progguide
|
||||
:members:
|
||||
|
||||
@ -1975,6 +1975,7 @@ MxN
|
||||
myCompute
|
||||
myIndex
|
||||
mylammps
|
||||
MyPool
|
||||
mysocket
|
||||
myTemp
|
||||
myVec
|
||||
|
||||
267
src/my_page.cpp
Normal file
267
src/my_page.cpp
Normal file
@ -0,0 +1,267 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
usage:
|
||||
request one datum at a time, repeat, clear
|
||||
request chunks of datums in each get() or vget(), repeat, clear
|
||||
chunk size can vary from request to request
|
||||
chunk size can be known in advance or registered after usage via vgot()
|
||||
inputs:
|
||||
template T = one datum, e.g. int, double, struct, int[3]
|
||||
for int[3], access datum as ivec[i][2]
|
||||
methods:
|
||||
T *get() = return ptr to one datum
|
||||
T *get(N) = return ptr to N datums, N < maxchunk required
|
||||
T *vget() = return ptr to maxchunk datums, use as needed, then call vgot()
|
||||
all gets return NULL if error encountered
|
||||
vgot(N) = used N datums of previous vget(), N < maxchunk required
|
||||
void init(maxchunk, pagesize, pagedelta)
|
||||
define allocation params and allocate first page(s)
|
||||
call right after constructor
|
||||
can call again to reset allocation params and free previous pages
|
||||
maxchunk = max # of datums in one chunk, default = 1
|
||||
pagesize = # of datums in one page, default = 1024
|
||||
should be big enough to store multiple chunks
|
||||
pagedelta = # of pages to allocate at a time, default = 1
|
||||
return 1 if bad params
|
||||
void reset() = clear pages w/out freeing
|
||||
int size() = return total size of allocated pages in bytes
|
||||
int status() = return error status
|
||||
0 = ok, 1 = chunksize > maxchunk, 2 = allocation error
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "my_page.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#if defined(LMP_USER_INTEL) && !defined(LAMMPS_MEMALIGN) && !defined(_WIN32)
|
||||
#define LAMMPS_MEMALIGN 64
|
||||
#endif
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/** \class LAMMPS_NS::MyPage
|
||||
* \brief Templated class for storing chunks of datums in pages.
|
||||
*
|
||||
* The chunks are not returnable (i.e. cannot be freed individually).
|
||||
* One can only reset and start over. The purpose of this
|
||||
* class is to replace many small mallocs with a few large
|
||||
* mallocs. Since the pages are never freed, they can be re-used
|
||||
* without having to re-allocate them.
|
||||
*
|
||||
* The settings *maxchunk*, *pagesize*, and *pagedelta* contol
|
||||
* the memory allocation strategy. The *maxchunk* value represents
|
||||
* the expected largest number of items per chunk. If there is
|
||||
* less space left on the current page, a new page is allocated
|
||||
* for the next chunk. The *pagesize* value represents how many
|
||||
* items can fit on a single page. It should have space for multiple
|
||||
* chunks of size *maxchunk*. The combination of these two
|
||||
* parameters determines how much memory is wasted by either switching
|
||||
* to the next page too soon or allocating too large pages that never
|
||||
* get properly used. It is an error, if a requested chunk is larger
|
||||
* than *maxchunk*. The *pagedelta* parameter determines how many
|
||||
* pages are allocated in one go. In combination with the *pagesize*
|
||||
* setting, this determines how often blocks of memory get allocated
|
||||
* (fewer allocations will result in faster execution).
|
||||
*
|
||||
* This class is the "workhorse" for the memory management of
|
||||
* neighbor lists. */
|
||||
|
||||
/** Create a class instance
|
||||
*
|
||||
* Need to call init() before use to define allocation settings */
|
||||
|
||||
template <class T>
|
||||
MyPage<T>::MyPage() : ndatum(0), nchunk(0), pages(nullptr), page(nullptr),
|
||||
npage(0), ipage(-1), index(-1), maxchunk(-1),
|
||||
pagesize(-1), pagedelta(1), errorflag(0) {};
|
||||
|
||||
/** Free all allocated pages of this class instance */
|
||||
|
||||
template <class T>
|
||||
MyPage<T>::~MyPage() {
|
||||
for (int i = 0; i < npage; i++) free(pages[i]);
|
||||
free(pages);
|
||||
}
|
||||
|
||||
/** (Re-)initialize the set of pages and allocation parameters.
|
||||
*
|
||||
* This also frees all previously allocated storage and allocates
|
||||
* the first page(s).
|
||||
*
|
||||
* \param user_maxchunk Expected maximum number of items for one chunk
|
||||
* \param user_pagesize Number of items on a single memory page
|
||||
* \param user_page_delta Number of pages to allocate with one malloc
|
||||
* \return 1 if there was an error or 0 if successful */
|
||||
|
||||
template<class T>
|
||||
int MyPage<T>::init(int user_maxchunk, int user_pagesize,
|
||||
int user_pagedelta) {
|
||||
maxchunk = user_maxchunk;
|
||||
pagesize = user_pagesize;
|
||||
pagedelta = user_pagedelta;
|
||||
|
||||
if (maxchunk <= 0 || pagesize <= 0 || pagedelta <= 0) return 1;
|
||||
if (maxchunk > pagesize) return 1;
|
||||
|
||||
// free any previously allocated pages
|
||||
|
||||
for (int i = 0; i < npage; i++) free(pages[i]);
|
||||
free(pages);
|
||||
|
||||
// initial page allocation
|
||||
|
||||
ndatum = nchunk = 0;
|
||||
pages = NULL;
|
||||
npage = 0;
|
||||
allocate();
|
||||
if (errorflag) return 2;
|
||||
ipage = index = 0;
|
||||
page = pages[ipage];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Pointer to location that can store one item.
|
||||
*
|
||||
* This will allocate more pages as needed.
|
||||
*
|
||||
* \return memory location or null pointer, if memory allocation failed */
|
||||
|
||||
template <class T>
|
||||
T *MyPage<T>::get() {
|
||||
ndatum++;
|
||||
nchunk++;
|
||||
if (index < pagesize) return &page[index++];
|
||||
ipage++;
|
||||
if (ipage == npage) {
|
||||
allocate();
|
||||
if (errorflag) return NULL;
|
||||
}
|
||||
page = pages[ipage];
|
||||
index = 0;
|
||||
return &page[index++];
|
||||
}
|
||||
|
||||
/** Pointer to location that can store N items.
|
||||
*
|
||||
* This will allocate more pages as needed.
|
||||
* If the parameter *N* is larger than the *maxchunk*
|
||||
* setting an error is flagged.
|
||||
*
|
||||
* \param n number of items for which storage is requested
|
||||
* \return memory location or null pointer, if error or allocation failed */
|
||||
|
||||
template <class T>
|
||||
T *MyPage<T>::get(int n) {
|
||||
if (n > maxchunk) {
|
||||
errorflag = 1;
|
||||
return NULL;
|
||||
}
|
||||
ndatum += n;
|
||||
nchunk++;
|
||||
if (index+n <= pagesize) {
|
||||
int start = index;
|
||||
index += n;
|
||||
return &page[start];
|
||||
}
|
||||
ipage++;
|
||||
if (ipage == npage) {
|
||||
allocate();
|
||||
if (errorflag) return NULL;
|
||||
}
|
||||
page = pages[ipage];
|
||||
index = n;
|
||||
return &page[0];
|
||||
}
|
||||
|
||||
/** Get pointer to location that can store *maxchunk* items.
|
||||
*
|
||||
* This will return the same pointer as the previous call to
|
||||
* this function unless vgot() is called afterwards to record
|
||||
* how many items of the chunk were actually used.
|
||||
*
|
||||
* \return pointer to chunk of memory or null pointer if run out of memory */
|
||||
|
||||
template <class T>
|
||||
T *MyPage<T>::vget() {
|
||||
if (index+maxchunk <= pagesize) return &page[index];
|
||||
ipage++;
|
||||
if (ipage == npage) {
|
||||
allocate();
|
||||
if (errorflag) return NULL;
|
||||
}
|
||||
page = pages[ipage];
|
||||
index = 0;
|
||||
return &page[index];
|
||||
}
|
||||
|
||||
/** Mark *N* items as used of the chunk reserved with a preceding call to vget().
|
||||
*
|
||||
* This will advance the internal pointer inside the current memory page.
|
||||
* It is not necessary to call this function for *N* = 0, that is the reserved
|
||||
* storage was not used. A following call to vget() will then reserve the
|
||||
* same location again. It is an error if *N* > *maxchunk*.
|
||||
*
|
||||
* \param n Number of iterms used in previously reserved chunk */
|
||||
|
||||
template <class T>
|
||||
void MyPage<T>::vgot(int n) {
|
||||
if (n > maxchunk) errorflag = 1;
|
||||
ndatum += n;
|
||||
nchunk++;
|
||||
index += n;
|
||||
}
|
||||
|
||||
/** Reset state of memory pool without freeing any memory */
|
||||
|
||||
template <class T>
|
||||
void MyPage<T>::reset() {
|
||||
ndatum = nchunk = 0;
|
||||
index = ipage = 0;
|
||||
page = pages[ipage];
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
template <class T>
|
||||
void MyPage<T>::allocate() {
|
||||
npage += pagedelta;
|
||||
pages = (T **) realloc(pages,npage*sizeof(T *));
|
||||
if (!pages) {
|
||||
errorflag = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = npage-pagedelta; i < npage; i++) {
|
||||
#if defined(LAMMPS_MEMALIGN)
|
||||
void *ptr;
|
||||
if (posix_memalign(&ptr, LAMMPS_MEMALIGN, pagesize*sizeof(T)))
|
||||
errorflag = 2;
|
||||
pages[i] = (T *) ptr;
|
||||
#else
|
||||
pages[i] = (T *) malloc(pagesize*sizeof(T));
|
||||
if (!pages[i]) errorflag = 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
#include "REPLICA/fix_hyper_local.h"
|
||||
namespace LAMMPS_NS {
|
||||
template class MyPage<int>;
|
||||
template class MyPage<long>;
|
||||
template class MyPage<long long>;
|
||||
template class MyPage<double>;
|
||||
template class MyPage<FixHyperLocal::OneCoeff>;
|
||||
}
|
||||
193
src/my_page.h
193
src/my_page.h
@ -12,37 +12,7 @@
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
MyPage = templated class for storing chunks of datums in pages
|
||||
chunks are not returnable, can only reset and start over
|
||||
replaces many small mallocs with a few large mallocs
|
||||
pages are never freed, so can reuse w/out reallocs
|
||||
usage:
|
||||
request one datum at a time, repeat, clear
|
||||
request chunks of datums in each get() or vget(), repeat, clear
|
||||
chunk size can vary from request to request
|
||||
chunk size can be known in advance or registered after usage via vgot()
|
||||
inputs:
|
||||
template T = one datum, e.g. int, double, struct, int[3]
|
||||
for int[3], access datum as ivec[i][2]
|
||||
methods:
|
||||
T *get() = return ptr to one datum
|
||||
T *get(N) = return ptr to N datums, N < maxchunk required
|
||||
T *vget() = return ptr to maxchunk datums, use as needed, then call vgot()
|
||||
all gets return NULL if error encountered
|
||||
vgot(N) = used N datums of previous vget(), N < maxchunk required
|
||||
void init(maxchunk, pagesize, pagedelta)
|
||||
define allocation params and allocate first page(s)
|
||||
call right after constructor
|
||||
can call again to reset allocation params and free previous pages
|
||||
maxchunk = max # of datums in one chunk, default = 1
|
||||
pagesize = # of datums in one page, default = 1024
|
||||
should be big enough to store multiple chunks
|
||||
pagedelta = # of pages to allocate at a time, default = 1
|
||||
return 1 if bad params
|
||||
void reset() = clear pages w/out freeing
|
||||
int size() = return total size of allocated pages in bytes
|
||||
int status() = return error status
|
||||
0 = ok, 1 = chunksize > maxchunk, 2 = allocation error
|
||||
templated class for storing chunks of datums in pages
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LAMMPS_MY_PAGE_H
|
||||
@ -52,7 +22,6 @@ methods:
|
||||
#define LAMMPS_MEMALIGN 64
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
template<class T>
|
||||
@ -60,139 +29,33 @@ class MyPage {
|
||||
public:
|
||||
int ndatum; // total # of stored datums
|
||||
int nchunk; // total # of stored chunks
|
||||
|
||||
MyPage() {
|
||||
ndatum = nchunk = 0;
|
||||
pages = NULL;
|
||||
npage = 0;
|
||||
errorflag = 0;
|
||||
}
|
||||
|
||||
// (re)initialize allocation params
|
||||
// also allocate first page(s)
|
||||
MyPage();
|
||||
virtual ~MyPage();
|
||||
|
||||
int init(int user_maxchunk = 1, int user_pagesize = 1024,
|
||||
int user_pagedelta = 1) {
|
||||
maxchunk = user_maxchunk;
|
||||
pagesize = user_pagesize;
|
||||
pagedelta = user_pagedelta;
|
||||
int user_pagedelta = 1);
|
||||
|
||||
T *get();
|
||||
T *get(int n);
|
||||
|
||||
if (maxchunk <= 0 || pagesize <= 0 || pagedelta <= 0) return 1;
|
||||
if (maxchunk > pagesize) return 1;
|
||||
T *vget();
|
||||
void vgot(int n);
|
||||
|
||||
// free any previously allocated pages
|
||||
void reset();
|
||||
|
||||
for (int i = 0; i < npage; i++) free(pages[i]);
|
||||
free(pages);
|
||||
|
||||
// initial page allocation
|
||||
|
||||
ndatum = nchunk = 0;
|
||||
pages = NULL;
|
||||
npage = 0;
|
||||
allocate();
|
||||
if (errorflag) return 2;
|
||||
ipage = index = 0;
|
||||
page = pages[ipage];
|
||||
return 0;
|
||||
}
|
||||
|
||||
// free all allocated pages
|
||||
|
||||
~MyPage() {
|
||||
for (int i = 0; i < npage; i++) free(pages[i]);
|
||||
free(pages);
|
||||
}
|
||||
|
||||
// get ptr to one datum
|
||||
// return NULL if run out of memory
|
||||
|
||||
T *get() {
|
||||
ndatum++;
|
||||
nchunk++;
|
||||
if (index < pagesize) return &page[index++];
|
||||
ipage++;
|
||||
if (ipage == npage) {
|
||||
allocate();
|
||||
if (errorflag) return NULL;
|
||||
}
|
||||
page = pages[ipage];
|
||||
index = 0;
|
||||
return &page[index++];
|
||||
}
|
||||
|
||||
// get ptr to location that can store N datums
|
||||
// error if N > maxchunk
|
||||
// return NULL if run out of memory
|
||||
|
||||
T *get(int n) {
|
||||
if (n > maxchunk) {
|
||||
errorflag = 1;
|
||||
return NULL;
|
||||
}
|
||||
ndatum += n;
|
||||
nchunk++;
|
||||
if (index+n <= pagesize) {
|
||||
int start = index;
|
||||
index += n;
|
||||
return &page[start];
|
||||
}
|
||||
ipage++;
|
||||
if (ipage == npage) {
|
||||
allocate();
|
||||
if (errorflag) return NULL;
|
||||
}
|
||||
page = pages[ipage];
|
||||
index = n;
|
||||
return &page[0];
|
||||
}
|
||||
|
||||
// get ptr to location that can store maxchunk datums
|
||||
// will return same ptr as previous call if vgot() not called
|
||||
// return NULL if run out of memory
|
||||
|
||||
T *vget() {
|
||||
if (index+maxchunk <= pagesize) return &page[index];
|
||||
ipage++;
|
||||
if (ipage == npage) {
|
||||
allocate();
|
||||
if (errorflag) return NULL;
|
||||
}
|
||||
page = pages[ipage];
|
||||
index = 0;
|
||||
return &page[index];
|
||||
}
|
||||
|
||||
// increment by N = # of values stored in loc returned by vget()
|
||||
// OK to not call if vget() ptr was not used
|
||||
// error if N > maxchunk
|
||||
|
||||
void vgot(int n) {
|
||||
if (n > maxchunk) errorflag = 1;
|
||||
ndatum += n;
|
||||
nchunk++;
|
||||
index += n;
|
||||
}
|
||||
|
||||
// clear all pages, without freeing any memory
|
||||
|
||||
void reset() {
|
||||
ndatum = nchunk = 0;
|
||||
index = ipage = 0;
|
||||
page = pages[ipage];
|
||||
}
|
||||
|
||||
// return total size of allocated pages
|
||||
/** Return total size of allocated pages
|
||||
*
|
||||
* \return total storage used in bytes */
|
||||
|
||||
int size() const {
|
||||
return npage*pagesize*sizeof(T);
|
||||
}
|
||||
|
||||
// return error status
|
||||
/** Return error status
|
||||
*
|
||||
* \return 0 if no error, 1 requested chunk size > maxchunk, 2 if malloc failed */
|
||||
|
||||
int status() const {
|
||||
return errorflag;
|
||||
}
|
||||
int status() const { return errorflag; }
|
||||
|
||||
private:
|
||||
T **pages; // list of allocated pages
|
||||
@ -208,27 +71,7 @@ class MyPage {
|
||||
int errorflag; // flag > 0 if error has occurred
|
||||
// 1 = chunk size exceeded maxchunk
|
||||
// 2 = memory allocation error
|
||||
|
||||
void allocate() {
|
||||
npage += pagedelta;
|
||||
pages = (T **) realloc(pages,npage*sizeof(T *));
|
||||
if (!pages) {
|
||||
errorflag = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = npage-pagedelta; i < npage; i++) {
|
||||
#if defined(LAMMPS_MEMALIGN)
|
||||
void *ptr;
|
||||
if (posix_memalign(&ptr, LAMMPS_MEMALIGN, pagesize*sizeof(T)))
|
||||
errorflag = 2;
|
||||
pages[i] = (T *) ptr;
|
||||
#else
|
||||
pages[i] = (T *) malloc(pagesize*sizeof(T));
|
||||
if (!pages[i]) errorflag = 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void allocate();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user