Caffe2 - C++ API
A deep learning, cross platform ML framework
numa.cc
1 #include "caffe2/core/numa.h"
2 
3 CAFFE2_DEFINE_bool(
4  caffe2_cpu_numa_enabled,
5  false,
6  "Use NUMA whenever possible.");
7 
8 #if defined(__linux__) && !defined(CAFFE2_DISABLE_NUMA) && CAFFE2_MOBILE == 0
9 #include <numa.h>
10 #include <numaif.h>
11 #define CAFFE2_NUMA_ENABLED
12 #endif
13 
14 namespace caffe2 {
15 
16 #ifdef CAFFE2_NUMA_ENABLED
17 bool IsNUMAEnabled() {
18  return FLAGS_caffe2_cpu_numa_enabled && numa_available() >= 0;
19 }
20 
21 void NUMABind(int numa_node_id) {
22  if (numa_node_id < 0) {
23  return;
24  }
25  if (!IsNUMAEnabled()) {
26  VLOG(1) << "NUMA is not enabled";
27  return;
28  }
29 
30  CAFFE_ENFORCE(
31  numa_node_id <= numa_max_node(),
32  "NUMA node id " + caffe2::to_string(numa_node_id) + " is unavailable");
33 
34  auto bm = numa_allocate_nodemask();
35  numa_bitmask_clearall(bm);
36  numa_bitmask_setbit(bm, numa_node_id);
37  numa_bind(bm);
38  numa_bitmask_free(bm);
39 }
40 
41 int GetNUMANode(const void* ptr) {
42  if (!IsNUMAEnabled()) {
43  VLOG(1) << "NUMA is not enabled";
44  return -1;
45  }
46  CAFFE_ENFORCE(ptr);
47 
48  int numa_node = -1;
49  CAFFE_ENFORCE(
50  get_mempolicy(
51  &numa_node, NULL, 0, (void*)ptr, MPOL_F_NODE | MPOL_F_ADDR) == 0,
52  "Unable to get memory policy");
53  return numa_node;
54 }
55 
56 int GetNumNUMANodes() {
57  if (!IsNUMAEnabled()) {
58  VLOG(1) << "NUMA is not enabled";
59  return -1;
60  }
61 
62  return numa_num_configured_nodes();
63 }
64 
65 void NUMAMove(void* ptr, size_t size, int numa_node_id) {
66  if (numa_node_id < 0) {
67  return;
68  }
69  if (!IsNUMAEnabled()) {
70  VLOG(1) << "NUMA is not enabled";
71  return;
72  }
73  CAFFE_ENFORCE(ptr);
74 
75  size_t page_start_ptr = (((size_t)ptr) & ~(getpagesize() - 1));
76  size_t offset = ((size_t)ptr) - page_start_ptr;
77  // Avoid extra dynamic allocation and NUMA api calls
78  CAFFE_ENFORCE(numa_node_id >= 0 && numa_node_id < sizeof(unsigned long) * 8);
79  unsigned long mask = 1UL << numa_node_id;
80  CAFFE_ENFORCE(
81  mbind(
82  (void*)page_start_ptr,
83  size + offset,
84  MPOL_BIND,
85  &mask,
86  sizeof(mask) * 8,
87  MPOL_MF_MOVE | MPOL_MF_STRICT) == 0,
88  "Could not move memory to a NUMA node");
89 }
90 
91 int GetCurrentNUMANode() {
92  if (!IsNUMAEnabled()) {
93  VLOG(1) << "NUMA is not enabled";
94  return -1;
95  }
96 
97  return numa_node_of_cpu(sched_getcpu());
98 }
99 
100 #else // CAFFE2_NUMA_ENABLED
101 
102 bool IsNUMAEnabled() {
103  return false;
104 }
105 
106 void NUMABind(int numa_node_id) {
107  if (numa_node_id >= 0) {
108  VLOG(1) << "NUMA is not enabled";
109  }
110 }
111 
112 int GetNUMANode(const void* ptr) {
113  VLOG(1) << "NUMA is not enabled";
114  return -1;
115 }
116 
117 int GetNumNUMANodes() {
118  VLOG(1) << "NUMA is not enabled";
119  return -1;
120 }
121 
122 void NUMAMove(void* ptr, size_t size, int numa_node_id) {
123  if (numa_node_id >= 0) {
124  VLOG(1) << "NUMA is not enabled";
125  }
126 }
127 
128 int GetCurrentNUMANode() {
129  VLOG(1) << "NUMA is not enabled";
130  return -1;
131 }
132 
133 #endif // CAFFE2_NUMA_ENABLED
134 
135 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...