mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'feature-memory_pool' into 'develop'
Draft: ENH: integrate memory pool support for List allocations See merge request Development/openfoam!739
This commit is contained in:
@ -132,6 +132,11 @@ projectDir="$HOME/OpenFOAM/OpenFOAM-$WM_PROJECT_VERSION"
|
||||
# projectDir="@PROJECT_DIR@"
|
||||
: # Safety statement (if the user removed all fallback values)
|
||||
|
||||
# [FOAM_MEMORY_POOL] - Optional memory management
|
||||
# - overrides the 'memory_pool' etc/controlDict entry
|
||||
# = "true | false | host [size=nn] [incr=nn]"
|
||||
#export FOAM_MEMORY_POOL="host"
|
||||
|
||||
# [FOAM_SIGFPE] - Trap floating-point exceptions.
|
||||
# - overrides the 'trapFpe' controlDict entry
|
||||
# = true | false
|
||||
|
||||
@ -221,6 +221,9 @@ OptimisationSwitches
|
||||
// Other
|
||||
// =====
|
||||
|
||||
// Optional memory management (sizing in MB)
|
||||
// memory_pool "host; size=1024; incr=5"
|
||||
|
||||
// Trap floating point exception.
|
||||
// Can override with FOAM_SIGFPE env variable (true|false)
|
||||
trapFpe 1;
|
||||
|
||||
@ -134,6 +134,11 @@ set projectDir=`lsof +p $$ |& sed -ne 's#^[^/]*##;\@/'"$projectName"'[^/]*/etc/c
|
||||
# Or optionally hard-coded (eg, with autoconfig)
|
||||
# set projectDir="@PROJECT_DIR@"
|
||||
|
||||
# [FOAM_MEMORY_POOL] - Optional memory management
|
||||
# - overrides the 'memory_pool' etc/controlDict entry
|
||||
# = "true | false | host [size=nn] [incr=nn]"
|
||||
#setenv FOAM_MEMORY_POOL "host"
|
||||
|
||||
# [FOAM_SIGFPE] - Trap floating-point exceptions.
|
||||
# - overrides the 'trapFpe' controlDict entry
|
||||
# = true | false
|
||||
|
||||
@ -3,6 +3,8 @@ MSwindows.C
|
||||
cpuInfo/cpuInfo.C
|
||||
memInfo/memInfo.C
|
||||
|
||||
memory/MemoryPool.cxx
|
||||
|
||||
signals/sigFpe.cxx
|
||||
signals/sigInt.cxx
|
||||
signals/sigQuit.cxx
|
||||
|
||||
83
src/OSspecific/MSwindows/memory/MemoryPool.cxx
Normal file
83
src/OSspecific/MSwindows/memory/MemoryPool.cxx
Normal file
@ -0,0 +1,83 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "MemoryPool.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
// bool Foam::MemoryPool::create(const std::string& ctrl, bool verbose)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
|
||||
bool Foam::MemoryPool::create(bool verbose)
|
||||
{
|
||||
// No banner information since it is currently never an option
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::MemoryPool::destroy(bool verbose)
|
||||
{}
|
||||
|
||||
|
||||
bool Foam::MemoryPool::active() noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::MemoryPool::suspend() noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::MemoryPool::resume() noexcept
|
||||
{}
|
||||
|
||||
|
||||
bool Foam::MemoryPool::is_pool(void* ptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void* Foam::MemoryPool::try_allocate(std::size_t nbytes)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::MemoryPool::try_deallocate(void* ptr)
|
||||
{
|
||||
return (!ptr);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -2,6 +2,7 @@
|
||||
cd "${0%/*}" || exit # Run from this directory
|
||||
targetType=libo # Preferred library type
|
||||
. ${WM_PROJECT_DIR:?}/wmake/scripts/AllwmakeParseArguments $*
|
||||
. ${WM_PROJECT_DIR:?}/wmake/scripts/have_umpire
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Hack for MacOS (with Gcc).
|
||||
@ -59,6 +60,47 @@ then
|
||||
export COMP_FLAGS="-DFOAM_USE_INOTIFY"
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# Have -lumpire, but also -lcamp etc.
|
||||
# Also need to follow the link order
|
||||
get_umpire_libs()
|
||||
{
|
||||
if [ -d "${UMPIRE_LIB_DIR}" ]
|
||||
then
|
||||
set -- $(
|
||||
# Expected link order
|
||||
for name in umpire fmt camp
|
||||
do
|
||||
[ -f "$UMPIRE_LIB_DIR/lib${name}.a" ] && echo "-l$name"
|
||||
done
|
||||
)
|
||||
echo "$@"
|
||||
else
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
if have_umpire
|
||||
then
|
||||
libNames="$(get_umpire_libs)"
|
||||
|
||||
if [ -n "$libNames" ]
|
||||
then
|
||||
echo " found umpire -- enabling memory pool interface" 1>&2
|
||||
echo " umpire libs: $libNames" 1>&2
|
||||
|
||||
COMP_FLAGS="$COMP_FLAGS -DFOAM_USE_UMPIRE -I${UMPIRE_INC_DIR}"
|
||||
LINK_FLAGS="$LINK_FLAGS -L${UMPIRE_LIB_DIR} $libNames"
|
||||
export COMP_FLAGS LINK_FLAGS
|
||||
else
|
||||
echo " expecting umpire, but did not resolve the libraries" 1>&2
|
||||
fi
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# Make object (non-shared by default)
|
||||
# Never want/need openmp, especially for static objects
|
||||
wmake -no-openmp $targetType
|
||||
|
||||
@ -4,6 +4,8 @@ cpuInfo/cpuInfo.C
|
||||
cpuTime/cpuTimePosix.C
|
||||
memInfo/memInfo.C
|
||||
|
||||
memory/MemoryPool.cxx
|
||||
|
||||
signals/sigFpe.cxx
|
||||
signals/sigSegv.cxx
|
||||
signals/sigInt.cxx
|
||||
|
||||
@ -1 +1,4 @@
|
||||
EXE_INC = $(COMP_FLAGS)
|
||||
/* umpire uses old-style cast etc */
|
||||
EXE_INC = $(COMP_FLAGS) $(c++LESSWARN)
|
||||
|
||||
LIBO_LIBS = $(LINK_FLAGS)
|
||||
|
||||
510
src/OSspecific/POSIX/memory/MemoryPool.cxx
Normal file
510
src/OSspecific/POSIX/memory/MemoryPool.cxx
Normal file
@ -0,0 +1,510 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "MemoryPool.H"
|
||||
#include "debug.H"
|
||||
#include "dictionary.H"
|
||||
#include "sigFpe.H"
|
||||
#include "OSspecific.H" // For getEnv
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef FOAM_USE_UMPIRE
|
||||
|
||||
// #include <cerrno>
|
||||
#include <cinttypes>
|
||||
#include <tuple>
|
||||
|
||||
#include "umpire/Allocator.hpp"
|
||||
#include "umpire/ResourceManager.hpp"
|
||||
#include "umpire/strategy/AlignedAllocator.hpp"
|
||||
#include "umpire/strategy/DynamicPoolList.hpp"
|
||||
|
||||
static bool disabled_(false);
|
||||
static umpire::Allocator aligned_allocator;
|
||||
static umpire::Allocator pooled_allocator;
|
||||
static umpire::ResourceManager* manager_(nullptr);
|
||||
static umpire::ResourceManager* suspended_(nullptr);
|
||||
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef FOAM_USE_UMPIRE
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Different supported allocation types
|
||||
enum class Types { undefined, none, host, device, managed };
|
||||
|
||||
typedef std::tuple<Types, std::size_t, std::size_t> ctrlTuple;
|
||||
|
||||
// Extract key=INT, the key includes the '='
|
||||
int getIntParameter(const std::string& key, const std::string& ctrl)
|
||||
{
|
||||
int val(0);
|
||||
|
||||
const auto pos = ctrl.find(key);
|
||||
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
const char* buf = (ctrl.data() + pos + key.size());
|
||||
|
||||
char *endptr = nullptr;
|
||||
errno = 0;
|
||||
auto parsed = std::strtoimax(buf, &endptr, 10);
|
||||
|
||||
if (errno || endptr == buf)
|
||||
{
|
||||
// Some type of error OR no conversion
|
||||
}
|
||||
else
|
||||
{
|
||||
val = int(parsed);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
ctrlTuple getControlValues(const std::string& ctrl)
|
||||
{
|
||||
ctrlTuple result(Types::undefined, 0, 0);
|
||||
|
||||
bool checkParam = false;
|
||||
|
||||
// Also find things that look like Switch constants.
|
||||
// Unfortunately need to do this manually since Switch::find()
|
||||
// itself would not manage to parse something like "true; size=10"
|
||||
|
||||
if (ctrl.empty())
|
||||
{
|
||||
// Nothing => undefined
|
||||
}
|
||||
else if
|
||||
(
|
||||
std::string::npos != ctrl.find("false") // ctrl.contains("false")
|
||||
|| std::string::npos != ctrl.find("off") // ctrl.contains("off")
|
||||
|| std::string::npos != ctrl.find("no") // ctrl.contains("no")
|
||||
|| std::string::npos != ctrl.find("none") // ctrl.contains("none")
|
||||
)
|
||||
{
|
||||
std::get<0>(result) = Types::none;
|
||||
}
|
||||
else if
|
||||
(
|
||||
std::string::npos != ctrl.find("true") // ctrl.contains("true")
|
||||
|| std::string::npos != ctrl.find("on") // ctrl.contains("on")
|
||||
|| std::string::npos != ctrl.find("yes") // ctrl.contains("yes")
|
||||
|
||||
|| std::string::npos != ctrl.find("host") // ctrl.contains("host")
|
||||
|| std::string::npos != ctrl.find("system") // ctrl.contains("system")
|
||||
)
|
||||
{
|
||||
std::get<0>(result) = Types::host;
|
||||
checkParam = true;
|
||||
}
|
||||
|
||||
// These need more testing
|
||||
else if
|
||||
(
|
||||
std::string::npos != ctrl.find("device") // ctrl.contains("device")
|
||||
)
|
||||
{
|
||||
std::get<0>(result) = Types::device;
|
||||
checkParam = true;
|
||||
}
|
||||
else if
|
||||
(
|
||||
std::string::npos != ctrl.find("managed") // ctrl.contains("managed")
|
||||
)
|
||||
{
|
||||
std::get<0>(result) = Types::managed;
|
||||
checkParam = true;
|
||||
}
|
||||
|
||||
if (checkParam)
|
||||
{
|
||||
std::get<1>(result) = getIntParameter("size=", ctrl);
|
||||
std::get<2>(result) = getIntParameter("incr=", ctrl);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool create_from(const ctrlTuple& controls, bool verbose)
|
||||
{
|
||||
using namespace Foam;
|
||||
|
||||
if (manager_ || suspended_)
|
||||
{
|
||||
// Already created
|
||||
return true;
|
||||
}
|
||||
|
||||
// Type, initial size, increment
|
||||
auto [which, size, incr] = controls;
|
||||
|
||||
// std::cerr
|
||||
// << "which=" << int(which)
|
||||
// << ", size=" << int(size)
|
||||
// << ", incr=" << int(incr) << '\n';
|
||||
|
||||
|
||||
constexpr size_t MegaByte(1024*1024);
|
||||
|
||||
switch (which)
|
||||
{
|
||||
case Types::undefined :
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
Info<< "memory pool : unused" << nl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Types::none :
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
Info<< "memory pool : disabled" << nl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Types::host :
|
||||
{
|
||||
// Default sizing parameters
|
||||
if (!size) size = 1024;
|
||||
if (!incr) incr = 5;
|
||||
|
||||
auto& rm = umpire::ResourceManager::getInstance();
|
||||
manager_ = &rm;
|
||||
|
||||
aligned_allocator =
|
||||
rm.makeAllocator<umpire::strategy::AlignedAllocator>
|
||||
(
|
||||
"aligned_allocator",
|
||||
rm.getAllocator("HOST"),
|
||||
|
||||
// alignment
|
||||
256
|
||||
);
|
||||
|
||||
pooled_allocator =
|
||||
rm.makeAllocator<umpire::strategy::DynamicPoolList>
|
||||
(
|
||||
"openfoam_HOST_pool",
|
||||
aligned_allocator,
|
||||
|
||||
// initial block allocation size
|
||||
(size*MegaByte),
|
||||
|
||||
// incremental block allocation size
|
||||
(incr*MegaByte)
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
Info<< "memory pool : host (size="
|
||||
<< int(size) << "MB, incr="
|
||||
<< int(incr) << "MB)\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Types::device :
|
||||
{
|
||||
auto& rm = umpire::ResourceManager::getInstance();
|
||||
manager_ = &rm;
|
||||
|
||||
aligned_allocator = rm.getAllocator("DEVICE");
|
||||
|
||||
pooled_allocator =
|
||||
rm.makeAllocator<umpire::strategy::DynamicPoolList>
|
||||
(
|
||||
"openfoam_DEVICE_pool",
|
||||
aligned_allocator
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
Info<< "memory pool : device" << nl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Types::managed :
|
||||
{
|
||||
// Default sizing parameters
|
||||
if (!size) size = 10*1024;
|
||||
if (!incr) incr = 10;
|
||||
|
||||
auto& rm = umpire::ResourceManager::getInstance();
|
||||
manager_ = &rm;
|
||||
|
||||
aligned_allocator = rm.getAllocator("UM");
|
||||
|
||||
pooled_allocator =
|
||||
rm.makeAllocator<umpire::strategy::DynamicPoolList>
|
||||
(
|
||||
"openfoam_UM_pool",
|
||||
aligned_allocator,
|
||||
|
||||
// initial block allocation size
|
||||
(size*MegaByte),
|
||||
|
||||
// incremental block allocation size
|
||||
(incr*MegaByte)
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
Info<< "memory pool : managed (size="
|
||||
<< int(size) << "MB, incr="
|
||||
<< int(incr) << "MB)\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (which != Types::undefined && which != Types::none);
|
||||
}
|
||||
|
||||
|
||||
} // End anonymous namespace
|
||||
|
||||
#endif // FOAM_USE_UMPIRE
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
// bool Foam::MemoryPool::create(const std::string& ctrl, bool verbose)
|
||||
// {
|
||||
// #ifdef FOAM_USE_UMPIRE
|
||||
// if (manager_ || suspended_)
|
||||
// {
|
||||
// // Already created
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// auto controls = getControlValues(ctrl);
|
||||
//
|
||||
// return create_from(controls, verbose);
|
||||
// #else
|
||||
// return false;
|
||||
// #endif
|
||||
// }
|
||||
|
||||
|
||||
bool Foam::MemoryPool::create(bool verbose)
|
||||
{
|
||||
#ifdef FOAM_USE_UMPIRE
|
||||
if (disabled_)
|
||||
{
|
||||
// Disallowed
|
||||
return false;
|
||||
}
|
||||
else if (manager_ || suspended_)
|
||||
{
|
||||
// Already created
|
||||
return true;
|
||||
}
|
||||
|
||||
// First check environment
|
||||
auto controls = getControlValues(Foam::getEnv("FOAM_MEMORY_POOL"));
|
||||
|
||||
if (std::get<0>(controls) == Types::none)
|
||||
{
|
||||
// Disabled from environment - has highest priority
|
||||
disabled_ = true;
|
||||
}
|
||||
|
||||
// Currently no easy way to handle <system>/controlDict...
|
||||
|
||||
// Fallback from etc/controlDict
|
||||
if (std::get<0>(controls) == Types::undefined)
|
||||
{
|
||||
// From central etc/controlDict
|
||||
const auto& dict = Foam::debug::optimisationSwitches();
|
||||
|
||||
if (auto* eptr = dict.findStream("memory_pool", keyType::LITERAL))
|
||||
{
|
||||
const token& firstToken = eptr->front();
|
||||
|
||||
if (firstToken.isStringType())
|
||||
{
|
||||
controls = getControlValues(firstToken.stringToken());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return create_from(controls, verbose);
|
||||
#else
|
||||
if (verbose)
|
||||
{
|
||||
Info<< "memory pool : not available" << nl;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Foam::MemoryPool::destroy(bool verbose)
|
||||
{
|
||||
// Nothing currently needed but could add in something like this:
|
||||
|
||||
// if (manager_ || suspended_)
|
||||
// {
|
||||
// pooled_allocator.release();
|
||||
// }
|
||||
|
||||
// However, need to find the proper sequence within
|
||||
// Foam::exit() or UPstream::exit() ...
|
||||
}
|
||||
|
||||
|
||||
bool Foam::MemoryPool::active() noexcept
|
||||
{
|
||||
#ifdef FOAM_USE_UMPIRE
|
||||
return bool(manager_);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool Foam::MemoryPool::suspend() noexcept
|
||||
{
|
||||
#ifdef FOAM_USE_UMPIRE
|
||||
bool status(suspended_);
|
||||
if (manager_) // <- and (!suspended_)
|
||||
{
|
||||
std::swap(manager_, suspended_);
|
||||
}
|
||||
return status;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Foam::MemoryPool::resume() noexcept
|
||||
{
|
||||
#ifdef FOAM_USE_UMPIRE
|
||||
if (suspended_) // <- and (!manager_)
|
||||
{
|
||||
std::swap(manager_, suspended_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool Foam::MemoryPool::is_pool(void* ptr)
|
||||
{
|
||||
#ifdef FOAM_USE_UMPIRE
|
||||
if (ptr)
|
||||
{
|
||||
if (manager_)
|
||||
{
|
||||
return manager_->hasAllocator(ptr);
|
||||
}
|
||||
else if (suspended_)
|
||||
{
|
||||
return suspended_->hasAllocator(ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void* Foam::MemoryPool::try_allocate(std::size_t nbytes)
|
||||
{
|
||||
void* ptr = nullptr;
|
||||
|
||||
#ifdef FOAM_USE_UMPIRE
|
||||
if (manager_)
|
||||
{
|
||||
ptr = pooled_allocator.allocate(nbytes);
|
||||
|
||||
// std::cerr<< "allocate(" << int(nbytes) << ")\n";
|
||||
|
||||
// Optionally fill with NaN (depends on current flags)
|
||||
Foam::sigFpe::fillNan_if(ptr, nbytes);
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
// Pout<< "umpire failed to allocate memory\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::MemoryPool::try_deallocate(void* ptr)
|
||||
{
|
||||
#ifdef FOAM_USE_UMPIRE
|
||||
if (ptr)
|
||||
{
|
||||
if (manager_)
|
||||
{
|
||||
if (manager_->hasAllocator(ptr)) // <- ie, is_pool()
|
||||
{
|
||||
// std::cerr<< "deallocate()\n";
|
||||
manager_->deallocate(ptr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (suspended_)
|
||||
{
|
||||
// Deallocate even if nominally suspended
|
||||
|
||||
if (suspended_->hasAllocator(ptr)) // <- ie, is_pool()
|
||||
{
|
||||
// std::cerr<< "deallocate()\n";
|
||||
suspended_->deallocate(ptr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return (!ptr);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -34,6 +34,7 @@ Description
|
||||
#ifndef Foam_ListPolicy_H
|
||||
#define Foam_ListPolicy_H
|
||||
|
||||
#include "MemoryPool.H" // Also includes <cstdint>
|
||||
#include "contiguous.H" // Also includes <type_traits>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -103,6 +104,18 @@ template<> struct no_linebreak<wordRe> : std::true_type {};
|
||||
// - use_offload(n) :
|
||||
// Lower threshold for switching to device offloading
|
||||
//
|
||||
//
|
||||
// Use of the memory-pool is controlled by the 'is_aligned_type()' test
|
||||
// and the minimum field size, controlled by the 'use_memory_pool()' test.
|
||||
//
|
||||
// If the memory-pool is not enabled or not required according to the two
|
||||
// above tests, the allocation falls back to either an aligned or unaligned
|
||||
// allocation.
|
||||
//
|
||||
// The decision about when to choose aligned vs unaligned allocation
|
||||
// is still a compile-time option. Made by direct edit of the
|
||||
// appropriate functions.
|
||||
//
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//- Consider aligned allocation for the given type?
|
||||
@ -146,27 +159,104 @@ inline constexpr bool use_offload(IntType n) noexcept
|
||||
}
|
||||
|
||||
|
||||
//- Default alignment for larger fields
|
||||
inline constexpr std::align_val_t default_alignment() noexcept
|
||||
{
|
||||
return std::align_val_t(256);
|
||||
}
|
||||
|
||||
|
||||
//- Allocate from memory pool (if active), or aligned, or normal
|
||||
template<class T, class IntType>
|
||||
inline T* allocate(IntType n)
|
||||
{
|
||||
// Plain new
|
||||
return new T[n];
|
||||
if constexpr (ListPolicy::is_aligned_type<T>())
|
||||
{
|
||||
// Note: threshold for use_memory_pool() >= use_alignment()
|
||||
|
||||
if (ListPolicy::use_alignment(n))
|
||||
{
|
||||
if
|
||||
(
|
||||
void *pool_ptr
|
||||
(
|
||||
// Consider memory pool for large amounts of data
|
||||
ListPolicy::use_memory_pool(n)
|
||||
? Foam::MemoryPool::try_allocate(sizeof(T)*n)
|
||||
: nullptr
|
||||
);
|
||||
pool_ptr
|
||||
)
|
||||
{
|
||||
// Placement new
|
||||
return new (pool_ptr) T[n];
|
||||
}
|
||||
else
|
||||
{
|
||||
return new (ListPolicy::default_alignment()) T[n];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Plain new
|
||||
return new T[n];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Plain new
|
||||
return new T[n];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//- Deallocate from memory pool, or normal
|
||||
template<class T, class IntType>
|
||||
inline void deallocate(T* ptr)
|
||||
{
|
||||
// Plain new
|
||||
delete[] ptr;
|
||||
if constexpr (ListPolicy::is_aligned_type<T>())
|
||||
{
|
||||
if (ptr && !Foam::MemoryPool::try_deallocate(ptr))
|
||||
{
|
||||
// Plain new
|
||||
delete[] ptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Plain new
|
||||
delete[] ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//- Deallocate from memory pool, or aligned, or normal
|
||||
template<class T, class IntType>
|
||||
inline void deallocate(T* ptr, [[maybe_unused]] IntType n)
|
||||
{
|
||||
// Plain new
|
||||
delete[] ptr;
|
||||
if constexpr (ListPolicy::is_aligned_type<T>())
|
||||
{
|
||||
// Note: threshold for use_memory_pool() >= use_alignment()
|
||||
|
||||
if (ListPolicy::use_alignment(n))
|
||||
{
|
||||
if (ptr && !Foam::MemoryPool::try_deallocate(ptr))
|
||||
{
|
||||
// Alignment depends on the number of elements
|
||||
::operator delete[](ptr, ListPolicy::default_alignment());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Plain new
|
||||
delete[] ptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Plain new
|
||||
delete[] ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@ License
|
||||
#include "IOobject.H"
|
||||
#include "dynamicCode.H"
|
||||
#include "simpleObjectRegistry.H"
|
||||
#include "MemoryPool.H"
|
||||
#include "sigFpe.H"
|
||||
#include "sigInt.H"
|
||||
#include "sigQuit.H"
|
||||
@ -2180,6 +2181,9 @@ void Foam::argList::parse
|
||||
sigQuit::set(bannerEnabled());
|
||||
sigSegv::set(bannerEnabled());
|
||||
|
||||
// Create memory pool (if any) after MPI has been setup
|
||||
MemoryPool::create(bannerEnabled());
|
||||
|
||||
if (UPstream::master() && bannerEnabled())
|
||||
{
|
||||
Info<< "fileModificationChecking : "
|
||||
|
||||
116
src/OpenFOAM/memory/pool/MemoryPool.H
Normal file
116
src/OpenFOAM/memory/pool/MemoryPool.H
Normal file
@ -0,0 +1,116 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::MemoryPool
|
||||
|
||||
Description
|
||||
Optional memory management using a memory pool such as Umpire
|
||||
(https://github.com/LLNL/Umpire).
|
||||
|
||||
When compiled with Umpire, its use can be controlled by the
|
||||
\c FOAM_MEMORY_POOL environment variable, or the
|
||||
\c memory_pool Optimisation switch (etc/controlDict).
|
||||
|
||||
It currently looks for any of the following entries, in this order:
|
||||
- true - same as \em "host"
|
||||
- false/none - disabled.
|
||||
- \em "host" - uses host memory pool
|
||||
- \em "system" - same as \em "host"
|
||||
- \em "device" - uses device memory pool
|
||||
- \em "managed" - uses managed host/device memory pool
|
||||
.
|
||||
|
||||
The parameters "size=nn" and "incr=nn" (in MegaBytes) can be used
|
||||
to specify alternatives to the default sizing.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_MemoryPool_H
|
||||
#define Foam_MemoryPool_H
|
||||
|
||||
#include <cstdint> // For size_t
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class MemoryPool Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class MemoryPool
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Create a memory pool instance (if not already active).
|
||||
// Uses environment or etc/controlDict entry
|
||||
static bool create(bool verbose = false);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
//- Remove the memory pool instance (currently does nothing)
|
||||
static void destroy(bool verbose = false);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- True if pool is active (ie, created and not suspended)
|
||||
static bool active() noexcept;
|
||||
|
||||
//- Suspend use of memory pool (for allocation).
|
||||
// \return previous suspend status
|
||||
static bool suspend() noexcept;
|
||||
|
||||
//- Resume use of memory pool (if previously active)
|
||||
static void resume() noexcept;
|
||||
|
||||
//- Test if given pointer belongs to the pool
|
||||
static bool is_pool(void *ptr);
|
||||
|
||||
//- Allocate from pool (if active).
|
||||
// \returns nullptr if the pool is not active
|
||||
static void* try_allocate(std::size_t nbytes);
|
||||
|
||||
//- Deallocate a pointer managed by the pool
|
||||
// \returns True if a nullptr (no-op) or when the pointer was
|
||||
// managed by the pool.
|
||||
static bool try_deallocate(void *ptr);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user