Program Listing for File numa.cpp¶
↰ Return to documentation for file (umpire/util/numa.cpp
)
//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-20, Lawrence Livermore National Security, LLC and Umpire
// project contributors. See the COPYRIGHT file for details.
//
// SPDX-License-Identifier: (MIT)
//////////////////////////////////////////////////////////////////////////////
#include "umpire/util/numa.hpp"
#include "umpire/util/Macros.hpp"
#include <numa.h>
#include <numaif.h>
#include <unistd.h>
namespace umpire {
long get_page_size() {
static const long s_cpu_page_size = sysconf(_SC_PAGESIZE);
return s_cpu_page_size;
}
namespace numa {
int preferred_node()
{
if (numa_available() < 0) UMPIRE_ERROR("libnuma is unusable.");
return numa_preferred();
}
void move_to_node(void* ptr, std::size_t bytes, int node)
{
if (numa_available() < 0) UMPIRE_ERROR("libnuma is unusable.");
struct bitmask* mask = numa_bitmask_alloc(numa_max_node() + 1);
numa_bitmask_clearall(mask);
numa_bitmask_setbit(mask, node);
if (mbind(ptr, bytes, MPOL_BIND, mask->maskp, mask->size + 1, MPOL_MF_MOVE | MPOL_MF_STRICT) != 0) {
UMPIRE_ERROR("numa::move_to_node error: mbind( ptr = " << ptr <<
", bytes = " << bytes <<
", node = " << node << " ) failed");
}
numa_bitmask_free(mask);
}
int get_location(void* ptr)
{
int numa_node = -1;
if (get_mempolicy(&numa_node, NULL, 0, ptr, MPOL_F_NODE | MPOL_F_ADDR) != 0) {
UMPIRE_ERROR("numa::get_location error: get_mempolicy( ptr = " << ptr << ") failed");
}
return numa_node;
}
std::vector<int> get_host_nodes()
{
if (numa_available() < 0) UMPIRE_ERROR("libnuma is unusable.");
std::vector<int> host_nodes;
struct bitmask* cpus = numa_allocate_cpumask();
const int size = numa_all_nodes_ptr->size;
for (int i = 0; i < size; i++) {
if (numa_bitmask_isbitset(numa_all_nodes_ptr, i)) {
// Check if this has CPUs
if (numa_node_to_cpus(i, cpus) != 0) {
UMPIRE_ERROR("Error getting CPU list for NUMA node.");
}
const std::size_t ncpus = numa_bitmask_weight(cpus);
if (ncpus > 0) {
// This is a host node
host_nodes.push_back(i);
}
}
}
numa_free_cpumask(cpus);
return host_nodes;
}
std::vector<int> get_device_nodes()
{
if (numa_available() < 0) UMPIRE_ERROR("libnuma is unusable.");
std::vector<int> device_nodes;
struct bitmask* cpus = numa_allocate_cpumask();
const int size = numa_all_nodes_ptr->size;
for (int i = 0; i < size; i++) {
if (numa_bitmask_isbitset(numa_all_nodes_ptr, i)) {
// Check if this has CPUs
if (numa_node_to_cpus(i, cpus) != 0) {
UMPIRE_ERROR("Error getting CPU list for NUMA node.");
}
const std::size_t ncpus = numa_bitmask_weight(cpus);
if (ncpus == 0) {
// This is a device node
device_nodes.push_back(i);
}
}
}
numa_free_cpumask(cpus);
return device_nodes;
}
std::vector<int> get_allocatable_nodes()
{
if (numa_available() < 0) UMPIRE_ERROR("libnuma is unusable.");
struct bitmask* mask = numa_get_mems_allowed();
std::vector<int> nodes;
const int size = mask->size;
for (int i = 0; i < size; i++) {
if (numa_bitmask_isbitset(mask, i)) nodes.push_back(i);
}
numa_free_nodemask(mask);
return nodes;
}
} // end namespace numa
} // end namespace umpire