41 - hands on lstopo

lstopo -i "node:2 sock:2 cache:1 cache:2 cache:2 core:1 pu:2" save.xml
lstopo -i save.xml



43 - hands on hwloc-calc

$ hwloc-calc -i save.xml socket:1
0x0000ff00

$ hwloc-calc -i save.xml socket:1.pu:2 node:1.core:0-1 ~node:1.pu:0
0x000e0400

$ hwloc-calc -i save.xml node:1 --number-of core     
8
$ hwloc-calc -i save.xml node:1 --intersect core
8,9,10,11,12,13,14,15

$ lstopo -i save.xml --restrict `hwloc-calc -i save.xml socket:0`

$ hwloc-calc os=eth0
0x0000000f

$ hwloc-calc all -I pu
0,1,2,3
$ hwloc-calc all -I pu -p
0,2,1,3



46 - hands on hwloc-bind

$ hwloc-calc all --intersect core --sep " "
0 1

$ for i in `hwloc-calc all --intersect core --sep " "` ; do hwloc-bind core:$i -- sleep 100 ; done

$ hwloc-ps
21927	L2Cache:0		sleep
21928	L2Cache:1		sleep

$ hwloc-bind --pid 21927 core:1
$ hwloc-ps                     
21927	L2Cache:1		sleep
21928	L2Cache:1		sleep

$ hwloc-bind --pid 21927 all      
$ hwloc-ps                  
21928	L2Cache:1		sleep

$ hwloc-bind --get-last-cpu-location --pid 21927
0x00000001



50 - Building programs with hwloc

#include <hwloc.h>
int main(int argc, char *argv[])
{
  hwloc_topology_t topo;
  int err;
  /* initialize a topology context */
  err = hwloc_topology_init(&topo);
  assert(!err);
  /* build the topology created and configured above */
  err = hwloc_topology_load(topo);

  printf("%u cores\n",
	 hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_CORE));

  /* terminate this topology context */
  hwloc_topology_destroy(topo);
  return 0;
}



54 - Hands on tree browsing

void print(hwloc_obj_t obj)
{
  unsigned i;
  hwloc_obj_t child;

  printf("obj type %s depth %u os_index %u\n", hwloc_obj_type_string(obj->type), obj->depth, obj->os_index);

  for(i=0; i<obj->arity; i++)
    print(obj->children[i]);

  child = obj->first_child;
  while (child) {
    print(child);
    child = child->next_sibling;
  }
}

print(hwloc_get_root_obj(topo));


int is_ancestor(hwloc_obj_t obj1, hwloc_obj_t obj2)
{
  while (obj1) {
    if (obj1 == obj2)
      return 1;
    obj1 = obj1->parent;
  }
  return 0;
}

hwloc_obj_t firstpu = hwloc_get_obj_by_type(topo, HWLOC_OBJ_PU, 0);
hwloc_obj_t root = hwloc_get_root_obj(topo);

is_ancestor(firstpu, root);



57 - Hands on level browsing

unsigned i;
for(i=0; i<hwloc_topology_get_depth(topo); i++) {
  hwloc_obj_t obj = hwloc_get_obj_by_depth(topo, i, 0);
  print(obj);
}

for(i=0; i<hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_PU); i++) {
  hwloc_obj_t obj = hwloc_get_obj_by_type(topo, HWLOC_OBJ_PU, i);
  print(obj);
}

unsigned depth = hwloc_topology_get_depth(topo) - 1;
hwloc_obj_t obj = NULL;
while ((obj = hwloc_get_next_obj_by_depth(topo, depth, obj)) != NULL)
  print(obj);



64 - Hands on bitmaps

unsigned nbpus;
hwloc_obj_t firstpu, lastpu;
hwloc_bitmap_t set;
char *string;
nbpus = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_PU);
firstpu = hwloc_get_obj_by_type(topo, HWLOC_OBJ_PU, 0);
lastpu = hwloc_get_obj_by_type(topo, HWLOC_OBJ_PU, nbpus-1);
set = hwloc_bitmap_dup(firstpu->cpuset);
hwloc_bitmap_or(set, set, lastpu->cpuset);
hwloc_bitmap_asprintf(&string, set);
printf("bitmap is %s\n", string);
free(string)
hwloc_bitmap_free(set);


char line[128]
while (fgets(line, sizeof(line), stdin)) {
  hwloc_bitmap_t set;
  hwloc_obj_t obj;
  set = hwloc_bitmap_alloc();
  hwloc_bitmap_sscanf(set, line);
  obj = NULL;
  while ((obj = hwloc_get_next_obj_inside_cpuset_by_type(topo, set, HWLOC_OBJ_CORE, obj)) != NULL) {
    print(obj);
  }
}



65 - Hands on binding

#include <hwloc.h>
#include <assert.h>

