NeoPZ
tpzpagemigrationmanager.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (C) 2014 by Edson Borin *
3  * edson@ic.unicamp.br *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ******************************************************************************/
20 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include "arglib.h"
27 
28 #ifdef USING_LIBNUMA
29 
32 clarg::argBool mig_mp("-mig_mp", "Use move_pages when migrating pages.");
33 clarg::argBool mig_mbind("-mig_mbind", "Use mbind when migrating pages.");
34 #endif
35 
36 #ifdef USING_HWLOC
37 
40 clarg::argBool mig_hwloc("-mig_hwloc", "Use hwloc when migrating pages.");
41 #endif
42 
47 #ifdef USING_HWLOC
48  hwloc_topology_init(&hw_topo);
49  hwloc_topology_load(hw_topo);
50 
51  hwloc_obj_t obj;
52  HwCacheSize = 0;
53  for (obj = hwloc_get_obj_by_type(hw_topo, HWLOC_OBJ_PU, 0); obj; obj = obj->parent)
54  if (obj->type == HWLOC_OBJ_CACHE)
55  HwCacheSize += obj->attr->cache.size;
56 #endif
57 }
58 
63 #ifdef USING_HWLOC
64  hwloc_topology_destroy(hw_topo);
65 #endif
66 }
67 
68 #if defined (USING_HWLOC) || defined (USING_LIBNUMA)
69 
75 void TPZPageMigrationManager::MigrateToLocal(char* start, uint64_t size_in_bytes) {
76 #ifdef USING_LIBNUMA
77  if (mig_mp.was_set()) {
78  MigrateToLocalMovePages(start, size_in_bytes);
79  return;
80  }
81  else if (mig_mbind.was_set()) {
82  MigrateToLocalMbind(start, size_in_bytes);
83  return;
84  }
85 #endif
86 
87 #ifdef USING_HWLOC
88  if (mig_hwloc.was_set()) {
89  MigrateToLocalHwloc(start, size_in_bytes);
90  }
91 #endif
92 }
93 #endif
94 
95 #ifdef USING_LIBNUMA
96 
97 const int64_t PAGE_EXP = 12;
98 const int64_t PAGE_SZ = (1<<12);
99 const int64_t PAGE_MSK = ((1<<PAGE_EXP)-1);
100 
106 void TPZPageMigrationManager::MigrateToLocalMovePages(char* start, uint64_t size_in_bytes) {
107  int ret;
108  unsigned cpu, node;
109  if ( (ret=sched_getcpu()) < 0) {
110  printf("sched_getcpu(...) returned %d\n", ret);
111  return;
112  }
113  else {
114  cpu = ret;
115  node = cpu >> 3;
116  }
117  uint64_t nodemask = 1 << node;
118  uint64_t maxnode = 9;
119  int64_t page_start = (int64_t) start;
120  page_start = page_start & ~PAGE_MSK;
121  int64_t last_page = (int64_t) start + (int64_t) size_in_bytes;
122  last_page = last_page & ~PAGE_MSK;
123  int64_t count = (last_page - page_start + PAGE_SZ) >> PAGE_EXP;
124  void** pages = (void**) malloc(count*sizeof(void*));
125  int* nodes = (int*) malloc(count*sizeof(int));
126  int* status = (int*) malloc(count*sizeof(int));
127  for (int i=0; i<count; i++) {
128  pages[i] = (void*) (page_start + PAGE_SZ*i);
129  nodes[i] = node;
130  status[i] = 0;
131  }
132  if ( (ret = move_pages(0 /*pid*/, count , pages, nodes, status, MPOL_MF_MOVE)) != 0) {
133  int err = errno;
134  fprintf(stderr, "move_pages(0, npages(%ld), pages, nodes (%u), status, MPOL_MF_MOVE) = %d (cpu=%d, node=%d)\n",
135  count, node, ret, cpu, node);
136  fprintf(stderr, "errno (%d) = %s\n", err, strerror(err));
137  }
138 
139 }
140 
146 void TPZPageMigrationManager::MigrateToLocalMbind(char* start, uint64_t size_in_bytes) {
147  int ret;
148  unsigned cpu, node;
149  if ( (ret=sched_getcpu()) < 0) {
150  printf("sched_getcpu(...) returned %d\n", ret);
151  return;
152  }
153  else {
154  cpu = ret;
155  node = cpu >> 3;
156  }
157  uint64_t nodemask = 1 << node;
158  //uint64_t maxnode = 7;
159  //uint64_t nodemask = 1;
160  uint64_t maxnode = 9;
161  int64_t page_start = (int64_t) start;
162  page_start = page_start & ~PAGE_MSK;
163  int64_t last_page = (int64_t) start + (int64_t) size_in_bytes;
164  last_page = last_page & ~PAGE_MSK;
165  int64_t nbytes = last_page - page_start + PAGE_SZ;
166 #ifndef MPOL_F_STATIC_NODES
167 #define MPOL_F_STATIC_NODES (1 << 15)
168 #endif
169  if ( (ret = mbind((void*) page_start, nbytes, MPOL_BIND , &nodemask, maxnode, /* flags */ MPOL_MF_MOVE) ) != 0 ) {
170  // Error.
171  int err = errno;
172  fprintf(stderr,"ERROR: mbind(start=%ld, sz=%ld, MPOL_BIND, nodemask = %08ld (node = %u), maxnode = %lu, MPOL_MF_MOVE) = %d\n",
173  page_start, nbytes, nodemask, node, maxnode, ret);
174  fprintf(stderr, "errno (%d) = %s\n", err, strerror(err));
175  return;
176  }
177  else
178  {
179 #ifdef PZDEBUG
180  fprintf(stderr,"mbind(start=%ld, sz=%ld, MPOL_BIND, nodemask = %08ld (node = %d), maxnode = %lu, MPOL_MF_MOVE) = %d\n",
181  page_start, nbytes, nodemask, node, maxnode, ret);
182 #endif
183  }
184 }
185 #endif
186 
187 #ifdef USING_HWLOC
188 
194 void TPZPageMigrationManager::MigrateToLocalHwloc(char* start, uint64_t size_in_bytes) {
195  int ret;
196  // hwloc_bitmap_t set = hwloc_bitmap_alloc();
197  // if ( (ret=hwloc_get_cpubind(hw_topo, set, HWLOC_CPUBIND_THREAD)) != 0) {
198  // fprintf(stderr,"ERROR: hwloc_get_cpubind(...) returned %d\n", ret);
199  // }
200  hwloc_cpuset_t last = hwloc_bitmap_alloc();
201  if ( (ret=hwloc_get_last_cpu_location(hw_topo, last, HWLOC_CPUBIND_THREAD)) != 0) {
202  fprintf(stderr,"ERROR: hwloc_get_last_cpu_location(...) returned %d\n", ret);
203  }
204  if (hwloc_bitmap_iszero(last)) {
205  fprintf(stderr,"ERROR: hwloc_get_last_cpu_location returned a zeroed bit vector.\n");
206  }
207  //hwloc_bitmap_singlify(set);
208  int64_t page_start = (int64_t) start;
209  int64_t last_page = (int64_t) start + (int64_t) size_in_bytes;
210  page_start = page_start & ~PAGE_MSK;
211  last_page = last_page & ~PAGE_MSK;
212  int64_t nbytes = last_page - page_start + PAGE_SZ;
213  unsigned cpu, node;
214  if ( (ret=sched_getcpu()) < 0) {
215  printf("getcpu(...) returned %d\n",ret);
216  }
217  else {
218  cpu = ret;
219  node = -1;
220  }
221  char buffer[256];
222  hwloc_bitmap_snprintf(buffer,256,last);
223 #ifdef PZDEBUG
224  printf("migrate: start = 0x%ld, page_start = 0x%ld, #bytes = %ld (nbytes = %ld), last = %s, getcpu(cpu=%d,node=%d)\n",
225  (int64_t) start, (int64_t) page_start, (int64_t) size_in_bytes, nbytes, buffer,cpu,node);
226 #endif
227  if ( (ret = hwloc_set_area_membind(hw_topo, (const void*) page_start, nbytes,
228  (hwloc_const_cpuset_t)last, HWLOC_MEMBIND_BIND,
229  HWLOC_MEMBIND_MIGRATE )) != 0 ) {
230  int err = errno;
231  fprintf(stderr, "hwloc_set_area_membind(hw_topo, page_start=0x%ld, sz=%ld, set, HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_MIGRAGE) = %d\n",
232  page_start, nbytes, ret);
233  fprintf(stderr, "errno (%d) = %s\n", err, strerror(err));
234  }
235  hwloc_bitmap_free(last);
236 }
237 #endif
238 
240 
241 void migrate_to_local(char* start,uint64_t sz_in_bytes) {
242 #if defined (USING_HWLOC) || defined (USING_LIBNUMA)
243  MigrationManager.MigrateToLocal(start, sz_in_bytes);
244 #else
245  fprintf(stderr, "PZ compiled without page migration support. Compile with USING_HWLOC or USING_LIBNUMA.");
246 #endif
247 }
Contains declaration of the TPZPageMigrationManager class which implements methods to migrate data in...
~TPZPageMigrationManager()
Destroy hwloc topology when the lib is enabled.
void migrate_to_local(char *start, uint64_t sz_in_bytes)
TPZPageMigrationManager MigrationManager
TPZPageMigrationManager()
Initialize hwloc tolopology when the lib is enabled.
obj
Definition: test.py:225