NUMA++ 0.11.0
Loading...
Searching...
No Matches
numapp::MemPolicy Class Reference

Class representing a memory policy that can be modified and used to apply to the current thread or a memory range. More...

#include <numapp/mempolicy.hpp>

Public Types

enum class  Mode : int { Default = MPOL_DEFAULT , Bind = MPOL_BIND , Interleave = MPOL_INTERLEAVE , Preferred = MPOL_PREFERRED }
 Memory allocation modes. More...
 

Public Member Functions

 MemPolicy (Mode mode, Nodemask &&node_mask) noexcept
 Create memory policy.
 
bool operator== (MemPolicy const &rhs) const noexcept
 
Mode GetMode () const noexcept
 
void SetMode (Mode mode) noexcept
 Set memory policy mode.
 
Nodemask const & GetNodemask () const noexcept
 

Static Public Member Functions

static MemPolicy MakeBindNode (int node)
 Creates a strict policy (using MPOL_BIND) to allocate all memory to the specified node.
 
static MemPolicy MakeFromNodeString (Mode mode, char const *nodestring)
 Create MemPolicy from mode and nodestring while considering currently allowed nodes.
 
static MemPolicy MakeFromNodeStringAll (Mode mode, char const *nodestring)
 Create MemPolicy from mode and nodestring considering all nodes, whether they are allowed or not.
 
static MemPolicy MakeFromActive ()
 Make from active default policy of calling thread.
 
static MemPolicy MakeFromAddress (void *address)
 Make from policy at address.
 

Related Symbols

(Note that these are not member symbols.)

enum class  MemPolicyFlag : unsigned
 Flag that modify the behaviour of applying a memory policy to a range of memory.
 
std::ostream & operator<< (std::ostream &os, MemPolicy::Mode const &mode)
 Formats mode and inserts it to os.
 
std::ostream & operator<< (std::ostream &os, MemPolicy const &mempolicy)
 Formats mempolicy and inserts it to os.
 
Allocate and free memory with specified memory policy

Allocate
numapp::Allocate() function is equivalent to performing the following:
  • Create new memory mapping with mmap (anonymous read/write) memory
  • Applying memory policy to allocated memory using provided policy and flag (1) using mbind.

