mirror of https://github.com/lammps/lammps.git
small updates to MyPage and convert MyPoolChunk similar to MyPage
This commit is contained in:
parent
a3cc7581b1
commit
9f7e309f07
|
@ -430,6 +430,7 @@ INPUT = @LAMMPS_SOURCE_DIR@/utils.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.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/my_pool_chunk.h \
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
|
|
|
@ -1162,3 +1162,7 @@ its size is registered later with :cpp:func:`vgot()
|
|||
.. doxygenclass:: LAMMPS_NS::MyPage
|
||||
:project: progguide
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: LAMMPS_NS::MyPoolChunk
|
||||
:project: progguide
|
||||
:members:
|
||||
|
|
|
@ -555,7 +555,7 @@ bigint AtomVecBody::memory_usage_bonus()
|
|||
{
|
||||
bigint bytes = 0;
|
||||
bytes += nmax_bonus*sizeof(Bonus);
|
||||
bytes += icp->size + dcp->size;
|
||||
bytes += icp->size() + dcp->size();
|
||||
|
||||
int nall = nlocal_bonus + nghost_bonus;
|
||||
for (int i = 0; i < nall; i++) {
|
||||
|
|
|
@ -29,8 +29,9 @@ using namespace LAMMPS_NS;
|
|||
* The chunks are not returnable like with malloc() (i.e. you cannot
|
||||
* call free() on them individually). One can only reset and start over.
|
||||
* The purpose of this class is to replace many small memory allocations
|
||||
* via malloc() with a few large ones. Since the pages are never freed,
|
||||
* they can be re-used without having to re-allocate them.
|
||||
* via malloc() with a few large ones. Since the pages are never freed
|
||||
* until the class is re-initialized, they can be re-used without having
|
||||
* to re-allocate them by calling the reset() method.
|
||||
*
|
||||
* The settings *maxchunk*, *pagesize*, and *pagedelta* control
|
||||
* the memory allocation strategy. The *maxchunk* value represents
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
#ifndef LAMMPS_MY_PAGE_H
|
||||
#define LAMMPS_MY_PAGE_H
|
||||
|
||||
#if defined(LMP_USER_INTEL) && !defined(LAMMPS_MEMALIGN) && !defined(_WIN32)
|
||||
#define LAMMPS_MEMALIGN 64
|
||||
#endif
|
||||
|
||||
#include "lmptype.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
|
|
@ -0,0 +1,244 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "my_pool_chunk.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#if defined(LMP_USER_INTEL) && !defined(LAMMPS_MEMALIGN) && !defined(_WIN32)
|
||||
#define LAMMPS_MEMALIGN 64
|
||||
#endif
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/** \class LAMMPS_NS::MyPoolChunk
|
||||
* \brief Templated class for storing chunks of datums in pages
|
||||
*
|
||||
* The size of the chunk may vary from call to call between the
|
||||
* *minchunk* and *maxchunk* setting. Chunks may be returned
|
||||
* to the pool for re-use. Chunks can be reserved in *nbin*
|
||||
* different sizes between *minchunk* and *maxchunk*.
|
||||
* The *chunksperpage* setting specifies how many chunks are stored
|
||||
* on any page and the *pagedelta* setting determines how many
|
||||
* pages are allocated in one go. Pages are never freed, so they
|
||||
* can be re-used without re-allocation.
|
||||
*
|
||||
* \note
|
||||
* This is a template class with explicit instantiation. If the class
|
||||
* is used with a new data type a new explicit instantiation may need
|
||||
* to be added at the end of the file ``src/my_pool_chunk.cpp`` to
|
||||
* avoid symbol lookup errors. */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
MyPoolChunk = templated class for storing chunks of datums in pages
|
||||
chunks can be returned to pool for reuse
|
||||
chunks come in nbin different fixed sizes so can reuse
|
||||
replaces many small mallocs with a few large mallocs
|
||||
pages are never freed, so can reuse w/out reallocs
|
||||
usage:
|
||||
continuously get() and put() chunks as needed
|
||||
NOTE: could add a clear() if retain info on mapping of pages to bins
|
||||
inputs:
|
||||
template T = one datum, e.g. int, double, struct
|
||||
minchunk = min # of datums in one chunk, def = 1
|
||||
maxchunk = max # of datums in one chunk, def = 1
|
||||
nbin = # of bins between minchunk and maxchunk
|
||||
chunkperpage = # of chunks in one page, def = 1024
|
||||
pagedelta = # of pages to allocate at a time, def = 1
|
||||
methods:
|
||||
T *get(index) = return ptr/index to unused chunk of size maxchunk
|
||||
T *get(N,index) = return ptr/index to unused chunk of size N
|
||||
minchunk <= N <= maxchunk required
|
||||
put(index) = return indexed chunk to pool (same index returned by get)
|
||||
int size() = return total size of allocated pages in bytes
|
||||
public variables:
|
||||
ndatum = total # of stored datums
|
||||
nchunk = total # of stored chunks
|
||||
size = total size of all allocated pages in daums
|
||||
errorflag = flag for various error conditions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/** Create a class instance and set memory pool parameters */
|
||||
template <class T>
|
||||
MyPoolChunk<T>::MyPoolChunk(int user_minchunk, int user_maxchunk, int user_nbin,
|
||||
int user_chunkperpage, int user_pagedelta) {
|
||||
minchunk = user_minchunk;
|
||||
maxchunk = user_maxchunk;
|
||||
nbin = user_nbin;
|
||||
chunkperpage = user_chunkperpage;
|
||||
pagedelta = user_pagedelta;
|
||||
|
||||
errorflag = 0;
|
||||
if (minchunk <= 0 || minchunk > maxchunk) errorflag = 1;
|
||||
if (user_nbin <= 0 || chunkperpage <= 0 || pagedelta <= 0) errorflag = 1;
|
||||
|
||||
freehead = new int[nbin];
|
||||
chunksize = new int[nbin];
|
||||
if (!freehead || !chunksize) errorflag = 1;
|
||||
if (errorflag) return;
|
||||
|
||||
// insure nbin*binsize spans minchunk to maxchunk inclusive
|
||||
|
||||
binsize = (maxchunk-minchunk+1) / nbin;
|
||||
if (minchunk + nbin*binsize <= maxchunk) binsize++;
|
||||
|
||||
freelist = nullptr;
|
||||
for (int ibin = 0; ibin < nbin; ibin++) {
|
||||
freehead[ibin] = -1;
|
||||
chunksize[ibin] = minchunk + (ibin+1)*binsize - 1;
|
||||
if (chunksize[ibin] > maxchunk) chunksize[ibin] = maxchunk;
|
||||
}
|
||||
|
||||
ndatum = nchunk = 0;
|
||||
pages = nullptr;
|
||||
whichbin = nullptr;
|
||||
npage = 0;
|
||||
}
|
||||
|
||||
/** Destroy class instance and free all allocated memory */
|
||||
template <class T>
|
||||
MyPoolChunk<T>::~MyPoolChunk() {
|
||||
delete [] freehead;
|
||||
delete [] chunksize;
|
||||
if (npage) {
|
||||
free(freelist);
|
||||
for (int i = 0; i < npage; i++) free(pages[i]);
|
||||
free(pages);
|
||||
free(whichbin);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return pointer/index of unused chunk of size maxchunk
|
||||
*
|
||||
* \param index Index of chunk in memory pool
|
||||
* \return Pointer to requested chunk of storage */
|
||||
|
||||
template <class T>
|
||||
T *MyPoolChunk<T>::get(int &index) {
|
||||
int ibin = nbin-1;
|
||||
if (freehead[ibin] < 0) {
|
||||
allocate(ibin);
|
||||
if (errorflag) return nullptr;
|
||||
}
|
||||
|
||||
ndatum += maxchunk;
|
||||
nchunk++;
|
||||
index = freehead[ibin];
|
||||
int ipage = index/chunkperpage;
|
||||
int ientry = index % chunkperpage;
|
||||
freehead[ibin] = freelist[index];
|
||||
return &pages[ipage][ientry*chunksize[ibin]];
|
||||
}
|
||||
|
||||
/** Return pointer/index of unused chunk of size N
|
||||
*
|
||||
* \param n Size of chunk
|
||||
* \param index Index of chunk in memory pool
|
||||
* \return Pointer to requested chunk of storage */
|
||||
|
||||
template <class T>
|
||||
T *MyPoolChunk<T>::get(int n, int &index) {
|
||||
if (n < minchunk || n > maxchunk) {
|
||||
errorflag = 3;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int ibin = (n-minchunk) / binsize;
|
||||
if (freehead[ibin] < 0) {
|
||||
allocate(ibin);
|
||||
if (errorflag) return nullptr;
|
||||
}
|
||||
|
||||
ndatum += n;
|
||||
nchunk++;
|
||||
index = freehead[ibin];
|
||||
int ipage = index/chunkperpage;
|
||||
int ientry = index % chunkperpage;
|
||||
freehead[ibin] = freelist[index];
|
||||
return &pages[ipage][ientry*chunksize[ibin]];
|
||||
}
|
||||
|
||||
/** Put indexed chunk back into memory pool via free list
|
||||
*/
|
||||
// index = -1 if no allocated chunk
|
||||
|
||||
template <class T>
|
||||
void MyPoolChunk<T>::put(int index) {
|
||||
if (index < 0) return;
|
||||
int ipage = index/chunkperpage;
|
||||
int ibin = whichbin[ipage];
|
||||
nchunk--;
|
||||
ndatum -= chunksize[ibin];
|
||||
freelist[index] = freehead[ibin];
|
||||
freehead[ibin] = index;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
void MyPoolChunk<T>::allocate(int ibin) {
|
||||
int oldpage = npage;
|
||||
npage += pagedelta;
|
||||
freelist = (int *) realloc(freelist,npage*chunkperpage*sizeof(int));
|
||||
pages = (T **) realloc(pages,npage*sizeof(T *));
|
||||
whichbin = (int *) realloc(whichbin,npage*sizeof(int));
|
||||
if (!freelist || !pages) {
|
||||
errorflag = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
// allocate pages with appropriate chunksize for ibin
|
||||
|
||||
for (int i = oldpage; i < npage; i++) {
|
||||
whichbin[i] = ibin;
|
||||
#if defined(LAMMPS_MEMALIGN)
|
||||
void *ptr;
|
||||
if (posix_memalign(&ptr, LAMMPS_MEMALIGN,
|
||||
chunkperpage*chunksize[ibin]*sizeof(T)))
|
||||
errorflag = 2;
|
||||
pages[i] = (T *) ptr;
|
||||
#else
|
||||
pages[i] = (T *) malloc(chunkperpage*chunksize[ibin]*sizeof(T));
|
||||
size += chunkperpage*chunksize[ibin];
|
||||
if (!pages[i]) errorflag = 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
// reset free list for unused chunks on new pages
|
||||
|
||||
freehead[ibin] = oldpage*chunkperpage;
|
||||
for (int i = freehead[ibin]; i < npage*chunkperpage; i++) freelist[i] = i+1;
|
||||
freelist[npage*chunkperpage-1] = -1;
|
||||
}
|
||||
|
||||
/** Return total size of allocated pages
|
||||
*
|
||||
* \return total storage used in bytes */
|
||||
|
||||
template <class T>
|
||||
double MyPoolChunk<T>::size() const {
|
||||
double bytes = npage*chunkperpage*sizeof(int);
|
||||
bytes += npage*sizeof(T *);
|
||||
bytes += npage*sizeof(int);
|
||||
for (int i=0; i < npage; ++i)
|
||||
bytes += chunkperpage*chunksize[i]*sizeof(T);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
template class MyPoolChunk<int>;
|
||||
template class MyPoolChunk<double>;
|
||||
}
|
|
@ -9,46 +9,11 @@
|
|||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
MyPoolChunk = templated class for storing chunks of datums in pages
|
||||
chunks can be returned to pool for reuse
|
||||
chunks come in nbin different fixed sizes so can reuse
|
||||
replaces many small mallocs with a few large mallocs
|
||||
pages are never freed, so can reuse w/out reallocs
|
||||
usage:
|
||||
continuously get() and put() chunks as needed
|
||||
NOTE: could add a clear() if retain info on mapping of pages to bins
|
||||
inputs:
|
||||
template T = one datum, e.g. int, double, struct
|
||||
minchunk = min # of datums in one chunk, def = 1
|
||||
maxchunk = max # of datums in one chunk, def = 1
|
||||
nbin = # of bins between minchunk and maxchunk
|
||||
chunkperpage = # of chunks in one page, def = 1024
|
||||
pagedelta = # of pages to allocate at a time, def = 1
|
||||
methods:
|
||||
T *get(index) = return ptr/index to unused chunk of size maxchunk
|
||||
T *get(N,index) = return ptr/index to unused chunk of size N
|
||||
minchunk <= N <= maxchunk required
|
||||
put(index) = return indexed chunk to pool (same index returned by get)
|
||||
int size() = return total size of allocated pages in bytes
|
||||
public variables:
|
||||
ndatum = total # of stored datums
|
||||
nchunk = total # of stored chunks
|
||||
size = total size of all allocated pages in daums
|
||||
errorflag = flag for various error conditions
|
||||
------------------------------------------------------------------------- */
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LAMMPS_MY_POOL_CHUNK_H
|
||||
#define LAMMPS_MY_POOL_CHUNK_H
|
||||
|
||||
#if defined(LMP_USER_INTEL) && !defined(LAMMPS_MEMALIGN) && !defined(_WIN32)
|
||||
#define LAMMPS_MEMALIGN 64
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
template<class T>
|
||||
|
@ -56,113 +21,36 @@ class MyPoolChunk {
|
|||
public:
|
||||
int ndatum; // total # of stored datums
|
||||
int nchunk; // total # of stored chunks
|
||||
int size; // total size of all allocated pages in datums
|
||||
int errorflag; // flag > 1 if error has occurred
|
||||
// 1 = invalid inputs
|
||||
// 2 = memory allocation error
|
||||
// 3 = chunk size exceeded maxchunk
|
||||
|
||||
MyPoolChunk(int user_minchunk = 1, int user_maxchunk = 1, int user_nbin = 1,
|
||||
int user_chunkperpage = 1024, int user_pagedelta = 1) {
|
||||
minchunk = user_minchunk;
|
||||
maxchunk = user_maxchunk;
|
||||
nbin = user_nbin;
|
||||
chunkperpage = user_chunkperpage;
|
||||
pagedelta = user_pagedelta;
|
||||
|
||||
errorflag = 0;
|
||||
if (minchunk <= 0 || minchunk > maxchunk) errorflag = 1;
|
||||
if (user_nbin <= 0 || chunkperpage <= 0 || pagedelta <= 0) errorflag = 1;
|
||||
|
||||
freehead = new int[nbin];
|
||||
chunksize = new int[nbin];
|
||||
if (!freehead || !chunksize) errorflag = 1;
|
||||
if (errorflag) return;
|
||||
|
||||
// insure nbin*binsize spans minchunk to maxchunk inclusive
|
||||
|
||||
binsize = (maxchunk-minchunk+1) / nbin;
|
||||
if (minchunk + nbin*binsize <= maxchunk) binsize++;
|
||||
|
||||
freelist = NULL;
|
||||
for (int ibin = 0; ibin < nbin; ibin++) {
|
||||
freehead[ibin] = -1;
|
||||
chunksize[ibin] = minchunk + (ibin+1)*binsize - 1;
|
||||
if (chunksize[ibin] > maxchunk) chunksize[ibin] = maxchunk;
|
||||
}
|
||||
|
||||
ndatum = nchunk = size = 0;
|
||||
pages = NULL;
|
||||
whichbin = NULL;
|
||||
npage = 0;
|
||||
}
|
||||
int user_chunkperpage = 1024, int user_pagedelta = 1);
|
||||
|
||||
// free all allocated memory
|
||||
|
||||
~MyPoolChunk() {
|
||||
delete [] freehead;
|
||||
delete [] chunksize;
|
||||
if (npage) {
|
||||
free(freelist);
|
||||
for (int i = 0; i < npage; i++) free(pages[i]);
|
||||
free(pages);
|
||||
free(whichbin);
|
||||
}
|
||||
}
|
||||
~MyPoolChunk();
|
||||
|
||||
// return pointer/index of unused chunk of size maxchunk
|
||||
|
||||
T *get(int &index) {
|
||||
int ibin = nbin-1;
|
||||
if (freehead[ibin] < 0) {
|
||||
allocate(ibin);
|
||||
if (errorflag) return NULL;
|
||||
}
|
||||
|
||||
ndatum += maxchunk;
|
||||
nchunk++;
|
||||
index = freehead[ibin];
|
||||
int ipage = index/chunkperpage;
|
||||
int ientry = index % chunkperpage;
|
||||
freehead[ibin] = freelist[index];
|
||||
return &pages[ipage][ientry*chunksize[ibin]];
|
||||
}
|
||||
T *get(int &index);
|
||||
|
||||
// return pointer/index of unused chunk of size N
|
||||
|
||||
T *get(int n, int &index) {
|
||||
if (n < minchunk || n > maxchunk) {
|
||||
errorflag = 3;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ibin = (n-minchunk) / binsize;
|
||||
if (freehead[ibin] < 0) {
|
||||
allocate(ibin);
|
||||
if (errorflag) return NULL;
|
||||
}
|
||||
|
||||
ndatum += n;
|
||||
nchunk++;
|
||||
index = freehead[ibin];
|
||||
int ipage = index/chunkperpage;
|
||||
int ientry = index % chunkperpage;
|
||||
freehead[ibin] = freelist[index];
|
||||
return &pages[ipage][ientry*chunksize[ibin]];
|
||||
}
|
||||
|
||||
T *get(int n, int &index);
|
||||
|
||||
// return indexed chunk to pool via free list
|
||||
// index = -1 if no allocated chunk
|
||||
|
||||
void put(int index) {
|
||||
if (index < 0) return;
|
||||
int ipage = index/chunkperpage;
|
||||
int ibin = whichbin[ipage];
|
||||
nchunk--;
|
||||
ndatum -= chunksize[ibin];
|
||||
freelist[index] = freehead[ibin];
|
||||
freehead[ibin] = index;
|
||||
}
|
||||
void put(int index);
|
||||
|
||||
// total memory used in bytes
|
||||
|
||||
double size() const;
|
||||
|
||||
/** Return error status
|
||||
*
|
||||
* \return 0 if no error, 1 if invalid input, 2 if malloc() failed, 3 if chunk > maxchunk */
|
||||
|
||||
int status() const { return errorflag; }
|
||||
|
||||
private:
|
||||
int minchunk; // min # of datums per chunk
|
||||
|
@ -171,6 +59,10 @@ class MyPoolChunk {
|
|||
int chunkperpage; // # of chunks on every page, regardless of which bin
|
||||
int pagedelta; // # of pages to allocate at once, default = 1
|
||||
int binsize; // delta in chunk sizes between adjacent bins
|
||||
int errorflag; // flag > 0 if error has occurred
|
||||
// 1 = invalid inputs
|
||||
// 2 = memory allocation error
|
||||
// 3 = chunk size exceeded maxchunk
|
||||
|
||||
T **pages; // list of allocated pages
|
||||
int *whichbin; // which bin each page belongs to
|
||||
|
@ -179,42 +71,7 @@ class MyPoolChunk {
|
|||
int *freehead; // index of first unused chunk in each bin
|
||||
int *chunksize; // size of chunks in each bin
|
||||
|
||||
void allocate(int ibin) {
|
||||
int oldpage = npage;
|
||||
npage += pagedelta;
|
||||
freelist = (int *) realloc(freelist,npage*chunkperpage*sizeof(int));
|
||||
pages = (T **) realloc(pages,npage*sizeof(T *));
|
||||
whichbin = (int *) realloc(whichbin,npage*sizeof(int));
|
||||
if (!freelist || !pages) {
|
||||
errorflag = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
// allocate pages with appropriate chunksize for ibin
|
||||
|
||||
for (int i = oldpage; i < npage; i++) {
|
||||
whichbin[i] = ibin;
|
||||
#if defined(LAMMPS_MEMALIGN)
|
||||
void *ptr;
|
||||
if (posix_memalign(&ptr, LAMMPS_MEMALIGN,
|
||||
chunkperpage*chunksize[ibin]*sizeof(T)))
|
||||
errorflag = 2;
|
||||
pages[i] = (T *) ptr;
|
||||
#else
|
||||
pages[i] = (T *) malloc(chunkperpage*chunksize[ibin]*sizeof(T));
|
||||
size += chunkperpage*chunksize[ibin];
|
||||
if (!pages[i]) errorflag = 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
// reset free list for unused chunks on new pages
|
||||
|
||||
freehead[ibin] = oldpage*chunkperpage;
|
||||
for (int i = freehead[ibin]; i < npage*chunkperpage; i++) freelist[i] = i+1;
|
||||
freelist[npage*chunkperpage-1] = -1;
|
||||
}
|
||||
void allocate(int ibin);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue