Skip to content

Commit

Permalink
[OpenMP][libomp] Add support for offline CPUs in Linux
Browse files Browse the repository at this point in the history
If some CPUs are offline, then make sure they are not included in the
fullMask even if norespect is given to KMP_AFFINITY.

Differential Revision: https://reviews.llvm.org/D112274
  • Loading branch information
jpeyton52 committed Nov 17, 2021
1 parent 9cc489a commit 1dd7971
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 5 deletions.
9 changes: 9 additions & 0 deletions openmp/runtime/src/kmp.h
Expand Up @@ -4274,6 +4274,15 @@ class kmp_safe_raii_file_t {
}
}
}
/// Instead of erroring out, return non-zero when
/// unsuccessful fopen() for any reason
int try_open(const char *filename, const char *mode) {
KMP_ASSERT(!f);
f = fopen(filename, mode);
if (!f)
return errno;
return 0;
}
/// Set the FILE* object to stdout and output there
/// No open call should happen before this call.
void set_stdout() {
Expand Down
76 changes: 73 additions & 3 deletions openmp/runtime/src/kmp_affinity.cpp
Expand Up @@ -26,6 +26,7 @@
#define HWLOC_GROUP_KIND_INTEL_DIE 104
#define HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP 220
#endif
#include <ctype.h>

// The machine topology
kmp_topology_t *__kmp_topology = nullptr;
Expand Down Expand Up @@ -1030,7 +1031,67 @@ kmp_str_buf_t *__kmp_affinity_str_buf_mask(kmp_str_buf_t *buf,
return buf;
}

void __kmp_affinity_entire_machine_mask(kmp_affin_mask_t *mask) {
// Return (possibly empty) affinity mask representing the offline CPUs
// Caller must free the mask
kmp_affin_mask_t *__kmp_affinity_get_offline_cpus() {
kmp_affin_mask_t *offline;
KMP_CPU_ALLOC(offline);
KMP_CPU_ZERO(offline);
#if KMP_OS_LINUX
int n, begin_cpu, end_cpu;
kmp_safe_raii_file_t offline_file;
auto skip_ws = [](FILE *f) {
int c;
do {
c = fgetc(f);
} while (isspace(c));
if (c != EOF)
ungetc(c, f);
};
// File contains CSV of integer ranges representing the offline CPUs
// e.g., 1,2,4-7,9,11-15
int status = offline_file.try_open("/sys/devices/system/cpu/offline", "r");
if (status != 0)
return offline;
while (!feof(offline_file)) {
skip_ws(offline_file);
n = fscanf(offline_file, "%d", &begin_cpu);
if (n != 1)
break;
skip_ws(offline_file);
int c = fgetc(offline_file);
if (c == EOF || c == ',') {
// Just single CPU
end_cpu = begin_cpu;
} else if (c == '-') {
// Range of CPUs
skip_ws(offline_file);
n = fscanf(offline_file, "%d", &end_cpu);
if (n != 1)
break;
skip_ws(offline_file);
c = fgetc(offline_file); // skip ','
} else {
// Syntax problem
break;
}
// Ensure a valid range of CPUs
if (begin_cpu < 0 || begin_cpu >= __kmp_xproc || end_cpu < 0 ||
end_cpu >= __kmp_xproc || begin_cpu > end_cpu) {
continue;
}
// Insert [begin_cpu, end_cpu] into offline mask
for (int cpu = begin_cpu; cpu <= end_cpu; ++cpu) {
KMP_CPU_SET(cpu, offline);
}
}
#endif
return offline;
}

// Return the number of available procs
int __kmp_affinity_entire_machine_mask(kmp_affin_mask_t *mask) {
int avail_proc = 0;
KMP_CPU_ZERO(mask);

#if KMP_GROUP_AFFINITY
Expand All @@ -1043,6 +1104,7 @@ void __kmp_affinity_entire_machine_mask(kmp_affin_mask_t *mask) {
int num = __kmp_GetActiveProcessorCount(group);
for (i = 0; i < num; i++) {
KMP_CPU_SET(i + group * (CHAR_BIT * sizeof(DWORD_PTR)), mask);
avail_proc++;
}
}
} else
Expand All @@ -1051,10 +1113,18 @@ void __kmp_affinity_entire_machine_mask(kmp_affin_mask_t *mask) {

{
int proc;
kmp_affin_mask_t *offline_cpus = __kmp_affinity_get_offline_cpus();
for (proc = 0; proc < __kmp_xproc; proc++) {
// Skip offline CPUs
if (KMP_CPU_ISSET(proc, offline_cpus))
continue;
KMP_CPU_SET(proc, mask);
avail_proc++;
}
KMP_CPU_FREE(offline_cpus);
}

return avail_proc;
}

// All of the __kmp_affinity_create_*_map() routines should allocate the
Expand Down Expand Up @@ -3561,8 +3631,8 @@ static void __kmp_aux_affinity_initialize(void) {
__kmp_affin_fullMask);
KMP_INFORM(InitOSProcSetNotRespect, "KMP_AFFINITY", buf);
}
__kmp_affinity_entire_machine_mask(__kmp_affin_fullMask);
__kmp_avail_proc = __kmp_xproc;
__kmp_avail_proc =
__kmp_affinity_entire_machine_mask(__kmp_affin_fullMask);
#if KMP_OS_WINDOWS
// Set the process affinity mask since threads' affinity
// masks must be subset of process mask in Windows* OS
Expand Down
8 changes: 6 additions & 2 deletions openmp/runtime/src/z_Linux_util.cpp
Expand Up @@ -1801,8 +1801,12 @@ static int __kmp_get_xproc(void) {

int r = 0;

#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
KMP_OS_OPENBSD || KMP_OS_HURD
#if KMP_OS_LINUX

__kmp_type_convert(sysconf(_SC_NPROCESSORS_CONF), &(r));

#elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_OPENBSD || \
KMP_OS_HURD

__kmp_type_convert(sysconf(_SC_NPROCESSORS_ONLN), &(r));

Expand Down

0 comments on commit 1dd7971

Please sign in to comment.