(1) Overloads without flag use no modifiers (i.e. won't move pages).

Important
Memory is not pre-faulted by default. If memory is used by real-time threads consider using numapp::MemLock() after allocation to guarantee that pages as faulted in.
However if process locks memory when it is mapped (as controlled by numapp::MemLockAll() with numapp::LockAllFlag::Future) memory may have to be moved to apply the requested policy. It is in this case the flags argument has an important role to control if pages should be moved.
Free
numapp::Free() frees memory previously allocated with numapp::Allocate().
Parameters
[in]sizeNumber of bytes to allocate/free, will be rounded up to multiples of system page size.
[in]policyMemory policy to apply.
[in]flagsControls behaviour if memory have to be moved because it was already paged-in due to a numapp::MemLockAll policy.
[in]ptrPage-aligned pointer to memory previously allocated with numapp::Allocate().
[out]ecError code for non-throwing overloads. If there is an out of memory situation the error code std::errc::not_enough_memory is used.
Exceptions
std::system_erroron failure (only applicable to throwing-overloads without std::error_code return value).
Returns
numapp::Allocate() returns pointer to memory block that is at least size big or nullptr on failure.

Example allocating with bind policy and then lock and pre-fault the newly allocated memory:

void* BindAlloc(std::size_t size, int node, std::error_code& ec) {
using namespace numapp;
void* ptr = Allocate(size, policy, MemPolicyFlag::Strict, ec);
if (ec) {
return nullptr;
}
ec = MemLock(ptr, size, LockFlag::PreFault);
if (ec) {
return nullptr;
}
return ptr;
}
MemPolicy(Mode mode, Nodemask &&node_mask) noexcept
Create memory policy.
static MemPolicy MakeBindNode(int node)
Creates a strict policy (using MPOL_BIND) to allocate all memory to the specified node.
std::error_code MemLock(void const *addr, std::size_t len, LockFlag flag) noexcept
Lock memory pages in the specified address range.
Definition memory.cpp:58
void * Allocate(std::size_t size, MemPolicy const &policy, std::error_code &ec) noexcept
See group for details.
Definition memory.cpp:87
@ PreFault
Locks pages whether they are resident or not.
Definition memory.hpp:126
Contains memory function declarations.
Contains declarations for numapp::MemPolicy.
Related man-page(s):
void * Allocate (std::size_t size, MemPolicy const &policy, std::error_code &ec) noexcept
 See group for details.
 
void * Allocate (std::size_t size, MemPolicy const &policy, MemPolicyFlag flags, std::error_code &ec) noexcept
 See group for details.
 
void * Allocate (std::size_t size, MemPolicy const &policy)
 See group for details.
 
void * Allocate (std::size_t size, MemPolicy const &policy, MemPolicyFlag flags)
 See group for details.
 
void Free (void *ptr, std::size_t size, std::error_code &ec) noexcept
 See group for details.
 
void Free (void *ptr, std::size_t size)
 See group for details.
 
Allocate and free huge pages

Allocation is similar to Allocate and free but with the additional argument specifying the (huge) page size. Like non-huge allocations the pages are not pre-faulted by the functions so to avoid page fault failurs it is recommended to do that before use.

void Example() {
// Allocate 16MiB from NUMA node 1 in 2MiB pages.
auto const size = 16 * 1024 * 1024;
auto const page_size = numapp::HugePagePreset::Huge2M;
// 1) AllocateHuge will allocate size, rounding up to nearest page_size
// multiple
void* ptr = numapp::AllocateHuge(size,
page_size,
numapp::MemPolicyFlag::Strict);
// 2) It is particularly important to pre-fault huge-pages as the likelihood
// for failure is higher. If page-fault would fail when memory is accessed
// the result is a segmentation fault.
if (auto ec = numapp::MemLock(ptr, size, numapp::LockFlag::PreFault); ec) {
// Page-fault failed; this would have caused a segmentation fault if not
// for `numapp::MemLock()`.
throw std::system_error(ec, "Page fault failed");
}
// 3) FreeHuge will free memory, rounding up to nearest page_size multiple
// as required by mmap.
numapp::FreeHuge(ptr, size, page_size);
}
void FreeHuge(void *ptr, std::size_t size, HugePageSize page_size, std::error_code &ec) noexcept
Free huge pages previously allocated with AllocateHuge.
Definition memory.cpp:205
void * AllocateHuge(std::size_t size, HugePageSize page_size, MemPolicy const &policy, MemPolicyFlag flags, std::error_code &ec) noexcept
Non-throwing version of AllocateHuge()
Definition memory.cpp:165
@ Huge2M
2 MiB page size.
Definition memory.hpp:505
Parameters
Parameters
[in]sizeNumber of bytes to allocate/free, will be rounded up to multiples of page_size.
[in]page_sizePage size.
[in]policyMemory policy to apply.
[in]flagsControls behaviour if memory have to be moved because it was already paged-in due to a numapp::MemLockAll policy.
[in]ptrPage-aligned pointer to memory previously allocated with numapp::AllocateHuge().
[out]ecError code for non-throwing overloads. If there is an out of memory situation the error code std::errc::not_enough_memory is used.
Exceptions
std::system_erroron failure (only applicable to throwing-overloads without std::error_code return value).
Returns
numapp::AllocateHuge() returns pointer to memory block that is at least size big or nullptr on failure.
Related man-page(s):
void * AllocateHuge (std::size_t size, HugePageSize page_size, MemPolicy const &policy, MemPolicyFlag flags, std::error_code &ec) noexcept
 Non-throwing version of AllocateHuge()
 
void * AllocateHuge (std::size_t size, HugePageSize page_size, MemPolicy const &policy, MemPolicyFlag flags)
 Throwing version of AllocateHuge()
 
Apply Memory Policy to Current Thread

Applies default memory policy to calling thread or to thread stack memory.

std::error_code Apply (MemPolicy const &policy) noexcept
 Applies the default memory policy to the calling thread.
 
Apply Memory Policy to Memory Range
std::error_code Apply (void *address, std::size_t length, MemPolicy const &policy, MemPolicyFlag flags) noexcept
 Applies memory policy to the memory pages that spans the range [address, adress + length].
 

Detailed Description

Class representing a memory policy that can be modified and used to apply to the current thread or a memory range.

Uses numa APIs set_mempolicy and get_mempolicy.

To read the current memory policy use MemPolicy::MakeFromActive. To apply a policy use thisThread::Apply(MemPolicy const&).

For CPU policy see numapp::CpuAffinity.

Attention
The memory policy is used for new physical page allocations. One way this happens is by writing to unpaged memory which triggers a page-fault that then is handled according to the policy. This means that it's possible that memory returned by an allocator like malloc/std::allocator/new after a sucessfull call to MemPolicy::Apply does not in fact allocate a new physical page but may reuse recently freed memory or otherwise unused, but physically allocated memory.
Bottom line is that MemPolicy does not apply directly to virtual memory allocators but on the kernel level page allocation.
Related man-page(s):

Definition at line 174 of file mempolicy.hpp.

Member Enumeration Documentation

◆ Mode

enum class numapp::MemPolicy::Mode : int
strong

Memory allocation modes.

Enumerator
Default 

The Default mode specifies that any nondefault process memory policy be removed, so that the memory policy "falls back" to the system default policy.

The system default policy is "local allocation"– i.e., allocate memory on the node of the CPU that triggered the allocation. nodemask must be specified as NULL. If the "local node" contains no free memory, the system will attempt to allocate memory from a "near by" node.

Corresponds to native mode MPOL_DEFAULT.

Bind 

The Bind mode defines a strict policy that restricts memory allocation to the nodes specified in nodemask.

If nodemask specifies more than one node, page allocations will come from the node with the lowest numeric node ID first, until that node contains no free memory. Allocations will then come from the node with the next highest node ID specified in nodemask and so forth, until none of the specified nodes contain free memory. Pages will not be allocated from any node not specified in the nodemask.

Corresponds to native mode MPOL_BIND.

Interleave 

Interleave interleaves page allocations across the nodes specified in nodemask in numeric node ID order.

This optimizes for bandwidth instead of latency by spreading out pages and memory accesses to those pages across multiple nodes. However, accesses to a single page will still be limited to the memory bandwidth of a single node.

Corresponds to native mode MPOL_INTERLEAVE.

Preferred 

Preferred sets the preferred node for allocation.

The kernel will try to allocate pages from this node first and fall back to "near by" nodes if the preferred node is low on free memory. If nodemask specifies more than one node ID, the first node in the mask will be selected as the preferred node. If the nodemask and maxnode arguments specify the empty set, then the policy specifies "local allocation" (like the system default policy discussed above).

Corresponds to native mode MPOL_PREFERRED.

Definition at line 179 of file mempolicy.hpp.

Constructor & Destructor Documentation

◆ MemPolicy()

numapp::MemPolicy::MemPolicy ( Mode mode,
Nodemask && node_mask )
inlineexplicitnoexcept

Create memory policy.

Parameters
modePolicy mode
node_mask

Definition at line 229 of file mempolicy.hpp.

Member Function Documentation

◆ GetMode()

Mode numapp::MemPolicy::GetMode ( ) const
inlinenodiscardnoexcept
Returns
policy mode.

Definition at line 326 of file mempolicy.hpp.

◆ GetNodemask()

Nodemask const & numapp::MemPolicy::GetNodemask ( ) const
inlinenoexcept
Returns
Node mask.

Definition at line 342 of file mempolicy.hpp.

◆ MakeBindNode()

static MemPolicy numapp::MemPolicy::MakeBindNode ( int node)
staticnodiscard

Creates a strict policy (using MPOL_BIND) to allocate all memory to the specified node.

Parameters
nodeNuma node.
Exceptions
std::system_errorif it fails.

◆ MakeFromActive()

static MemPolicy numapp::MemPolicy::MakeFromActive ( )
staticnodiscard

Make from active default policy of calling thread.

Exceptions
std::system_errorif it fails.

◆ MakeFromAddress()

static MemPolicy numapp::MemPolicy::MakeFromAddress ( void * address)
staticnodiscard

Make from policy at address.

Parameters
addressmemory address to make policy from.
Exceptions
std::system_errorif it fails.

◆ MakeFromNodeString()

static MemPolicy numapp::MemPolicy::MakeFromNodeString ( Mode mode,
char const * nodestring )
inlinestaticnodiscard

Create MemPolicy from mode and nodestring while considering currently allowed nodes.

Nodestring use patterns such as:

  • 1-5,7,10
  • !4-5
  • +0-3
  • all
Related man-page(s):
Parameters
modeMemory policy mode such as MPOL_BIND
nodestringNodes to include such as 1-5,7,10 or all.
Exceptions
std::system_erroron failure. This can also happen if the nodestring references a disallowed node. Use MakeFromNodeStringAll to ignore this.
See also
MakeFromNodeStringAll

Definition at line 269 of file mempolicy.hpp.

◆ MakeFromNodeStringAll()

static MemPolicy numapp::MemPolicy::MakeFromNodeStringAll ( Mode mode,
char const * nodestring )
inlinestaticnodiscard

Create MemPolicy from mode and nodestring considering all nodes, whether they are allowed or not.

Nodestring use patterns such as:

  • 1-5,7,10
  • !4-5
  • +0-3
  • all
Related man-page(s):
Parameters
modeMemory policy mode such as MPOL_BIND
nodestringNodes to include such as 1-5,7,10 or all.
Exceptions
std::system_erroron failure. This can also happen if the nodestring references a disallowed node. Use MakeFromNodeStringAll to ignore this.
See also
MakeFromNodeString

Definition at line 294 of file mempolicy.hpp.

◆ operator==()

bool numapp::MemPolicy::operator== ( MemPolicy const & rhs) const
inlinenodiscardnoexcept
Returns
true if this memory policy mode and nodes equals rhs.

Definition at line 316 of file mempolicy.hpp.

◆ SetMode()

void numapp::MemPolicy::SetMode ( Mode mode)
inlinenoexcept

Set memory policy mode.

Parameters
modepolicy mode.

Definition at line 335 of file mempolicy.hpp.

Friends And Related Symbol Documentation

◆ Apply()

std::error_code Apply ( void * address,
std::size_t length,
MemPolicy const & policy,
MemPolicyFlag flags )
related

Applies memory policy to the memory pages that spans the range [address, adress + length].

Note
The memory policy is by default only applied to new physical page allocations. This can be modified using MemPolicyFlag::Move and MemPolicyFlag::MoveAll.

Read related man-page of mbind() to understand the various behaviours if memory is mapped or shared.

Parameters
addressstart of address range.
lengthlength of range.
policyPolicy to apply.
flagscombination of MemPolicyFlag values that modify the behaviour.
Returns
0 if successful.
non-zero if it failed.
Related man-page(s):

◆ operator<<() [1/2]

std::ostream & operator<< ( std::ostream & os,
MemPolicy const & mempolicy )
related

Formats mempolicy and inserts it to os.

Parameters
osoutput stream to insert into.
mempolicyMemory policy to format.
Returns
os

◆ operator<<() [2/2]

std::ostream & operator<< ( std::ostream & os,
MemPolicy::Mode const & mode )
related

Formats mode and inserts it to os.

Parameters
osoutput stream to insert into.
modeMemory policy mode to format.
Returns
os

The documentation for this class was generated from the following files: