blob: 0a59c937a1b778a5bfaa9d2785e93f8a713ea751 [file] [log] [blame]
#include "caffe2/core/numa.h"
C10_DEFINE_bool(caffe2_cpu_numa_enabled, false, "Use NUMA whenever possible.");
#if defined(__linux__) && !defined(CAFFE2_DISABLE_NUMA) && CAFFE2_MOBILE == 0
#include <numa.h>
#include <numaif.h>
#define CAFFE2_NUMA_ENABLED
#endif
namespace caffe2 {
#ifdef CAFFE2_NUMA_ENABLED
bool IsNUMAEnabled() {
return FLAGS_caffe2_cpu_numa_enabled && numa_available() >= 0;
}
void NUMABind(int numa_node_id) {
if (numa_node_id < 0) {
return;
}
if (!IsNUMAEnabled()) {
VLOG(1) << "NUMA is not enabled";
return;
}
CAFFE_ENFORCE(
numa_node_id <= numa_max_node(),
"NUMA node id " + caffe2::to_string(numa_node_id) + " is unavailable");
auto bm = numa_allocate_nodemask();
numa_bitmask_clearall(bm);
numa_bitmask_setbit(bm, numa_node_id);
numa_bind(bm);
numa_bitmask_free(bm);
}
int GetNUMANode(const void* ptr) {
if (!IsNUMAEnabled()) {
VLOG(1) << "NUMA is not enabled";
return -1;
}
CAFFE_ENFORCE(ptr);
int numa_node = -1;
CAFFE_ENFORCE(
get_mempolicy(
&numa_node, NULL, 0, (void*)ptr, MPOL_F_NODE | MPOL_F_ADDR) == 0,
"Unable to get memory policy");
return numa_node;
}
int GetNumNUMANodes() {
if (!IsNUMAEnabled()) {
VLOG(1) << "NUMA is not enabled";
return -1;
}
return numa_num_configured_nodes();
}
void NUMAMove(void* ptr, size_t size, int numa_node_id) {
if (numa_node_id < 0) {
return;
}
if (!IsNUMAEnabled()) {
VLOG(1) << "NUMA is not enabled";
return;
}
CAFFE_ENFORCE(ptr);
size_t page_start_ptr = (((size_t)ptr) & ~(getpagesize() - 1));
size_t offset = ((size_t)ptr) - page_start_ptr;
// Avoid extra dynamic allocation and NUMA api calls
CAFFE_ENFORCE(numa_node_id >= 0 && (unsigned)numa_node_id < sizeof(unsigned long) * 8);
unsigned long mask = 1UL << numa_node_id;
CAFFE_ENFORCE(
mbind(
(void*)page_start_ptr,
size + offset,
MPOL_BIND,
&mask,
sizeof(mask) * 8,
MPOL_MF_MOVE | MPOL_MF_STRICT) == 0,
"Could not move memory to a NUMA node");
}
int GetCurrentNUMANode() {
if (!IsNUMAEnabled()) {
VLOG(1) << "NUMA is not enabled";
return -1;
}
return numa_node_of_cpu(sched_getcpu());
}
#else // CAFFE2_NUMA_ENABLED
bool IsNUMAEnabled() {
return false;
}
void NUMABind(int numa_node_id) {
if (numa_node_id >= 0) {
VLOG(1) << "NUMA is not enabled";
}
}
int GetNUMANode(const void* ptr) {
VLOG(1) << "NUMA is not enabled";
return -1;
}
int GetNumNUMANodes() {
VLOG(1) << "NUMA is not enabled";
return -1;
}
void NUMAMove(void* ptr, size_t size, int numa_node_id) {
if (numa_node_id >= 0) {
VLOG(1) << "NUMA is not enabled";
}
}
int GetCurrentNUMANode() {
VLOG(1) << "NUMA is not enabled";
return -1;
}
#endif // CAFFE2_NUMA_ENABLED
} // namespace caffe2