static void test(hwloc_const_bitmap_t cpuset, int flags) { hwloc_bitmap_t new_cpuset = hwloc_bitmap_alloc(); result_set("Bind this singlethreaded process", hwloc_set_cpubind(topology, cpuset, flags), support->cpubind->set_thisproc_cpubind || support->cpubind->set_thisthread_cpubind); result_get("Get this singlethreaded process", cpuset, new_cpuset, hwloc_get_cpubind(topology, new_cpuset, flags), support->cpubind->get_thisproc_cpubind || support->cpubind->get_thisthread_cpubind); result_set("Bind this thread", hwloc_set_cpubind(topology, cpuset, flags | HWLOC_CPUBIND_THREAD), support->cpubind->set_thisthread_cpubind); result_get("Get this thread", cpuset, new_cpuset, hwloc_get_cpubind(topology, new_cpuset, flags | HWLOC_CPUBIND_THREAD), support->cpubind->get_thisthread_cpubind); result_set("Bind this whole process", hwloc_set_cpubind(topology, cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->set_thisproc_cpubind); result_get("Get this whole process", cpuset, new_cpuset, hwloc_get_cpubind(topology, new_cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->get_thisproc_cpubind); #ifdef HWLOC_WIN_SYS result_set("Bind process", hwloc_set_proc_cpubind(topology, GetCurrentProcess(), cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->set_proc_cpubind); result_get("Get process", cpuset, new_cpuset, hwloc_get_proc_cpubind(topology, GetCurrentProcess(), new_cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->get_proc_cpubind); result_set("Bind thread", hwloc_set_thread_cpubind(topology, GetCurrentThread(), cpuset, flags | HWLOC_CPUBIND_THREAD), support->cpubind->set_thread_cpubind); result_get("Get thread", cpuset, new_cpuset, hwloc_get_thread_cpubind(topology, GetCurrentThread(), new_cpuset, flags | HWLOC_CPUBIND_THREAD), support->cpubind->get_thread_cpubind); #else /* !HWLOC_WIN_SYS */ result_set("Bind whole process", hwloc_set_proc_cpubind(topology, getpid(), cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->set_proc_cpubind); result_get("Get whole process", cpuset, new_cpuset, hwloc_get_proc_cpubind(topology, getpid(), new_cpuset, flags | HWLOC_CPUBIND_PROCESS), support->cpubind->get_proc_cpubind); result_set("Bind process", hwloc_set_proc_cpubind(topology, getpid(), cpuset, flags), support->cpubind->set_proc_cpubind); result_get("Get process", cpuset, new_cpuset, hwloc_get_proc_cpubind(topology, getpid(), new_cpuset, flags), support->cpubind->get_proc_cpubind); #ifdef hwloc_thread_t result_set("Bind thread", hwloc_set_thread_cpubind(topology, pthread_self(), cpuset, flags), support->cpubind->set_thread_cpubind); result_get("Get thread", cpuset, new_cpuset, hwloc_get_thread_cpubind(topology, pthread_self(), new_cpuset, flags), support->cpubind->get_thread_cpubind); #endif #endif /* !HWLOC_WIN_SYS */ printf("\n"); hwloc_bitmap_free(new_cpuset); }
/* * Get the core where the current process is running * param flag set of cores is possible * return the core */ int hw_get_proc_core(int flag) { int core; hwloc_cpuset_t set; set = hwloc_bitmap_alloc(); hwloc_get_proc_cpubind (topology,0,set,HWLOC_CPUBIND_PROCESS); core = hwloc_bitmap_first(set); hwloc_bitmap_free(set); //hwloc can't detect the thread core - use linux based syscall if (flag) core = sched_getcpu(); return core; }
/* * Get the first core of a node * return the core */ int hw_get_firstcore() { int core; hwloc_cpuset_t set; if (local_topo->nnodes != 0 ){ set = hwloc_bitmap_alloc(); hwloc_get_proc_cpubind (topology,0,set,HWLOC_CPUBIND_PROCESS); core = hwloc_bitmap_first(set); hwloc_bitmap_free(set); } else core = -1; return core; }
/* * Get the node where the current process is running * return the node of the core */ int hw_get_proc_node() { int node; hwloc_cpuset_t set; hwloc_nodeset_t nset; if (local_topo->nnodes != 0 ){ set = hwloc_bitmap_alloc(); nset = hwloc_bitmap_alloc(); hwloc_get_proc_cpubind (topology,0,set,HWLOC_CPUBIND_PROCESS); hwloc_cpuset_to_nodeset(topology,set,nset); node = hwloc_bitmap_first(nset); hwloc_bitmap_free(set); hwloc_bitmap_free(nset); } else node = -1; return node; }
static void add_process_objects(hwloc_topology_t topology) { #ifdef HAVE_DIRENT_H hwloc_obj_t root; hwloc_bitmap_t cpuset; #ifdef HWLOC_LINUX_SYS hwloc_bitmap_t task_cpuset; #endif /* HWLOC_LINUX_SYS */ DIR *dir; struct dirent *dirent; const struct hwloc_topology_support *support; root = hwloc_get_root_obj(topology); support = hwloc_topology_get_support(topology); if (!support->cpubind->get_proc_cpubind) return; dir = opendir("/proc"); if (!dir) return; cpuset = hwloc_bitmap_alloc(); #ifdef HWLOC_LINUX_SYS task_cpuset = hwloc_bitmap_alloc(); #endif /* HWLOC_LINUX_SYS */ while ((dirent = readdir(dir))) { long local_pid_number; hwloc_pid_t local_pid; char *end; char name[80]; int proc_cpubind; local_pid_number = strtol(dirent->d_name, &end, 10); if (*end) /* Not a number */ continue; snprintf(name, sizeof(name), "%ld", local_pid_number); local_pid = hwloc_pid_from_number(local_pid_number, 0); proc_cpubind = hwloc_get_proc_cpubind(topology, local_pid, cpuset, 0) != -1; #ifdef HWLOC_LINUX_SYS { char comm[16]; char *path; size_t pathlen = 6 + strlen(dirent->d_name) + 1 + 7 + 1; path = malloc(pathlen); { /* Get the process name */ char cmd[64]; int file; ssize_t n; snprintf(path, pathlen, "/proc/%s/cmdline", dirent->d_name); file = open(path, O_RDONLY); if (file < 0) { /* Ignore errors */ free(path); continue; } n = read(file, cmd, sizeof(cmd)); close(file); if (n <= 0) { /* Ignore kernel threads and errors */ free(path); continue; } snprintf(path, pathlen, "/proc/%s/comm", dirent->d_name); file = open(path, O_RDONLY); if (file >= 0) { n = read(file, comm, sizeof(comm) - 1); close(file); if (n > 0) { comm[n] = 0; if (n > 1 && comm[n-1] == '\n') comm[n-1] = 0; } else { snprintf(comm, sizeof(comm), "(unknown)"); } } else { /* Old kernel, have to look at old file */ char stats[32]; char *parenl = NULL, *parenr; snprintf(path, pathlen, "/proc/%s/stat", dirent->d_name); file = open(path, O_RDONLY); if (file < 0) { /* Ignore errors */ free(path); continue; } /* "pid (comm) ..." */ n = read(file, stats, sizeof(stats) - 1); close(file); if (n > 0) { stats[n] = 0; parenl = strchr(stats, '('); parenr = strchr(stats, ')'); if (!parenr) parenr = &stats[sizeof(stats)-1]; *parenr = 0; } if (!parenl) { snprintf(comm, sizeof(comm), "(unknown)"); } else { snprintf(comm, sizeof(comm), "%s", parenl+1); } } snprintf(name, sizeof(name), "%ld %s", local_pid_number, comm); } { /* Get threads */ DIR *task_dir; struct dirent *task_dirent; snprintf(path, pathlen, "/proc/%s/task", dirent->d_name); task_dir = opendir(path); if (task_dir) { while ((task_dirent = readdir(task_dir))) { long local_tid; char *task_end; const size_t tid_len = sizeof(local_tid)*3+1; size_t task_pathlen = 6 + strlen(dirent->d_name) + 1 + 4 + 1 + strlen(task_dirent->d_name) + 1 + 4 + 1; char *task_path; int comm_file; char task_comm[16] = ""; char task_name[sizeof(name) + 1 + tid_len + 1 + sizeof(task_comm) + 1]; ssize_t n; local_tid = strtol(task_dirent->d_name, &task_end, 10); if (*task_end) /* Not a number, or the main task */ continue; task_path = malloc(task_pathlen); snprintf(task_path, task_pathlen, "/proc/%s/task/%s/comm", dirent->d_name, task_dirent->d_name); comm_file = open(task_path, O_RDONLY); free(task_path); if (comm_file >= 0) { n = read(comm_file, task_comm, sizeof(task_comm) - 1); if (n < 0) n = 0; close(comm_file); task_comm[n] = 0; if (n > 1 && task_comm[n-1] == '\n') task_comm[n-1] = 0; if (!strcmp(comm, task_comm)) /* Same as process comm, do not show it again */ n = 0; } else { n = 0; } if (hwloc_linux_get_tid_cpubind(topology, local_tid, task_cpuset)) continue; if (proc_cpubind && hwloc_bitmap_isequal(task_cpuset, cpuset)) continue; if (n) { snprintf(task_name, sizeof(task_name), "%s %li %s", name, local_tid, task_comm); } else { snprintf(task_name, sizeof(task_name), "%s %li", name, local_tid); } insert_task(topology, task_cpuset, task_name); } closedir(task_dir); } } free(path); } #endif /* HWLOC_LINUX_SYS */ if (!proc_cpubind) continue; if (hwloc_bitmap_isincluded(root->cpuset, cpuset)) continue; insert_task(topology, cpuset, name); } hwloc_bitmap_free(cpuset); #ifdef HWLOC_LINUX_SYS hwloc_bitmap_free(task_cpuset); #endif /* HWLOC_LINUX_SYS */ closedir(dir); #endif /* HAVE_DIRENT_H */ }
int main(int argc, char *argv[]) { const struct hwloc_topology_support *support; hwloc_topology_t topology; hwloc_const_bitmap_t topocpuset; hwloc_bitmap_t cpuset; unsigned long flags = 0; DIR *dir; struct dirent *dirent; int show_all = 0; int show_threads = 0; int get_last_cpu_location = 0; char *callname; char *pidcmd = NULL; int err; int opt; callname = strrchr(argv[0], '/'); if (!callname) callname = argv[0]; else callname++; /* skip argv[0], handle options */ argc--; argv++; hwloc_utils_check_api_version(callname); while (argc >= 1) { opt = 0; if (!strcmp(argv[0], "-a")) show_all = 1; else if (!strcmp(argv[0], "-l") || !strcmp(argv[0], "--logical")) { logical = 1; } else if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--physical")) { logical = 0; } else if (!strcmp(argv[0], "-c") || !strcmp(argv[0], "--cpuset")) { show_cpuset = 1; } else if (!strcmp(argv[0], "-e") || !strncmp(argv[0], "--get-last-cpu-location", 10)) { get_last_cpu_location = 1; } else if (!strcmp(argv[0], "-t") || !strcmp(argv[0], "--threads")) { #ifdef HWLOC_LINUX_SYS show_threads = 1; #else fprintf (stderr, "Listing threads is currently only supported on Linux\n"); #endif } else if (!strcmp (argv[0], "--whole-system")) { flags |= HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM; } else if (!strcmp (argv[0], "--pid-cmd")) { if (argc < 2) { usage(callname, stdout); exit(EXIT_FAILURE); } pidcmd = argv[1]; opt = 1; } else { fprintf (stderr, "Unrecognized option: %s\n", argv[0]); usage (callname, stderr); exit(EXIT_FAILURE); } argc -= opt+1; argv += opt+1; } err = hwloc_topology_init(&topology); if (err) goto out; hwloc_topology_set_flags(topology, flags); err = hwloc_topology_load(topology); if (err) goto out_with_topology; support = hwloc_topology_get_support(topology); if (get_last_cpu_location) { if (!support->cpubind->get_proc_last_cpu_location) goto out_with_topology; } else { if (!support->cpubind->get_proc_cpubind) goto out_with_topology; } topocpuset = hwloc_topology_get_topology_cpuset(topology); dir = opendir("/proc"); if (!dir) goto out_with_topology; cpuset = hwloc_bitmap_alloc(); if (!cpuset) goto out_with_dir; while ((dirent = readdir(dir))) { long pid_number; hwloc_pid_t pid; char pidoutput[1024]; char *end; char name[64] = ""; /* management of threads */ unsigned boundthreads = 0, i; long *tids = NULL; /* NULL if process is not threaded */ hwloc_bitmap_t *tidcpusets = NULL; pid_number = strtol(dirent->d_name, &end, 10); if (*end) /* Not a number */ continue; pid = hwloc_pid_from_number(pid_number, 0); #ifdef HWLOC_LINUX_SYS { unsigned pathlen = 6 + strlen(dirent->d_name) + 1 + 7 + 1; char *path; int file; ssize_t n; path = malloc(pathlen); snprintf(path, pathlen, "/proc/%s/cmdline", dirent->d_name); file = open(path, O_RDONLY); free(path); if (file >= 0) { n = read(file, name, sizeof(name) - 1); close(file); if (n <= 0) /* Ignore kernel threads and errors */ continue; name[n] = 0; } } #endif /* HWLOC_LINUX_SYS */ if (show_threads) { #ifdef HWLOC_LINUX_SYS /* check if some threads must be displayed */ unsigned pathlen = 6 + strlen(dirent->d_name) + 1 + 4 + 1; char *path; DIR *taskdir; path = malloc(pathlen); snprintf(path, pathlen, "/proc/%s/task", dirent->d_name); taskdir = opendir(path); if (taskdir) { struct dirent *taskdirent; long tid; unsigned n = 0; /* count threads */ while ((taskdirent = readdir(taskdir))) { tid = strtol(taskdirent->d_name, &end, 10); if (*end) /* Not a number */ continue; n++; } if (n > 1) { /* if there's more than one thread, see if some are bound */ tids = malloc(n * sizeof(*tids)); tidcpusets = calloc(n+1, sizeof(*tidcpusets)); if (tids && tidcpusets) { /* reread the directory but gather info now */ rewinddir(taskdir); i = 0; while ((taskdirent = readdir(taskdir))) { tid = strtol(taskdirent->d_name, &end, 10); if (*end) /* Not a number */ continue; if (get_last_cpu_location) { if (hwloc_linux_get_tid_last_cpu_location(topology, tid, cpuset)) continue; } else { if (hwloc_linux_get_tid_cpubind(topology, tid, cpuset)) continue; } hwloc_bitmap_and(cpuset, cpuset, topocpuset); tids[i] = tid; tidcpusets[i] = hwloc_bitmap_dup(cpuset); i++; if (hwloc_bitmap_iszero(cpuset)) continue; if (hwloc_bitmap_isequal(cpuset, topocpuset) && !show_all) continue; boundthreads++; } } else { /* failed to alloc, behave as if there were no threads */ free(tids); tids = NULL; free(tidcpusets); tidcpusets = NULL; } } closedir(taskdir); } #endif /* HWLOC_LINUX_SYS */ } if (get_last_cpu_location) { if (hwloc_get_proc_last_cpu_location(topology, pid, cpuset, 0)) continue; } else { if (hwloc_get_proc_cpubind(topology, pid, cpuset, 0)) continue; } hwloc_bitmap_and(cpuset, cpuset, topocpuset); if (hwloc_bitmap_iszero(cpuset)) continue; /* don't print anything if the process isn't bound and if no threads are bound and if not showing all */ if (hwloc_bitmap_isequal(cpuset, topocpuset) && (!tids || !boundthreads) && !show_all) continue; pidoutput[0] = '\0'; if (pidcmd) { char *cmd; FILE *file; cmd = malloc(strlen(pidcmd)+1+5+2+1); sprintf(cmd, "%s %u", pidcmd, pid); file = popen(cmd, "r"); if (file) { if (fgets(pidoutput, sizeof(pidoutput), file)) { end = strchr(pidoutput, '\n'); if (end) *end = '\0'; } pclose(file); } free(cmd); } /* print the process */ print_task(topology, pid_number, name, cpuset, pidoutput[0] == '\0' ? NULL : pidoutput, 0); if (tids) /* print each tid we found (it's tidcpuset isn't NULL anymore) */ for(i=0; tidcpusets[i] != NULL; i++) { print_task(topology, tids[i], "", tidcpusets[i], NULL, 1); hwloc_bitmap_free(tidcpusets[i]); } /* free threads stuff */ free(tidcpusets); free(tids); } err = 0; hwloc_bitmap_free(cpuset); out_with_dir: closedir(dir); out_with_topology: hwloc_topology_destroy(topology); out: return err; }
int main (int argc, char *argv[]) { int err; hwloc_topology_t topology; const char *filename = NULL; unsigned long flags = HWLOC_TOPOLOGY_FLAG_IO_DEVICES | HWLOC_TOPOLOGY_FLAG_IO_BRIDGES | HWLOC_TOPOLOGY_FLAG_ICACHES; unsigned long restrict_flags = 0; int merge = 0; int ignorecache = 0; char * callname; char * input = NULL; enum hwloc_utils_input_format input_format = HWLOC_UTILS_INPUT_DEFAULT; enum output_format output_format = LSTOPO_OUTPUT_DEFAULT; char *restrictstring = NULL; struct lstopo_output loutput; int opt; unsigned i; loutput.overwrite = 0; loutput.logical = -1; loutput.legend = 1; loutput.verbose_mode = LSTOPO_VERBOSE_MODE_DEFAULT; for(i=0; i<HWLOC_OBJ_TYPE_MAX; i++) force_orient[i] = LSTOPO_ORIENT_NONE; force_orient[HWLOC_OBJ_PU] = LSTOPO_ORIENT_HORIZ; force_orient[HWLOC_OBJ_CACHE] = LSTOPO_ORIENT_HORIZ; force_orient[HWLOC_OBJ_NUMANODE] = LSTOPO_ORIENT_HORIZ; /* enable verbose backends */ putenv("HWLOC_XML_VERBOSE=1"); putenv("HWLOC_SYNTHETIC_VERBOSE=1"); #ifdef HAVE_SETLOCALE setlocale(LC_ALL, ""); #endif callname = strrchr(argv[0], '/'); if (!callname) callname = argv[0]; else callname++; /* skip argv[0], handle options */ argc--; argv++; err = hwloc_topology_init (&topology); if (err) return EXIT_FAILURE; while (argc >= 1) { opt = 0; if (!strcmp (argv[0], "-v") || !strcmp (argv[0], "--verbose")) { loutput.verbose_mode++; } else if (!strcmp (argv[0], "-s") || !strcmp (argv[0], "--silent")) { loutput.verbose_mode--; } else if (!strcmp (argv[0], "-h") || !strcmp (argv[0], "--help")) { usage(callname, stdout); exit(EXIT_SUCCESS); } else if (!strcmp (argv[0], "-f") || !strcmp (argv[0], "--force")) loutput.overwrite = 1; else if (!strcmp (argv[0], "-l") || !strcmp (argv[0], "--logical")) loutput.logical = 1; else if (!strcmp (argv[0], "-p") || !strcmp (argv[0], "--physical")) loutput.logical = 0; else if (!strcmp (argv[0], "-c") || !strcmp (argv[0], "--cpuset")) lstopo_show_cpuset = 1; else if (!strcmp (argv[0], "-C") || !strcmp (argv[0], "--cpuset-only")) lstopo_show_cpuset = 2; else if (!strcmp (argv[0], "--taskset")) { lstopo_show_taskset = 1; if (!lstopo_show_cpuset) lstopo_show_cpuset = 1; } else if (!strcmp (argv[0], "--only")) { if (argc < 2) { usage (callname, stderr); exit(EXIT_FAILURE); } if (hwloc_obj_type_sscanf(argv[1], &lstopo_show_only, NULL, NULL, 0) < 0) fprintf(stderr, "Unsupported type `%s' passed to --only, ignoring.\n", argv[1]); opt = 1; } else if (!strcmp (argv[0], "--ignore")) { hwloc_obj_type_t type; if (argc < 2) { usage (callname, stderr); exit(EXIT_FAILURE); } if (hwloc_obj_type_sscanf(argv[1], &type, NULL, NULL, 0) < 0) fprintf(stderr, "Unsupported type `%s' passed to --ignore, ignoring.\n", argv[1]); else if (type == HWLOC_OBJ_PU) lstopo_ignore_pus = 1; else hwloc_topology_ignore_type(topology, type); opt = 1; } else if (!strcmp (argv[0], "--no-caches")) ignorecache = 2; else if (!strcmp (argv[0], "--no-useless-caches")) ignorecache = 1; else if (!strcmp (argv[0], "--no-icaches")) flags &= ~HWLOC_TOPOLOGY_FLAG_ICACHES; else if (!strcmp (argv[0], "--whole-system")) flags |= HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM; else if (!strcmp (argv[0], "--no-io")) flags &= ~(HWLOC_TOPOLOGY_FLAG_IO_DEVICES | HWLOC_TOPOLOGY_FLAG_IO_BRIDGES); else if (!strcmp (argv[0], "--no-bridges")) flags &= ~(HWLOC_TOPOLOGY_FLAG_IO_BRIDGES); else if (!strcmp (argv[0], "--whole-io")) flags |= HWLOC_TOPOLOGY_FLAG_WHOLE_IO; else if (!strcmp (argv[0], "--merge")) merge = 1; else if (!strcmp (argv[0], "--no-collapse")) lstopo_collapse = 0; else if (!strcmp (argv[0], "--thissystem")) flags |= HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM; else if (!strcmp (argv[0], "--restrict")) { if (argc < 2) { usage (callname, stderr); exit(EXIT_FAILURE); } restrictstring = strdup(argv[1]); opt = 1; } else if (!strcmp (argv[0], "--restrict-flags")) { if (argc < 2) { usage (callname, stderr); exit(EXIT_FAILURE); } restrict_flags = (unsigned long) strtoull(argv[1], NULL, 0); opt = 1; } else if (!strcmp (argv[0], "--export-synthetic-flags")) { if (argc < 2) { usage (callname, stderr); exit(EXIT_FAILURE); } lstopo_export_synthetic_flags = (unsigned long) strtoull(argv[1], NULL, 0); opt = 1; } else if (!strcmp (argv[0], "--horiz")) for(i=0; i<HWLOC_OBJ_TYPE_MAX; i++) force_orient[i] = LSTOPO_ORIENT_HORIZ; else if (!strcmp (argv[0], "--vert")) for(i=0; i<HWLOC_OBJ_TYPE_MAX; i++) force_orient[i] = LSTOPO_ORIENT_VERT; else if (!strcmp (argv[0], "--rect")) for(i=0; i<HWLOC_OBJ_TYPE_MAX; i++) force_orient[i] = LSTOPO_ORIENT_RECT; else if (!strncmp (argv[0], "--horiz=", 8) || !strncmp (argv[0], "--vert=", 7) || !strncmp (argv[0], "--rect=", 7)) { enum lstopo_orient_e orient = (argv[0][2] == 'h') ? LSTOPO_ORIENT_HORIZ : (argv[0][2] == 'v') ? LSTOPO_ORIENT_VERT : LSTOPO_ORIENT_RECT; char *tmp = argv[0] + ((argv[0][2] == 'h') ? 8 : 7); while (tmp) { char *end = strchr(tmp, ','); hwloc_obj_type_t type; if (end) *end = '\0'; if (hwloc_obj_type_sscanf(tmp, &type, NULL, NULL, 0) < 0) fprintf(stderr, "Unsupported type `%s' passed to %s, ignoring.\n", tmp, argv[0]); else force_orient[type] = orient; if (!end) break; tmp = end+1; } } else if (!strcmp (argv[0], "--fontsize")) { if (argc < 2) { usage (callname, stderr); exit(EXIT_FAILURE); } fontsize = atoi(argv[1]); opt = 1; } else if (!strcmp (argv[0], "--gridsize")) { if (argc < 2) { usage (callname, stderr); exit(EXIT_FAILURE); } gridsize = atoi(argv[1]); opt = 1; } else if (!strcmp (argv[0], "--no-legend")) { loutput.legend = 0; } else if (!strcmp (argv[0], "--append-legend")) { char **tmp; if (argc < 2) { usage (callname, stderr); exit(EXIT_FAILURE); } tmp = realloc(lstopo_append_legends, (lstopo_append_legends_nr+1) * sizeof(*lstopo_append_legends)); if (!tmp) { fprintf(stderr, "Failed to realloc legend append array, legend ignored.\n"); } else { lstopo_append_legends = tmp; lstopo_append_legends[lstopo_append_legends_nr] = strdup(argv[1]); lstopo_append_legends_nr++; } opt = 1; } else if (hwloc_utils_lookup_input_option(argv, argc, &opt, &input, &input_format, callname)) { /* nothing to do anymore */ } else if (!strcmp (argv[0], "--pid")) { if (argc < 2) { usage (callname, stderr); exit(EXIT_FAILURE); } lstopo_pid_number = atoi(argv[1]); opt = 1; } else if (!strcmp (argv[0], "--ps") || !strcmp (argv[0], "--top")) top = 1; else if (!strcmp (argv[0], "--version")) { printf("%s %s\n", callname, HWLOC_VERSION); exit(EXIT_SUCCESS); } else if (!strcmp (argv[0], "--output-format") || !strcmp (argv[0], "--of")) { if (argc < 2) { usage (callname, stderr); exit(EXIT_FAILURE); } output_format = parse_output_format(argv[1], callname); opt = 1; } else { if (filename) { fprintf (stderr, "Unrecognized option: %s\n", argv[0]); usage (callname, stderr); exit(EXIT_FAILURE); } else filename = argv[0]; } argc -= opt+1; argv += opt+1; } if (lstopo_show_only != (hwloc_obj_type_t)-1) merge = 0; hwloc_topology_set_flags(topology, flags); if (ignorecache > 1) { hwloc_topology_ignore_type(topology, HWLOC_OBJ_CACHE); } else if (ignorecache) { hwloc_topology_ignore_type_keep_structure(topology, HWLOC_OBJ_CACHE); } if (merge) hwloc_topology_ignore_all_keep_structure(topology); if (input) { err = hwloc_utils_enable_input_format(topology, input, &input_format, loutput.verbose_mode > 1, callname); if (err) return err; } if (lstopo_pid_number > 0) { lstopo_pid = hwloc_pid_from_number(lstopo_pid_number, 0); if (hwloc_topology_set_pid(topology, lstopo_pid)) { perror("Setting target pid"); return EXIT_FAILURE; } } /* if the output format wasn't enforced, look at the filename */ if (filename && output_format == LSTOPO_OUTPUT_DEFAULT) { if (!strcmp(filename, "-") || !strcmp(filename, "/dev/stdout")) { output_format = LSTOPO_OUTPUT_CONSOLE; } else { char *dot = strrchr(filename, '.'); if (dot) output_format = parse_output_format(dot+1, callname); else { fprintf(stderr, "Cannot infer output type for file `%s' without any extension, using default output.\n", filename); filename = NULL; } } } /* if the output format wasn't enforced, think a bit about what the user probably want */ if (output_format == LSTOPO_OUTPUT_DEFAULT) { if (lstopo_show_cpuset || lstopo_show_only != (hwloc_obj_type_t)-1 || loutput.verbose_mode != LSTOPO_VERBOSE_MODE_DEFAULT) output_format = LSTOPO_OUTPUT_CONSOLE; } if (input_format == HWLOC_UTILS_INPUT_XML && output_format == LSTOPO_OUTPUT_XML) { /* must be after parsing output format and before loading the topology */ putenv("HWLOC_XML_USERDATA_NOT_DECODED=1"); hwloc_topology_set_userdata_import_callback(topology, hwloc_utils_userdata_import_cb); hwloc_topology_set_userdata_export_callback(topology, hwloc_utils_userdata_export_cb); } err = hwloc_topology_load (topology); if (err) { fprintf(stderr, "hwloc_topology_load() failed (%s).\n", strerror(errno)); return EXIT_FAILURE; } if (top) add_process_objects(topology); if (restrictstring) { hwloc_bitmap_t restrictset = hwloc_bitmap_alloc(); if (!strcmp (restrictstring, "binding")) { if (lstopo_pid_number > 0) hwloc_get_proc_cpubind(topology, lstopo_pid, restrictset, HWLOC_CPUBIND_PROCESS); else hwloc_get_cpubind(topology, restrictset, HWLOC_CPUBIND_PROCESS); } else { hwloc_bitmap_sscanf(restrictset, restrictstring); } err = hwloc_topology_restrict (topology, restrictset, restrict_flags); if (err) { perror("Restricting the topology"); /* fallthrough */ } hwloc_bitmap_free(restrictset); free(restrictstring); } if (loutput.logical == -1) { if (output_format == LSTOPO_OUTPUT_CONSOLE) loutput.logical = 1; else if (output_format != LSTOPO_OUTPUT_DEFAULT) loutput.logical = 0; } loutput.topology = topology; loutput.file = NULL; lstopo_populate_userdata(hwloc_get_root_obj(topology)); if (output_format != LSTOPO_OUTPUT_XML && lstopo_collapse) lstopo_add_collapse_attributes(topology); switch (output_format) { case LSTOPO_OUTPUT_DEFAULT: #ifdef LSTOPO_HAVE_GRAPHICS #if CAIRO_HAS_XLIB_SURFACE && defined HWLOC_HAVE_X11_KEYSYM if (getenv("DISPLAY")) { if (loutput.logical == -1) loutput.logical = 0; output_x11(&loutput, NULL); } else #endif /* CAIRO_HAS_XLIB_SURFACE */ #ifdef HWLOC_WIN_SYS { if (loutput.logical == -1) loutput.logical = 0; output_windows(&loutput, NULL); } #endif #endif /* !LSTOPO_HAVE_GRAPHICS */ #if !defined HWLOC_WIN_SYS || !defined LSTOPO_HAVE_GRAPHICS { if (loutput.logical == -1) loutput.logical = 1; output_console(&loutput, NULL); } #endif break; case LSTOPO_OUTPUT_CONSOLE: output_console(&loutput, filename); break; case LSTOPO_OUTPUT_SYNTHETIC: output_synthetic(&loutput, filename); break; case LSTOPO_OUTPUT_ASCII: output_ascii(&loutput, filename); break; case LSTOPO_OUTPUT_FIG: output_fig(&loutput, filename); break; #ifdef LSTOPO_HAVE_GRAPHICS # if CAIRO_HAS_PNG_FUNCTIONS case LSTOPO_OUTPUT_PNG: output_png(&loutput, filename); break; # endif /* CAIRO_HAS_PNG_FUNCTIONS */ # if CAIRO_HAS_PDF_SURFACE case LSTOPO_OUTPUT_PDF: output_pdf(&loutput, filename); break; # endif /* CAIRO_HAS_PDF_SURFACE */ # if CAIRO_HAS_PS_SURFACE case LSTOPO_OUTPUT_PS: output_ps(&loutput, filename); break; #endif /* CAIRO_HAS_PS_SURFACE */ #if CAIRO_HAS_SVG_SURFACE case LSTOPO_OUTPUT_SVG: output_svg(&loutput, filename); break; #endif /* CAIRO_HAS_SVG_SURFACE */ #endif /* LSTOPO_HAVE_GRAPHICS */ case LSTOPO_OUTPUT_XML: output_xml(&loutput, filename); break; default: fprintf(stderr, "file format not supported\n"); usage(callname, stderr); exit(EXIT_FAILURE); } lstopo_destroy_userdata(hwloc_get_root_obj(topology)); hwloc_utils_userdata_free_recursive(hwloc_get_root_obj(topology)); hwloc_topology_destroy (topology); for(i=0; i<lstopo_append_legends_nr; i++) free(lstopo_append_legends[i]); free(lstopo_append_legends); return EXIT_SUCCESS; }
static void add_process_objects(hwloc_topology_t topology) { #ifdef HAVE_DIRENT_H hwloc_obj_t root; hwloc_bitmap_t cpuset; #ifdef HWLOC_LINUX_SYS hwloc_bitmap_t task_cpuset; #endif /* HWLOC_LINUX_SYS */ DIR *dir; struct dirent *dirent; const struct hwloc_topology_support *support; root = hwloc_get_root_obj(topology); support = hwloc_topology_get_support(topology); if (!support->cpubind->get_proc_cpubind) return; dir = opendir("/proc"); if (!dir) return; cpuset = hwloc_bitmap_alloc(); #ifdef HWLOC_LINUX_SYS task_cpuset = hwloc_bitmap_alloc(); #endif /* HWLOC_LINUX_SYS */ while ((dirent = readdir(dir))) { long local_pid_number; hwloc_pid_t local_pid; char *end; char name[64]; int proc_cpubind; local_pid_number = strtol(dirent->d_name, &end, 10); if (*end) /* Not a number */ continue; snprintf(name, sizeof(name), "%ld", local_pid_number); local_pid = hwloc_pid_from_number(local_pid_number, 0); proc_cpubind = hwloc_get_proc_cpubind(topology, local_pid, cpuset, 0) != -1; #ifdef HWLOC_LINUX_SYS { /* Get the process name */ char *path; unsigned pathlen = 6 + strlen(dirent->d_name) + 1 + 7 + 1; char cmd[64], *c; int file; ssize_t n; path = malloc(pathlen); snprintf(path, pathlen, "/proc/%s/cmdline", dirent->d_name); file = open(path, O_RDONLY); free(path); if (file >= 0) { n = read(file, cmd, sizeof(cmd) - 1); close(file); if (n <= 0) /* Ignore kernel threads and errors */ continue; cmd[n] = 0; if ((c = strchr(cmd, ' '))) *c = 0; snprintf(name, sizeof(name), "%ld %s", local_pid_number, cmd); } } { /* Get threads */ char *path; unsigned pathlen = 6+strlen(dirent->d_name) + 1 + 4 + 1; DIR *task_dir; struct dirent *task_dirent; path = malloc(pathlen); snprintf(path, pathlen, "/proc/%s/task", dirent->d_name); task_dir = opendir(path); free(path); if (task_dir) { while ((task_dirent = readdir(task_dir))) { long local_tid; char *task_end; char task_name[64]; local_tid = strtol(task_dirent->d_name, &task_end, 10); if (*task_end) /* Not a number, or the main task */ continue; if (hwloc_linux_get_tid_cpubind(topology, local_tid, task_cpuset)) continue; if (proc_cpubind && hwloc_bitmap_isequal(task_cpuset, cpuset)) continue; snprintf(task_name, sizeof(task_name), "%s %li", name, local_tid); insert_task(topology, task_cpuset, task_name); } closedir(task_dir); } } #endif /* HWLOC_LINUX_SYS */ if (!proc_cpubind) continue; if (hwloc_bitmap_isincluded(root->cpuset, cpuset)) continue; insert_task(topology, cpuset, name); } hwloc_bitmap_free(cpuset); #ifdef HWLOC_LINUX_SYS hwloc_bitmap_free(task_cpuset); #endif /* HWLOC_LINUX_SYS */ closedir(dir); #endif /* HAVE_DIRENT_H */ }
int main(int argc, char *argv[]) { hwloc_topology_t topology; int loaded = 0; unsigned depth; hwloc_bitmap_t cpubind_set, membind_set; int got_cpubind = 0, got_membind = 0; int working_on_cpubind = 1; /* membind if 0 */ int get_binding = 0; int get_last_cpu_location = 0; unsigned long flags = 0; int force = 0; int single = 0; int verbose = 0; int logical = 1; int taskset = 0; int cpubind_flags = 0; hwloc_membind_policy_t membind_policy = HWLOC_MEMBIND_BIND; int membind_flags = 0; int opt; int ret; int pid_number = -1; hwloc_pid_t pid = 0; /* only valid when pid_number > 0, but gcc-4.8 still reports uninitialized warnings */ char *callname; cpubind_set = hwloc_bitmap_alloc(); membind_set = hwloc_bitmap_alloc(); /* don't load now, in case some options change the config before the topology is actually used */ #define LOADED() (loaded) #define ENSURE_LOADED() do { \ if (!loaded) { \ hwloc_topology_init(&topology); \ hwloc_topology_set_all_types_filter(topology, HWLOC_TYPE_FILTER_KEEP_ALL); \ hwloc_topology_set_flags(topology, flags); \ hwloc_topology_load(topology); \ depth = hwloc_topology_get_depth(topology); \ loaded = 1; \ } \ } while (0) callname = argv[0]; /* skip argv[0], handle options */ argv++; argc--; while (argc >= 1) { if (!strcmp(argv[0], "--")) { argc--; argv++; break; } opt = 0; if (*argv[0] == '-') { if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--verbose")) { verbose++; goto next; } if (!strcmp(argv[0], "-q") || !strcmp(argv[0], "--quiet")) { verbose--; goto next; } if (!strcmp(argv[0], "--help")) { usage("hwloc-bind", stdout); return EXIT_SUCCESS; } if (!strcmp(argv[0], "--single")) { single = 1; goto next; } if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--force")) { force = 1; goto next; } if (!strcmp(argv[0], "--strict")) { cpubind_flags |= HWLOC_CPUBIND_STRICT; membind_flags |= HWLOC_MEMBIND_STRICT; goto next; } if (!strcmp(argv[0], "--pid")) { if (argc < 2) { usage ("hwloc-bind", stderr); exit(EXIT_FAILURE); } pid_number = atoi(argv[1]); opt = 1; goto next; } if (!strcmp (argv[0], "--version")) { printf("%s %s\n", callname, HWLOC_VERSION); exit(EXIT_SUCCESS); } if (!strcmp(argv[0], "-l") || !strcmp(argv[0], "--logical")) { logical = 1; goto next; } if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--physical")) { logical = 0; goto next; } if (!strcmp(argv[0], "--taskset")) { taskset = 1; goto next; } if (!strcmp (argv[0], "-e") || !strncmp (argv[0], "--get-last-cpu-location", 10)) { get_last_cpu_location = 1; goto next; } if (!strcmp (argv[0], "--get")) { get_binding = 1; goto next; } if (!strcmp (argv[0], "--cpubind")) { working_on_cpubind = 1; goto next; } if (!strcmp (argv[0], "--membind")) { working_on_cpubind = 0; goto next; } if (!strcmp (argv[0], "--mempolicy")) { if (!strncmp(argv[1], "default", 2)) membind_policy = HWLOC_MEMBIND_DEFAULT; else if (!strncmp(argv[1], "firsttouch", 2)) membind_policy = HWLOC_MEMBIND_FIRSTTOUCH; else if (!strncmp(argv[1], "bind", 2)) membind_policy = HWLOC_MEMBIND_BIND; else if (!strncmp(argv[1], "interleave", 2)) membind_policy = HWLOC_MEMBIND_INTERLEAVE; else if (!strncmp(argv[1], "nexttouch", 2)) membind_policy = HWLOC_MEMBIND_NEXTTOUCH; else { fprintf(stderr, "Unrecognized memory binding policy %s\n", argv[1]); usage ("hwloc-bind", stderr); exit(EXIT_FAILURE); } opt = 1; goto next; } if (!strcmp (argv[0], "--whole-system")) { if (loaded) { fprintf(stderr, "Input option %s disallowed after options using the topology\n", argv[0]); exit(EXIT_FAILURE); } flags |= HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM; goto next; } if (!strcmp (argv[0], "--restrict")) { hwloc_bitmap_t restrictset; int err; if (argc < 2) { usage (callname, stdout); exit(EXIT_FAILURE); } restrictset = hwloc_bitmap_alloc(); hwloc_bitmap_sscanf(restrictset, argv[1]); ENSURE_LOADED(); err = hwloc_topology_restrict (topology, restrictset, 0); if (err) { perror("Restricting the topology"); /* fallthrough */ } hwloc_bitmap_free(restrictset); argc--; argv++; goto next; } fprintf (stderr, "Unrecognized option: %s\n", argv[0]); usage("hwloc-bind", stderr); return EXIT_FAILURE; } ENSURE_LOADED(); ret = hwloc_calc_process_arg(topology, depth, argv[0], logical, working_on_cpubind ? cpubind_set : membind_set, verbose); if (ret < 0) { if (verbose > 0) fprintf(stderr, "assuming the command starts at %s\n", argv[0]); break; } if (working_on_cpubind) got_cpubind = 1; else got_membind = 1; next: argc -= opt+1; argv += opt+1; } ENSURE_LOADED(); if (pid_number > 0) { pid = hwloc_pid_from_number(pid_number, !(get_binding || get_last_cpu_location)); /* no need to set_pid() * the doc just says we're operating on pid, not that we're retrieving the topo/cpuset as seen from inside pid */ } if (get_last_cpu_location && !working_on_cpubind) { fprintf(stderr, "Options --membind and --get-last-cpu-location cannot be combined.\n"); return EXIT_FAILURE; } if ((get_binding || get_last_cpu_location) && (got_cpubind || got_membind)) { /* doesn't work because get_binding/get_last_cpu_location overwrites cpubind_set */ fprintf(stderr, "Cannot display and set binding at the same time.\n"); return EXIT_FAILURE; } if (get_binding || get_last_cpu_location) { char *s; const char *policystr = NULL; int err; if (working_on_cpubind) { if (get_last_cpu_location) { if (pid_number > 0) err = hwloc_get_proc_last_cpu_location(topology, pid, cpubind_set, 0); else err = hwloc_get_last_cpu_location(topology, cpubind_set, 0); } else { if (pid_number > 0) err = hwloc_get_proc_cpubind(topology, pid, cpubind_set, 0); else err = hwloc_get_cpubind(topology, cpubind_set, 0); } if (err) { const char *errmsg = strerror(errno); if (pid_number > 0) fprintf(stderr, "hwloc_get_proc_%s %d failed (errno %d %s)\n", get_last_cpu_location ? "last_cpu_location" : "cpubind", pid_number, errno, errmsg); else fprintf(stderr, "hwloc_get_%s failed (errno %d %s)\n", get_last_cpu_location ? "last_cpu_location" : "cpubind", errno, errmsg); return EXIT_FAILURE; } if (taskset) hwloc_bitmap_taskset_asprintf(&s, cpubind_set); else hwloc_bitmap_asprintf(&s, cpubind_set); } else { hwloc_membind_policy_t policy; if (pid_number > 0) err = hwloc_get_proc_membind(topology, pid, membind_set, &policy, 0); else err = hwloc_get_membind(topology, membind_set, &policy, 0); if (err) { const char *errmsg = strerror(errno); if (pid_number > 0) fprintf(stderr, "hwloc_get_proc_membind %d failed (errno %d %s)\n", pid_number, errno, errmsg); else fprintf(stderr, "hwloc_get_membind failed (errno %d %s)\n", errno, errmsg); return EXIT_FAILURE; } if (taskset) hwloc_bitmap_taskset_asprintf(&s, membind_set); else hwloc_bitmap_asprintf(&s, membind_set); switch (policy) { case HWLOC_MEMBIND_DEFAULT: policystr = "default"; break; case HWLOC_MEMBIND_FIRSTTOUCH: policystr = "firsttouch"; break; case HWLOC_MEMBIND_BIND: policystr = "bind"; break; case HWLOC_MEMBIND_INTERLEAVE: policystr = "interleave"; break; case HWLOC_MEMBIND_NEXTTOUCH: policystr = "nexttouch"; break; default: fprintf(stderr, "unknown memory policy %d\n", policy); assert(0); break; } } if (policystr) printf("%s (%s)\n", s, policystr); else printf("%s\n", s); free(s); } if (got_membind) { if (hwloc_bitmap_iszero(membind_set)) { if (verbose >= 0) fprintf(stderr, "cannot membind to empty set\n"); if (!force) goto failed_binding; } if (verbose > 0) { char *s; hwloc_bitmap_asprintf(&s, membind_set); fprintf(stderr, "binding on memory set %s\n", s); free(s); } if (single) hwloc_bitmap_singlify(membind_set); if (pid_number > 0) ret = hwloc_set_proc_membind(topology, pid, membind_set, membind_policy, membind_flags); else ret = hwloc_set_membind(topology, membind_set, membind_policy, membind_flags); if (ret && verbose >= 0) { int bind_errno = errno; const char *errmsg = strerror(bind_errno); char *s; hwloc_bitmap_asprintf(&s, membind_set); if (pid_number > 0) fprintf(stderr, "hwloc_set_proc_membind %s %d failed (errno %d %s)\n", s, pid_number, bind_errno, errmsg); else fprintf(stderr, "hwloc_set_membind %s failed (errno %d %s)\n", s, bind_errno, errmsg); free(s); } if (ret && !force) goto failed_binding; } if (got_cpubind) { if (hwloc_bitmap_iszero(cpubind_set)) { if (verbose >= 0) fprintf(stderr, "cannot cpubind to empty set\n"); if (!force) goto failed_binding; } if (verbose > 0) { char *s; hwloc_bitmap_asprintf(&s, cpubind_set); fprintf(stderr, "binding on cpu set %s\n", s); free(s); } if (single) hwloc_bitmap_singlify(cpubind_set); if (pid_number > 0) ret = hwloc_set_proc_cpubind(topology, pid, cpubind_set, cpubind_flags); else ret = hwloc_set_cpubind(topology, cpubind_set, cpubind_flags); if (ret && verbose >= 0) { int bind_errno = errno; const char *errmsg = strerror(bind_errno); char *s; hwloc_bitmap_asprintf(&s, cpubind_set); if (pid_number > 0) fprintf(stderr, "hwloc_set_proc_cpubind %s %d failed (errno %d %s)\n", s, pid_number, bind_errno, errmsg); else fprintf(stderr, "hwloc_set_cpubind %s failed (errno %d %s)\n", s, bind_errno, errmsg); free(s); } if (ret && !force) goto failed_binding; } hwloc_bitmap_free(cpubind_set); hwloc_bitmap_free(membind_set); hwloc_topology_destroy(topology); if (pid_number > 0) return EXIT_SUCCESS; if (0 == argc) { if (get_binding || get_last_cpu_location) return EXIT_SUCCESS; fprintf(stderr, "%s: nothing to do!\n", callname); return EXIT_FAILURE; } /* FIXME: check whether Windows execvp() passes INHERIT_PARENT_AFFINITY to CreateProcess() * because we need to propagate processor group affinity. However process-wide affinity * isn't supported with processor groups so far. */ ret = execvp(argv[0], argv); if (ret) { fprintf(stderr, "%s: Failed to launch executable \"%s\"\n", callname, argv[0]); perror("execvp"); } return EXIT_FAILURE; failed_binding: hwloc_bitmap_free(cpubind_set); hwloc_bitmap_free(membind_set); hwloc_topology_destroy(topology); return EXIT_FAILURE; }
int main(int argc, char *argv[]) { hwloc_topology_t topology; unsigned depth; hwloc_bitmap_t cpubind_set, membind_set; int got_cpubind = 0, got_membind = 0; int working_on_cpubind = 1; /* membind if 0 */ int get_binding = 0; int get_last_cpu_location = 0; unsigned long flags = HWLOC_TOPOLOGY_FLAG_WHOLE_IO|HWLOC_TOPOLOGY_FLAG_ICACHES; int force = 0; int single = 0; int verbose = 0; int logical = 1; int taskset = 0; int cpubind_flags = 0; hwloc_membind_policy_t membind_policy = HWLOC_MEMBIND_BIND; int membind_flags = 0; int opt; int ret; int pid_number = 0; hwloc_pid_t pid; char *callname; cpubind_set = hwloc_bitmap_alloc(); membind_set = hwloc_bitmap_alloc(); hwloc_topology_init(&topology); hwloc_topology_set_flags(topology, flags); hwloc_topology_load(topology); depth = hwloc_topology_get_depth(topology); callname = argv[0]; /* skip argv[0], handle options */ argv++; argc--; while (argc >= 1) { if (!strcmp(argv[0], "--")) { argc--; argv++; break; } opt = 0; if (*argv[0] == '-') { if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--verbose")) { verbose++; goto next; } else if (!strcmp(argv[0], "-q") || !strcmp(argv[0], "--quiet")) { verbose--; goto next; } else if (!strcmp(argv[0], "--help")) { usage("hwloc-bind", stdout); return EXIT_SUCCESS; } else if (!strcmp(argv[0], "--single")) { single = 1; goto next; } else if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--force")) { force = 1; goto next; } else if (!strcmp(argv[0], "--strict")) { cpubind_flags |= HWLOC_CPUBIND_STRICT; membind_flags |= HWLOC_MEMBIND_STRICT; goto next; } else if (!strcmp(argv[0], "--pid")) { if (argc < 2) { usage ("hwloc-bind", stderr); exit(EXIT_FAILURE); } pid_number = atoi(argv[1]); opt = 1; goto next; } else if (!strcmp (argv[0], "--version")) { printf("%s %s\n", callname, VERSION); exit(EXIT_SUCCESS); } if (!strcmp(argv[0], "-l") || !strcmp(argv[0], "--logical")) { logical = 1; goto next; } if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--physical")) { logical = 0; goto next; } if (!strcmp(argv[0], "--taskset")) { taskset = 1; goto next; } else if (!strcmp (argv[0], "-e") || !strncmp (argv[0], "--get-last-cpu-location", 10)) { get_last_cpu_location = 1; goto next; } else if (!strcmp (argv[0], "--get")) { get_binding = 1; goto next; } else if (!strcmp (argv[0], "--cpubind")) { working_on_cpubind = 1; goto next; } else if (!strcmp (argv[0], "--membind")) { working_on_cpubind = 0; goto next; } else if (!strcmp (argv[0], "--mempolicy")) { if (!strncmp(argv[1], "default", 2)) membind_policy = HWLOC_MEMBIND_DEFAULT; else if (!strncmp(argv[1], "firsttouch", 2)) membind_policy = HWLOC_MEMBIND_FIRSTTOUCH; else if (!strncmp(argv[1], "bind", 2)) membind_policy = HWLOC_MEMBIND_BIND; else if (!strncmp(argv[1], "interleave", 2)) membind_policy = HWLOC_MEMBIND_INTERLEAVE; else if (!strncmp(argv[1], "replicate", 2)) membind_policy = HWLOC_MEMBIND_REPLICATE; else if (!strncmp(argv[1], "nexttouch", 2)) membind_policy = HWLOC_MEMBIND_NEXTTOUCH; else { fprintf(stderr, "Unrecognized memory binding policy %s\n", argv[1]); usage ("hwloc-bind", stderr); exit(EXIT_FAILURE); } opt = 1; goto next; } else if (!strcmp (argv[0], "--whole-system")) { flags |= HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM; hwloc_topology_destroy(topology); hwloc_topology_init(&topology); hwloc_topology_set_flags(topology, flags); hwloc_topology_load(topology); depth = hwloc_topology_get_depth(topology); goto next; } else if (!strcmp (argv[0], "--restrict")) { hwloc_bitmap_t restrictset; int err; if (argc < 2) { usage (callname, stdout); exit(EXIT_FAILURE); } restrictset = hwloc_bitmap_alloc(); hwloc_bitmap_sscanf(restrictset, argv[1]); err = hwloc_topology_restrict (topology, restrictset, 0); if (err) { perror("Restricting the topology"); /* fallthrough */ } hwloc_bitmap_free(restrictset); argc--; argv++; goto next; } fprintf (stderr, "Unrecognized option: %s\n", argv[0]); usage("hwloc-bind", stderr); return EXIT_FAILURE; } ret = hwloc_calc_process_arg(topology, depth, argv[0], logical, working_on_cpubind ? cpubind_set : membind_set, verbose); if (ret < 0) { if (verbose > 0) fprintf(stderr, "assuming the command starts at %s\n", argv[0]); break; } if (working_on_cpubind) got_cpubind = 1; else got_membind = 1; next: argc -= opt+1; argv += opt+1; } pid = hwloc_pid_from_number(pid_number, !(get_binding || get_last_cpu_location)); if (get_binding || get_last_cpu_location) { char *s; const char *policystr = NULL; int err; if (working_on_cpubind) { if (get_last_cpu_location) { if (pid_number) err = hwloc_get_proc_last_cpu_location(topology, pid, cpubind_set, 0); else err = hwloc_get_last_cpu_location(topology, cpubind_set, 0); } else { if (pid_number) err = hwloc_get_proc_cpubind(topology, pid, cpubind_set, 0); else err = hwloc_get_cpubind(topology, cpubind_set, 0); } if (err) { const char *errmsg = strerror(errno); if (pid_number) fprintf(stderr, "hwloc_get_proc_%s %d failed (errno %d %s)\n", get_last_cpu_location ? "last_cpu_location" : "cpubind", pid_number, errno, errmsg); else fprintf(stderr, "hwloc_get_%s failed (errno %d %s)\n", get_last_cpu_location ? "last_cpu_location" : "cpubind", errno, errmsg); return EXIT_FAILURE; } if (taskset) hwloc_bitmap_taskset_asprintf(&s, cpubind_set); else hwloc_bitmap_asprintf(&s, cpubind_set); } else { hwloc_membind_policy_t policy; if (pid_number) err = hwloc_get_proc_membind(topology, pid, membind_set, &policy, 0); else err = hwloc_get_membind(topology, membind_set, &policy, 0); if (err) { const char *errmsg = strerror(errno); if (pid_number) fprintf(stderr, "hwloc_get_proc_membind %d failed (errno %d %s)\n", pid_number, errno, errmsg); else fprintf(stderr, "hwloc_get_membind failed (errno %d %s)\n", errno, errmsg); return EXIT_FAILURE; } if (taskset) hwloc_bitmap_taskset_asprintf(&s, membind_set); else hwloc_bitmap_asprintf(&s, membind_set); switch (policy) { case HWLOC_MEMBIND_DEFAULT: policystr = "default"; break; case HWLOC_MEMBIND_FIRSTTOUCH: policystr = "firsttouch"; break; case HWLOC_MEMBIND_BIND: policystr = "bind"; break; case HWLOC_MEMBIND_INTERLEAVE: policystr = "interleave"; break; case HWLOC_MEMBIND_REPLICATE: policystr = "replicate"; break; case HWLOC_MEMBIND_NEXTTOUCH: policystr = "nexttouch"; break; default: fprintf(stderr, "unknown memory policy %d\n", policy); assert(0); break; } } if (policystr) printf("%s (%s)\n", s, policystr); else printf("%s\n", s); free(s); return EXIT_SUCCESS; } if (got_membind) { if (hwloc_bitmap_iszero(membind_set)) { if (verbose >= 0) fprintf(stderr, "cannot membind to empty set\n"); if (!force) goto failed_binding; } if (verbose > 0) { char *s; hwloc_bitmap_asprintf(&s, membind_set); fprintf(stderr, "binding on memory set %s\n", s); free(s); } if (single) hwloc_bitmap_singlify(membind_set); if (pid_number) ret = hwloc_set_proc_membind(topology, pid, membind_set, membind_policy, membind_flags); else ret = hwloc_set_membind(topology, membind_set, membind_policy, membind_flags); if (ret && verbose >= 0) { int bind_errno = errno; const char *errmsg = strerror(bind_errno); char *s; hwloc_bitmap_asprintf(&s, membind_set); if (pid_number) fprintf(stderr, "hwloc_set_proc_membind %s %d failed (errno %d %s)\n", s, pid_number, bind_errno, errmsg); else fprintf(stderr, "hwloc_set_membind %s failed (errno %d %s)\n", s, bind_errno, errmsg); free(s); } if (ret && !force) goto failed_binding; } if (got_cpubind) { if (hwloc_bitmap_iszero(cpubind_set)) { if (verbose >= 0) fprintf(stderr, "cannot cpubind to empty set\n"); if (!force) goto failed_binding; } if (verbose > 0) { char *s; hwloc_bitmap_asprintf(&s, cpubind_set); fprintf(stderr, "binding on cpu set %s\n", s); free(s); } if (single) hwloc_bitmap_singlify(cpubind_set); if (pid_number) ret = hwloc_set_proc_cpubind(topology, pid, cpubind_set, cpubind_flags); else ret = hwloc_set_cpubind(topology, cpubind_set, cpubind_flags); if (ret && verbose >= 0) { int bind_errno = errno; const char *errmsg = strerror(bind_errno); char *s; hwloc_bitmap_asprintf(&s, cpubind_set); if (pid_number) fprintf(stderr, "hwloc_set_proc_cpubind %s %d failed (errno %d %s)\n", s, pid_number, bind_errno, errmsg); else fprintf(stderr, "hwloc_set_cpubind %s failed (errno %d %s)\n", s, bind_errno, errmsg); free(s); } if (ret && !force) goto failed_binding; } hwloc_bitmap_free(cpubind_set); hwloc_bitmap_free(membind_set); hwloc_topology_destroy(topology); if (pid_number) return EXIT_SUCCESS; if (0 == argc) { fprintf(stderr, "%s: nothing to do!\n", callname); return EXIT_FAILURE; } ret = execvp(argv[0], argv); if (ret) { fprintf(stderr, "%s: Failed to launch executable \"%s\"\n", callname, argv[0]); perror("execvp"); } return EXIT_FAILURE; failed_binding: hwloc_bitmap_free(cpubind_set); hwloc_bitmap_free(membind_set); hwloc_topology_destroy(topology); return EXIT_FAILURE; }
int MPIR_Init_thread(int *argc, char ***argv, int required, int *provided) { int mpi_errno = MPI_SUCCESS; int has_args; int has_env; int thread_provided = 0; int exit_init_cs_on_failure = 0; MPIR_Info *info_ptr; #if defined(MPICH_IS_THREADED) bool cs_initialized = false; #endif /* The threading library must be initialized at the very beginning because * it manages all synchronization objects (e.g., mutexes) that will be * initialized later */ { int thread_err; MPL_thread_init(&thread_err); if (thread_err) goto fn_fail; } #ifdef HAVE_HWLOC MPIR_Process.bindset = hwloc_bitmap_alloc(); hwloc_topology_init(&MPIR_Process.hwloc_topology); MPIR_Process.bindset_is_valid = 0; hwloc_topology_set_io_types_filter(MPIR_Process.hwloc_topology, HWLOC_TYPE_FILTER_KEEP_ALL); if (!hwloc_topology_load(MPIR_Process.hwloc_topology)) { MPIR_Process.bindset_is_valid = !hwloc_get_proc_cpubind(MPIR_Process.hwloc_topology, getpid(), MPIR_Process.bindset, HWLOC_CPUBIND_PROCESS); } #endif #ifdef HAVE_NETLOC MPIR_Process.network_attr.u.tree.node_levels = NULL; MPIR_Process.network_attr.network_endpoint = NULL; MPIR_Process.netloc_topology = NULL; MPIR_Process.network_attr.type = MPIR_NETLOC_NETWORK_TYPE__INVALID; if (strlen(MPIR_CVAR_NETLOC_NODE_FILE)) { mpi_errno = netloc_parse_topology(&MPIR_Process.netloc_topology, MPIR_CVAR_NETLOC_NODE_FILE); if (mpi_errno == NETLOC_SUCCESS) { MPIR_Netloc_parse_topology(MPIR_Process.netloc_topology, &MPIR_Process.network_attr); } } #endif /* For any code in the device that wants to check for runtime * decisions on the value of isThreaded, set a provisional * value here. We could let the MPID_Init routine override this */ #if defined MPICH_IS_THREADED MPIR_ThreadInfo.isThreaded = required == MPI_THREAD_MULTIPLE; #endif /* MPICH_IS_THREADED */ #if defined(MPICH_IS_THREADED) mpi_errno = thread_cs_init(); cs_initialized = true; if (mpi_errno) MPIR_ERR_POP(mpi_errno); #endif /* FIXME: Move to os-dependent interface? */ #ifdef HAVE_WINDOWS_H /* prevent the process from bringing up an error message window if mpich * asserts */ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportHook2(_CRT_RPTHOOK_INSTALL, assert_hook); #ifdef _WIN64 { /* FIXME: (Windows) This severly degrades performance but fixes alignment * issues with the datatype code. */ /* Prevent misaligned faults on Win64 machines */ UINT mode, old_mode; old_mode = SetErrorMode(SEM_NOALIGNMENTFAULTEXCEPT); mode = old_mode | SEM_NOALIGNMENTFAULTEXCEPT; SetErrorMode(mode); } #endif #endif /* We need this inorder to implement IS_THREAD_MAIN */ #if (MPICH_THREAD_LEVEL >= MPI_THREAD_SERIALIZED) && defined(MPICH_IS_THREADED) { MPID_Thread_self(&MPIR_ThreadInfo.master_thread); } #endif #ifdef HAVE_ERROR_CHECKING /* Because the PARAM system has not been initialized, temporarily * uncondtionally enable error checks. Once the PARAM system is * initialized, this may be reset */ MPIR_Process.do_error_checks = 1; #else MPIR_Process.do_error_checks = 0; #endif /* Initialize necessary subsystems and setup the predefined attribute * values. Subsystems may change these values. */ MPIR_Process.attrs.appnum = -1; MPIR_Process.attrs.host = MPI_PROC_NULL; MPIR_Process.attrs.io = MPI_PROC_NULL; MPIR_Process.attrs.lastusedcode = MPI_ERR_LASTCODE; MPIR_Process.attrs.universe = MPIR_UNIVERSE_SIZE_NOT_SET; MPIR_Process.attrs.wtime_is_global = 0; /* Set the functions used to duplicate attributes. These are * when the first corresponding keyval is created */ MPIR_Process.attr_dup = 0; MPIR_Process.attr_free = 0; #ifdef HAVE_CXX_BINDING /* Set the functions used to call functions in the C++ binding * for reductions and attribute operations. These are null * until a C++ operation is defined. This allows the C code * that implements these operations to not invoke a C++ code * directly, which may force the inclusion of symbols known only * to the C++ compiler (e.g., under more non-GNU compilers, including * Solaris and IRIX). */ MPIR_Process.cxx_call_op_fn = 0; #endif #ifdef HAVE_F08_BINDING MPIR_C_MPI_UNWEIGHTED = MPI_UNWEIGHTED; MPIR_C_MPI_WEIGHTS_EMPTY = MPI_WEIGHTS_EMPTY; #endif /* This allows the device to select an alternative function for * dimsCreate */ MPIR_Process.dimsCreate = 0; /* "Allocate" from the reserved space for builtin communicators and * (partially) initialize predefined communicators. comm_parent is * intially NULL and will be allocated by the device if the process group * was started using one of the MPI_Comm_spawn functions. */ MPIR_Process.comm_world = MPIR_Comm_builtin + 0; MPII_Comm_init(MPIR_Process.comm_world); MPIR_Process.comm_world->handle = MPI_COMM_WORLD; MPIR_Process.comm_world->context_id = 0 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_world->recvcontext_id = 0 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_world->comm_kind = MPIR_COMM_KIND__INTRACOMM; /* This initialization of the comm name could be done only when * comm_get_name is called */ MPL_strncpy(MPIR_Process.comm_world->name, "MPI_COMM_WORLD", MPI_MAX_OBJECT_NAME); MPIR_Process.comm_self = MPIR_Comm_builtin + 1; MPII_Comm_init(MPIR_Process.comm_self); MPIR_Process.comm_self->handle = MPI_COMM_SELF; MPIR_Process.comm_self->context_id = 1 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_self->recvcontext_id = 1 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.comm_self->comm_kind = MPIR_COMM_KIND__INTRACOMM; MPL_strncpy(MPIR_Process.comm_self->name, "MPI_COMM_SELF", MPI_MAX_OBJECT_NAME); #ifdef MPID_NEEDS_ICOMM_WORLD MPIR_Process.icomm_world = MPIR_Comm_builtin + 2; MPII_Comm_init(MPIR_Process.icomm_world); MPIR_Process.icomm_world->handle = MPIR_ICOMM_WORLD; MPIR_Process.icomm_world->context_id = 2 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.icomm_world->recvcontext_id = 2 << MPIR_CONTEXT_PREFIX_SHIFT; MPIR_Process.icomm_world->comm_kind = MPIR_COMM_KIND__INTRACOMM; MPL_strncpy(MPIR_Process.icomm_world->name, "MPI_ICOMM_WORLD", MPI_MAX_OBJECT_NAME); /* Note that these communicators are not ready for use - MPID_Init * will setup self and world, and icomm_world if it desires it. */ #endif MPIR_Process.comm_parent = NULL; /* Setup the initial communicator list in case we have * enabled the debugger message-queue interface */ MPII_COMML_REMEMBER(MPIR_Process.comm_world); MPII_COMML_REMEMBER(MPIR_Process.comm_self); /* MPIU_Timer_pre_init(); */ /* Wait for debugger to attach if requested. */ if (MPIR_CVAR_DEBUG_HOLD) { volatile int hold = 1; while (hold) #ifdef HAVE_USLEEP usleep(100); #endif ; } #if defined(HAVE_ERROR_CHECKING) && (HAVE_ERROR_CHECKING == MPID_ERROR_LEVEL_RUNTIME) MPIR_Process.do_error_checks = MPIR_CVAR_ERROR_CHECKING; #endif /* define MPI as initialized so that we can use MPI functions within * MPID_Init if necessary */ OPA_store_int(&MPIR_Process.mpich_state, MPICH_MPI_STATE__IN_INIT); /* We can't acquire any critical sections until this point. Any * earlier the basic data structures haven't been initialized */ MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); exit_init_cs_on_failure = 1; /* create MPI_INFO_NULL object */ /* FIXME: Currently this info object is empty, we need to add data to this * as defined by the standard. */ info_ptr = MPIR_Info_builtin + 1; info_ptr->handle = MPI_INFO_ENV; MPIR_Object_set_ref(info_ptr, 1); info_ptr->next = NULL; info_ptr->key = NULL; info_ptr->value = NULL; #ifdef USE_MEMORY_TRACING MPL_trinit(); #endif /* Set the number of tag bits. The device may override this value. */ MPIR_Process.tag_bits = MPIR_TAG_BITS_DEFAULT; /* Create complete request to return in the event of immediately complete * operations. Use a SEND request to cover all possible use-cases. */ MPIR_Process.lw_req = MPIR_Request_create(MPIR_REQUEST_KIND__SEND); MPIR_ERR_CHKANDSTMT(MPIR_Process.lw_req == NULL, mpi_errno, MPIX_ERR_NOREQ, goto fn_fail, "**nomemreq"); MPIR_cc_set(&MPIR_Process.lw_req->cc, 0); mpi_errno = MPID_Init(argc, argv, required, &thread_provided, &has_args, &has_env); if (mpi_errno) MPIR_ERR_POP(mpi_errno); /* Initialize collectives infrastructure */ mpi_errno = MPII_Coll_init(); if (mpi_errno) MPIR_ERR_POP(mpi_errno); /* Set tag_ub as function of tag_bits set by the device */ MPIR_Process.attrs.tag_ub = MPIR_TAG_USABLE_BITS; /* Assert: tag_ub should be a power of 2 minus 1 */ MPIR_Assert(((unsigned) MPIR_Process. attrs.tag_ub & ((unsigned) MPIR_Process.attrs.tag_ub + 1)) == 0); /* Assert: tag_ub is at least the minimum asked for in the MPI spec */ MPIR_Assert(MPIR_Process.attrs.tag_ub >= 32767); /* Capture the level of thread support provided */ MPIR_ThreadInfo.thread_provided = thread_provided; if (provided) *provided = thread_provided; #if defined MPICH_IS_THREADED MPIR_ThreadInfo.isThreaded = (thread_provided == MPI_THREAD_MULTIPLE); #endif /* MPICH_IS_THREADED */ /* FIXME: Define these in the interface. Does Timer init belong here? */ MPII_Timer_init(MPIR_Process.comm_world->rank, MPIR_Process.comm_world->local_size); #ifdef USE_MEMORY_TRACING #ifdef MPICH_IS_THREADED MPL_trconfig(MPIR_Process.comm_world->rank, MPIR_ThreadInfo.isThreaded); #else MPL_trconfig(MPIR_Process.comm_world->rank, 0); #endif /* Indicate that we are near the end of the init step; memory * allocated already will have an id of zero; this helps * separate memory leaks in the initialization code from * leaks in the "active" code */ #endif #ifdef MPL_USE_DBG_LOGGING /* FIXME: This is a hack to handle the common case of two worlds. * If the parent comm is not NULL, we always give the world number * as "1" (false). */ #ifdef MPICH_IS_THREADED MPL_dbg_init(argc, argv, has_args, has_env, MPIR_Process.comm_parent != NULL, MPIR_Process.comm_world->rank, MPIR_ThreadInfo.isThreaded); #else MPL_dbg_init(argc, argv, has_args, has_env, MPIR_Process.comm_parent != NULL, MPIR_Process.comm_world->rank, 0); #endif MPIR_DBG_INIT = MPL_dbg_class_alloc("INIT", "init"); MPIR_DBG_PT2PT = MPL_dbg_class_alloc("PT2PT", "pt2pt"); MPIR_DBG_THREAD = MPL_dbg_class_alloc("THREAD", "thread"); MPIR_DBG_DATATYPE = MPL_dbg_class_alloc("DATATYPE", "datatype"); MPIR_DBG_HANDLE = MPL_dbg_class_alloc("HANDLE", "handle"); MPIR_DBG_COMM = MPL_dbg_class_alloc("COMM", "comm"); MPIR_DBG_BSEND = MPL_dbg_class_alloc("BSEND", "bsend"); MPIR_DBG_ERRHAND = MPL_dbg_class_alloc("ERRHAND", "errhand"); MPIR_DBG_OTHER = MPL_dbg_class_alloc("OTHER", "other"); MPIR_DBG_REQUEST = MPL_dbg_class_alloc("REQUEST", "request"); MPIR_DBG_COLL = MPL_dbg_class_alloc("COLL", "coll"); MPIR_DBG_ASSERT = MPL_dbg_class_alloc("ASSERT", "assert"); MPIR_DBG_STRING = MPL_dbg_class_alloc("STRING", "string"); #endif /* Initialize the C versions of the Fortran link-time constants. * * We now initialize the Fortran symbols from within the Fortran * interface in the routine that first needs the symbols. * This fixes a problem with symbols added by a Fortran compiler that * are not part of the C runtime environment (the Portland group * compilers would do this) */ #if defined(HAVE_FORTRAN_BINDING) && defined(HAVE_MPI_F_INIT_WORKS_WITH_C) mpirinitf_(); #endif /* FIXME: Does this need to come before the call to MPID_InitComplete? * For some debugger support, MPII_Wait_for_debugger may want to use * MPI communication routines to collect information for the debugger */ #ifdef HAVE_DEBUGGER_SUPPORT MPII_Wait_for_debugger(); #endif /* Let the device know that the rest of the init process is completed */ if (mpi_errno == MPI_SUCCESS) mpi_errno = MPID_InitCompleted(); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); /* Make fields of MPIR_Process global visible and set mpich_state * atomically so that MPI_Initialized() etc. are thread safe */ OPA_write_barrier(); OPA_store_int(&MPIR_Process.mpich_state, MPICH_MPI_STATE__POST_INIT); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ /* signal to error handling routines that core services are unavailable */ OPA_store_int(&MPIR_Process.mpich_state, MPICH_MPI_STATE__PRE_INIT); if (exit_init_cs_on_failure) { MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); } #if defined(MPICH_IS_THREADED) if (cs_initialized) { MPIR_Thread_CS_Finalize(); } #endif return mpi_errno; /* --END ERROR HANDLING-- */ }
static void getNumCPUs(void) { // // accessible cores // // // Hwloc can't tell us the number of accessible cores directly, so // get that by counting the parent cores of the accessible PUs. // // // We could seemingly use hwloc_topology_get_allowed_cpuset() to get // the set of accessible PUs here. But that seems not to reflect the // schedaffinity settings, so use hwloc_get_proc_cpubind() instead. // hwloc_cpuset_t logAccSet; CHK_ERR_ERRNO((logAccSet = hwloc_bitmap_alloc()) != NULL); if (hwloc_get_proc_cpubind(topology, getpid(), logAccSet, 0) != 0) { #ifdef __APPLE__ const int errRecoverable = (errno == ENOSYS); // no cpubind on macOS #else const int errRecoverable = 0; #endif if (errRecoverable) { hwloc_bitmap_fill(logAccSet); } else { REPORT_ERR_ERRNO(hwloc_get_proc_cpubind(topology, getpid(), logAccSet, 0) == 0); } } hwloc_bitmap_and(logAccSet, logAccSet, hwloc_topology_get_online_cpuset(topology)); hwloc_cpuset_t physAccSet; CHK_ERR_ERRNO((physAccSet = hwloc_bitmap_alloc()) != NULL); #define NEXT_PU(pu) \ hwloc_get_next_obj_inside_cpuset_by_type(topology, logAccSet, \ HWLOC_OBJ_PU, pu) for (hwloc_obj_t pu = NEXT_PU(NULL); pu != NULL; pu = NEXT_PU(pu)) { hwloc_obj_t core; CHK_ERR_ERRNO((core = hwloc_get_ancestor_obj_by_type(topology, HWLOC_OBJ_CORE, pu)) != NULL); hwloc_bitmap_set(physAccSet, core->logical_index); } #undef NEXT_PU numCPUsPhysAcc = hwloc_bitmap_weight(physAccSet); hwloc_bitmap_free(physAccSet); CHK_ERR(numCPUsPhysAcc > 0); // // all cores // numCPUsPhysAll = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_CORE); CHK_ERR(numCPUsPhysAll > 0); // // accessible PUs // numCPUsLogAcc = hwloc_bitmap_weight(logAccSet); CHK_ERR(numCPUsLogAcc > 0); hwloc_bitmap_free(logAccSet); // // all PUs // numCPUsLogAll = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU); CHK_ERR(numCPUsLogAll > 0); }