NUMA++ 0.11.0
Loading...
Searching...
No Matches
memory.cpp File Reference

Definition of memory functions from <numapp/memory.hpp> More...

#include <numapp/memory.hpp>
#include <bit>
#include <cassert>
#include <numa.h>
#include <type_traits>
#include <utility>
#include <x86intrin.h>
#include <numapp/mempolicy.hpp>

Go to the source code of this file.

Namespaces

namespace  numapp
 

Functions

auto numapp::EncodeMmapFlags (HugePageSize page_size) noexcept -> int
 Encodes page size into bit representation expected by mmap().
 
Hardware Queries

Query host system/hardware.

std::size_t numapp::GetPageSize () noexcept
 Fast query of system page size.
 
int numapp::GetNumNodes () noexcept
 Query number of configured NUMA nodes.
 
std::optional< int > numapp::GetNodeDistance (int node1, int node2) noexcept
 Get NUMA distance between two nodes.
 
std::optional< int > numapp::GetNodeOfCpu (int cpu) noexcept
 Get NUMA node of the given CPU.
 
Memory Locking

These functions provide the means to prevent memory from being paged to the swap area.

Note
Care should be taken when using these as resident memory consumption will increase as the risk of out-of-memory scenarios. In particular it should be noted that applications may allocate memory that is never resident in normal use. Forcing this memory to be faulted-in may lead to significant memory pressure. One way to avoid that is to use LockFlag::OnFault and LockAllFlag::OnFault which will lock resident memory only. For real-time applications this should not be used however as page faults should be avoided in those scenarios.
Permissions

Locking may require additional permissions if it exceeds resource limits (- getrlimit(2)). Permissions can be provided by CAP_IPC_LOCK (- capabilities(7)).

See also page section Memory Locking.

std::error_code numapp::MemLock (void const *addr, std::size_t len, LockFlag flag) noexcept
 Lock memory pages in the specified address range.
 
std::error_code numapp::MemUnlock (void const *addr, std::size_t len) noexcept
 Unlock memory pages in the specified address range.
 
std::error_code numapp::MemLockAll (LockAllFlag flags) noexcept
 Lock all memory pages as specified by provided flags.
 
std::error_code numapp::MemUnlockAll () noexcept
 Unlock all locked memory in this process.
 
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;
}
Class representing a memory policy that can be modified and used to apply to the current thread or a ...
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 * numapp::Allocate (std::size_t size, MemPolicy const &policy, std::error_code &ec) noexcept
 See group for details.
 
void * numapp::Allocate (std::size_t size, MemPolicy const &policy, MemPolicyFlag flags, std::error_code &ec) noexcept
 See group for details.
 
void * numapp::Allocate (std::size_t size, MemPolicy const &policy)
 See group for details.
 
void * numapp::Allocate (std::size_t size, MemPolicy const &policy, MemPolicyFlag flags)
 See group for details.
 
void numapp::Free (void *ptr, std::size_t size, std::error_code &ec) noexcept
 See group for details.
 
void numapp::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 * numapp::AllocateHuge (std::size_t size, HugePageSize page_size, MemPolicy const &policy, MemPolicyFlag flags, std::error_code &ec) noexcept
 Non-throwing version of AllocateHuge()
 
void * numapp::AllocateHuge (std::size_t size, HugePageSize page_size, MemPolicy const &policy, MemPolicyFlag flags)
 Throwing version of AllocateHuge()
 
void numapp::FreeHuge (void *ptr, std::size_t size, HugePageSize page_size, std::error_code &ec) noexcept
 Free huge pages previously allocated with AllocateHuge.
 
void numapp::FreeHuge (void *ptr, std::size_t size, HugePageSize page_size)
 Throwing version of FreeHuge().
 

Detailed Description

Definition of memory functions from <numapp/memory.hpp>

Definition in file memory.cpp.