hwloc_topology_t topo;
unsigned nbcores;
hwloc_obj_t firstcore;
hwloc_obj_t lastcore;

static void *thread_func(void *arg)
{
  hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
  char *s;

  /* wait for the main thread to bind us */
  usleep(1000000);

  /* get the current thread binding */
  hwloc_get_cpubind(topo, cpuset, HWLOC_CPUBIND_THREAD);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("second thread bound on %s\n", s);
  free(s);
  /* get the current thread CPU location */
  hwloc_get_last_cpu_location(topo, cpuset, HWLOC_CPUBIND_THREAD);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("second thread running on %s\n", s);
  free(s);
  /* get the current process binding */
  hwloc_get_cpubind(topo, cpuset, HWLOC_CPUBIND_PROCESS);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("process bound on %s\n", s);
  free(s);
  /* get the current process CPU location */
  hwloc_get_last_cpu_location(topo, cpuset, HWLOC_CPUBIND_PROCESS);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("process running on %s\n", s);
  free(s);

  /* rebind the current thread on a single PU of the lastcore */
  printf("second thread rebinding itself\n");
  hwloc_bitmap_copy(cpuset, lastcore->cpuset);
  hwloc_bitmap_singlify(cpuset);
  hwloc_set_cpubind(topo, cpuset, HWLOC_CPUBIND_THREAD);

  /* get the current thread binding */
  hwloc_get_cpubind(topo, cpuset, HWLOC_CPUBIND_THREAD);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("second thread bound on %s\n", s);
  free(s);
  /* get the current thread CPU location */
  hwloc_get_last_cpu_location(topo, cpuset, HWLOC_CPUBIND_THREAD);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("second thread running on %s\n", s);
  free(s);
  /* get the current process binding */
  hwloc_get_cpubind(topo, cpuset, HWLOC_CPUBIND_PROCESS);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("process bound on %s\n", s);
  free(s);
  /* get the current process CPU location */
  hwloc_get_last_cpu_location(topo, cpuset, HWLOC_CPUBIND_PROCESS);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("process running on %s\n", s);
  free(s);

  hwloc_bitmap_free(cpuset);
  return NULL;
}

int main()
{
  hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
  pthread_t th;
  char *s;
  int err;

  hwloc_topology_init(&topo);
  hwloc_topology_load(topo);

  nbcores = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_CORE);
  firstcore = hwloc_get_obj_by_type(topo, HWLOC_OBJ_CORE, 0);
  lastcore = hwloc_get_obj_by_type(topo, HWLOC_OBJ_CORE, nbcores-1);

  /* bind the entire process to the last core */
  err = hwloc_set_cpubind(topo, lastcore->cpuset, HWLOC_CPUBIND_PROCESS);
  assert(!err);

  pthread_create(&th, NULL, thread_func, NULL);
  hwloc_set_thread_cpubind(topo, th, firstcore->cpuset, HWLOC_CPUBIND_THREAD);
  pthread_join(th, NULL);

  /* get the current thread binding */
  hwloc_get_cpubind(topo, cpuset, HWLOC_CPUBIND_THREAD);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("main thread bound on %s\n", s);
  free(s);
  /* get the current thread CPU location */
  hwloc_get_last_cpu_location(topo, cpuset, HWLOC_CPUBIND_THREAD);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("main thread running on %s\n", s);
  free(s);
  /* get the current process binding */
  hwloc_get_cpubind(topo, cpuset, HWLOC_CPUBIND_PROCESS);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("process bound on %s\n", s);
  free(s);
  /* get the current process CPU location */
  hwloc_get_last_cpu_location(topo, cpuset, HWLOC_CPUBIND_PROCESS);
  hwloc_bitmap_asprintf(&s, cpuset);
  printf("process running on %s\n", s);
  free(s);

  hwloc_bitmap_free(cpuset);

  hwloc_topology_destroy(topo);
  return 0;
}



76 - Hands on I/O objects

hwloc_obj_t obj = NULL;
while ((obj = hwloc_get_next_pcidev(topo, obj)) != NULL) {
  hwloc_obj_t ancestor = hwloc_get_non_io_ancestor_obj(topo, obj);
  char *cpuset;
  hwloc_bitmap_asprintf(&cpuset, ancestor->cpuset);
  printf("PCI %04x:%02x:%02x.%01x name %s locality %s\n",
	 obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func,
	 obj->name, cpuset);
  free(cpuset);
}

hwloc_obj_t obj = NULL;
while ((obj = hwloc_get_next_osdev(topo, obj)) != NULL) {
  hwloc_obj_t ancestor = hwloc_get_non_io_ancestor_obj(topo, obj);
  char *cpuset;
  hwloc_bitmap_asprintf(&cpuset, ancestor->cpuset);
  printf("OS device type %u name %s locality %s\n",
	 obj->attr->osdev.type,
	 obj->name, cpuset);
  free(cpuset);
}
