[Openmp-commits] [openmp] [OpenMP][AIX] Affinity implementation for AIX (PR #84984)
Xing Xue via Openmp-commits
openmp-commits at lists.llvm.org
Thu Mar 21 10:02:52 PDT 2024
https://github.com/xingxue-ibm updated https://github.com/llvm/llvm-project/pull/84984
>From f9da8b4e898665f15e9ba82765b8563961b002f8 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Tue, 12 Mar 2024 15:55:17 -0400
Subject: [PATCH 1/4] AIX affinity implementation.
---
openmp/runtime/src/kmp.h | 5 +-
openmp/runtime/src/kmp_affinity.cpp | 127 ++++++++++++++++++++++++++--
openmp/runtime/src/kmp_affinity.h | 72 +++++++++++++++-
openmp/runtime/src/kmp_os.h | 2 +-
openmp/runtime/src/z_Linux_util.cpp | 33 ++++++--
openmp/runtime/test/lit.cfg | 2 +-
6 files changed, 224 insertions(+), 17 deletions(-)
diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h
index 885d6636abe4a8..18ccf10fe17d0f 100644
--- a/openmp/runtime/src/kmp.h
+++ b/openmp/runtime/src/kmp.h
@@ -819,6 +819,7 @@ class KMPAffinity {
typedef KMPAffinity::Mask kmp_affin_mask_t;
extern KMPAffinity *__kmp_affinity_dispatch;
+#ifndef KMP_OS_AIX
class kmp_affinity_raii_t {
kmp_affin_mask_t *mask;
bool restored;
@@ -843,6 +844,7 @@ class kmp_affinity_raii_t {
}
~kmp_affinity_raii_t() { restore(); }
};
+#endif // !KMP_OS_AIX
// Declare local char buffers with this size for printing debug and info
// messages, using __kmp_affinity_print_mask().
@@ -3910,7 +3912,8 @@ extern void __kmp_balanced_affinity(kmp_info_t *th, int team_size);
#if KMP_WEIGHTED_ITERATIONS_SUPPORTED
extern int __kmp_get_first_osid_with_ecore(void);
#endif
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY
+#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \
+ KMP_OS_AIX
extern int kmp_set_thread_affinity_mask_initial(void);
#endif
static inline void __kmp_assign_root_init_mask() {
diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp
index 048bd174fc95a2..a6c462eb0ce221 100644
--- a/openmp/runtime/src/kmp_affinity.cpp
+++ b/openmp/runtime/src/kmp_affinity.cpp
@@ -2913,9 +2913,11 @@ static inline const char *__kmp_cpuinfo_get_envvar() {
// affinity map.
static bool __kmp_affinity_create_cpuinfo_map(int *line,
kmp_i18n_id_t *const msg_id) {
+ *msg_id = kmp_i18n_null;
+
+#ifndef KMP_OS_AIX
const char *filename = __kmp_cpuinfo_get_filename();
const char *envvar = __kmp_cpuinfo_get_envvar();
- *msg_id = kmp_i18n_null;
if (__kmp_affinity.flags.verbose) {
KMP_INFORM(AffParseFilename, "KMP_AFFINITY", filename);
@@ -2974,6 +2976,9 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
*msg_id = kmp_i18n_str_CantRewindCpuinfo;
return false;
}
+#else // KMP_OS_AIX
+ unsigned num_records = __kmp_xproc;
+#endif
// Allocate the array of records to store the proc info in. The dummy
// element at the end makes the logic in filling them out easier to code.
@@ -3003,6 +3008,7 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
INIT_PROC_INFO(threadInfo[i]);
}
+#ifndef KMP_OS_AIX
unsigned num_avail = 0;
*line = 0;
#if KMP_ARCH_S390X
@@ -3250,6 +3256,100 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
qsort(threadInfo, num_avail, sizeof(*threadInfo),
__kmp_affinity_cmp_ProcCpuInfo_phys_id);
+#else // KMP_OS_AIX
+ int smt_threads;
+ lpar_info_format1_t cpuinfo;
+ unsigned num_avail = __kmp_xproc;
+
+ if (__kmp_affinity.flags.verbose)
+ KMP_INFORM(AffParseFilename, "KMP_AFFINITY", "system info for topology");
+
+ // Get the number of SMT threads per core.
+ int retval =
+ lpar_get_info(LPAR_INFO_FORMAT1, &cpuinfo, sizeof(lpar_info_format1_t));
+ if (!retval)
+ smt_threads = cpuinfo.smt_threads;
+ else {
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+
+ // Allocate a resource set containing available system resourses.
+ rsethandle_t sys_rset = rs_alloc(RS_SYSTEM);
+ if (sys_rset == NULL) {
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+ // Allocate a resource set for the SRAD info.
+ rsethandle_t srad = rs_alloc(RS_EMPTY);
+ if (srad == NULL) {
+ rs_free(sys_rset);
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+
+ // Get the SRAD system detail level.
+ int sradsdl = rs_getinfo(NULL, R_SRADSDL, 0);
+ if (sradsdl < 0) {
+ rs_free(sys_rset);
+ rs_free(srad);
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+ // Get the number of RADs at that SRAD SDL.
+ int num_rads = rs_numrads(sys_rset, sradsdl, 0);
+ if (num_rads < 0) {
+ rs_free(sys_rset);
+ rs_free(srad);
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+
+ // Get the maximum number of procs that may be contained in a resource set.
+ int max_procs = rs_getinfo(NULL, R_MAXPROCS, 0);
+ if (max_procs < 0) {
+ rs_free(sys_rset);
+ rs_free(srad);
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+
+ int cur_rad = 0;
+ int num_set = 0;
+ for (int srad_idx = 0; cur_rad < num_rads && srad_idx < VMI_MAXRADS;
+ ++srad_idx) {
+ // Check if the SRAD is available in the RSET.
+ if (rs_getrad(sys_rset, srad, sradsdl, srad_idx, 0) < 0)
+ continue;
+
+ for (int cpu = 0; cpu < max_procs; cpu++) {
+ // Set the info for the cpu if it is in the SRAD.
+ if (rs_op(RS_TESTRESOURCE, srad, NULL, R_PROCS, cpu)) {
+ threadInfo[cpu][osIdIndex] = cpu;
+ threadInfo[cpu][pkgIdIndex] = cur_rad;
+ threadInfo[cpu][coreIdIndex] = cpu / smt_threads;
+ ++num_set;
+ if (num_set >= num_avail) {
+ // Done if all available CPUs have been set.
+ break;
+ }
+ }
+ }
+ ++cur_rad;
+ }
+ rs_free(sys_rset);
+ rs_free(srad);
+
+ // The topology is already sorted.
+
+#endif // KMP_OS_AIX
+
// The table is now sorted by pkgId / coreId / threadId, but we really don't
// know the radix of any of the fields. pkgId's may be sparsely assigned among
// the chips on a system. Although coreId's are usually assigned
@@ -4445,7 +4545,7 @@ static bool __kmp_aux_affinity_initialize_topology(kmp_affinity_t &affinity) {
}
#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
-#if KMP_OS_LINUX
+#if KMP_OS_LINUX || KMP_OS_AIX
if (!success) {
int line = 0;
success = __kmp_affinity_create_cpuinfo_map(&line, &msg_id);
@@ -4841,7 +4941,12 @@ void __kmp_affinity_uninitialize(void) {
}
if (__kmp_affin_origMask != NULL) {
if (KMP_AFFINITY_CAPABLE()) {
+#ifdef KMP_OS_AIX
+ // Uninitialize by unbinding the thread.
+ bindprocessor(BINDTHREAD, thread_self(), PROCESSOR_CLASS_ANY);
+#else
__kmp_set_system_affinity(__kmp_affin_origMask, FALSE);
+#endif
}
KMP_CPU_FREE(__kmp_affin_origMask);
__kmp_affin_origMask = NULL;
@@ -5015,7 +5120,10 @@ void __kmp_affinity_bind_init_mask(int gtid) {
__kmp_set_system_affinity(th->th.th_affin_mask, FALSE);
} else
#endif
+#ifndef KMP_OS_AIX
+ // Do not set the full mask as the init mask on AIX.
__kmp_set_system_affinity(th->th.th_affin_mask, TRUE);
+#endif
}
void __kmp_affinity_bind_place(int gtid) {
@@ -5128,7 +5236,7 @@ int __kmp_aux_set_affinity(void **mask) {
int __kmp_aux_get_affinity(void **mask) {
int gtid;
int retval;
-#if KMP_OS_WINDOWS || KMP_DEBUG
+#if KMP_OS_WINDOWS || KMP_OS_AIX || KMP_DEBUG
kmp_info_t *th;
#endif
if (!KMP_AFFINITY_CAPABLE()) {
@@ -5136,7 +5244,7 @@ int __kmp_aux_get_affinity(void **mask) {
}
gtid = __kmp_entry_gtid();
-#if KMP_OS_WINDOWS || KMP_DEBUG
+#if KMP_OS_WINDOWS || KMP_OS_AIX || KMP_DEBUG
th = __kmp_threads[gtid];
#else
(void)gtid; // unused variable
@@ -5159,7 +5267,7 @@ int __kmp_aux_get_affinity(void **mask) {
}
}
-#if !KMP_OS_WINDOWS
+#if !KMP_OS_WINDOWS && !KMP_OS_AIX
retval = __kmp_get_system_affinity((kmp_affin_mask_t *)(*mask), FALSE);
KA_TRACE(
@@ -5179,7 +5287,7 @@ int __kmp_aux_get_affinity(void **mask) {
KMP_CPU_COPY((kmp_affin_mask_t *)(*mask), th->th.th_affin_mask);
return 0;
-#endif /* KMP_OS_WINDOWS */
+#endif /* !KMP_OS_WINDOWS && !KMP_OS_AIX */
}
int __kmp_aux_get_affinity_max_proc() {
@@ -5561,7 +5669,8 @@ void __kmp_balanced_affinity(kmp_info_t *th, int nthreads) {
}
}
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY
+#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \
+ KMP_OS_AIX
// We don't need this entry for Windows because
// there is GetProcessAffinityMask() api
//
@@ -5596,7 +5705,11 @@ extern "C"
"set full mask for thread %d\n",
gtid));
KMP_DEBUG_ASSERT(__kmp_affin_fullMask != NULL);
+#ifdef KMP_OS_AIX
+ return bindprocessor(BINDTHREAD, thread_self(), PROCESSOR_CLASS_ANY);
+#else
return __kmp_set_system_affinity(__kmp_affin_fullMask, FALSE);
+#endif
}
#endif
diff --git a/openmp/runtime/src/kmp_affinity.h b/openmp/runtime/src/kmp_affinity.h
index 1c7db2f59943f8..3e16f7c289b062 100644
--- a/openmp/runtime/src/kmp_affinity.h
+++ b/openmp/runtime/src/kmp_affinity.h
@@ -191,7 +191,8 @@ class KMPHwlocAffinity : public KMPAffinity {
};
#endif /* KMP_USE_HWLOC */
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY
+#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \
+ KMP_OS_AIX
#if KMP_OS_LINUX
/* On some of the older OS's that we build on, these constants aren't present
in <asm/unistd.h> #included from <sys.syscall.h>. They must be the same on
@@ -317,6 +318,10 @@ class KMPHwlocAffinity : public KMPAffinity {
#elif KMP_OS_NETBSD
#include <pthread.h>
#include <sched.h>
+#elif KMP_OS_AIX
+#include <sys/dr.h>
+#include <sys/rset.h>
+#define VMI_MAXRADS 64 // Maximum number of RADs allowed by AIX.
#endif
class KMPNativeAffinity : public KMPAffinity {
class Mask : public KMPAffinity::Mask {
@@ -404,6 +409,7 @@ class KMPNativeAffinity : public KMPAffinity {
++retval;
return retval;
}
+#ifndef KMP_OS_AIX
int get_system_affinity(bool abort_on_error) override {
KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
"Illegal get affinity operation when not capable");
@@ -446,6 +452,68 @@ class KMPNativeAffinity : public KMPAffinity {
}
return error;
}
+#elif KMP_OS_AIX
+ // On AIX, we don't have a way to get CPU(s) a thread is bound to.
+ // This routine is only used to get the full mask.
+ int get_system_affinity(bool abort_on_error) override {
+ KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
+ "Illegal get affinity operation when not capable");
+
+ // Set the mask with all CPUs that are available.
+ for (int i = 0; i < __kmp_xproc; ++i)
+ KMP_CPU_SET(i, this);
+ return 0;
+ }
+ int set_system_affinity(bool abort_on_error) const override {
+ KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
+
+ "Illegal set affinity operation when not capable");
+
+ int location;
+ int gtid = __kmp_entry_gtid();
+ int tid = thread_self();
+
+ // Unbind the thread if it was bound to any processors before so that
+ // we can bind the thread to CPUs specified by the mask not others.
+ int retval = bindprocessor(BINDTHREAD, tid, PROCESSOR_CLASS_ANY);
+
+ // On AIX, we can only bind to one instead of a set of CPUs with the
+ // bindprocessor() system call.
+ KMP_CPU_SET_ITERATE(location, this) {
+ if (KMP_CPU_ISSET(location, this)) {
+ retval = bindprocessor(BINDTHREAD, tid, location);
+ if (retval == -1 && errno == 1) {
+ rsid_t rsid;
+ rsethandle_t rsh;
+ // Put something in rsh to prevent compiler warning
+ // about uninitalized use
+ rsh = rs_alloc(RS_EMPTY);
+ rsid.at_pid = getpid();
+ if (RS_DEFAULT_RSET != ra_getrset(R_PROCESS, rsid, 0, rsh)) {
+ retval = ra_detachrset(R_PROCESS, rsid, 0);
+ retval = bindprocessor(BINDTHREAD, tid, location);
+ }
+ }
+ if (retval == 0) {
+ KA_TRACE(10, ("__kmp_set_system_affinity: Done binding "
+ "T#%d to cpu=%d.\n",
+ gtid, location));
+ continue;
+ }
+ int error = errno;
+ if (abort_on_error) {
+ __kmp_fatal(KMP_MSG(FunctionError, "bindprocessor()"),
+ KMP_ERR(error), __kmp_msg_null);
+ KA_TRACE(10, ("__kmp_set_system_affinity: Error binding "
+ "T#%d to cpu=%d, errno=%d.\n",
+ gtid, location, error));
+ return error;
+ }
+ }
+ }
+ return 0;
+ }
+#endif // !KMP_OS_AIX
};
void determine_capable(const char *env_var) override {
__kmp_affinity_determine_capable(env_var);
@@ -475,7 +543,7 @@ class KMPNativeAffinity : public KMPAffinity {
api_type get_api_type() const override { return NATIVE_OS; }
};
#endif /* KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY \
- */
+ || KMP_OS_AIX */
#if KMP_OS_WINDOWS
class KMPNativeAffinity : public KMPAffinity {
diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h
index 63da9e5fa15d1c..a628070c882ad7 100644
--- a/openmp/runtime/src/kmp_os.h
+++ b/openmp/runtime/src/kmp_os.h
@@ -76,7 +76,7 @@
#endif
#if (KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
- KMP_OS_DRAGONFLY) && \
+ KMP_OS_DRAGONFLY || KMP_OS_AIX) && \
!KMP_OS_WASI
#define KMP_AFFINITY_SUPPORTED 1
#if KMP_OS_WINDOWS && KMP_ARCH_X86_64
diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp
index d751a417331cee..3fdea2dc4f480e 100644
--- a/openmp/runtime/src/z_Linux_util.cpp
+++ b/openmp/runtime/src/z_Linux_util.cpp
@@ -125,7 +125,8 @@ static void __kmp_print_cond(char *buffer, kmp_cond_align_t *cond) {
}
#endif
-#if ((KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY) && \
+#if ((KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \
+ KMP_OS_AIX) && \
KMP_AFFINITY_SUPPORTED)
/* Affinity support */
@@ -142,6 +143,8 @@ void __kmp_affinity_bind_thread(int which) {
KMP_CPU_FREE_FROM_STACK(mask);
}
+#ifndef KMP_OS_AIX
+
/* Determine if we can access affinity functionality on this version of
* Linux* OS by checking __NR_sched_{get,set}affinity system calls, and set
* __kmp_affin_mask_size to the appropriate value (0 means not capable). */
@@ -272,7 +275,25 @@ void __kmp_affinity_determine_capable(const char *env_var) {
}
}
-#endif // KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED
+#elif KMP_OS_AIX
+void __kmp_affinity_determine_capable(const char *env_var) {
+ // All versions of AIX support bindprocessor().
+
+ size_t mask_size = __kmp_xproc / CHAR_BIT;
+ if (__kmp_xproc % CHAR_BIT)
+ ++mask_size;
+
+ KMP_AFFINITY_ENABLE(mask_size);
+ KA_TRACE(10,
+ ("__kmp_affinity_determine_capable: "
+ "AIX OS affinity interface bindprocessor functional (mask size = "
+ "%" KMP_SIZE_T_SPEC ").\n",
+ __kmp_affin_mask_size));
+}
+
+#endif // KMP_OS_AIX
+#endif // (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
+ KMP_OS_DRAGONFLY || KMP_OS_AIX) && KMP_AFFINITY_SUPPORTED
#if KMP_USE_FUTEX
@@ -501,7 +522,7 @@ static void *__kmp_launch_worker(void *thr) {
#endif /* KMP_BLOCK_SIGNALS */
void *exit_val;
#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
- KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS
+ KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_AIX
void *volatile padding = 0;
#endif
int gtid;
@@ -550,7 +571,7 @@ static void *__kmp_launch_worker(void *thr) {
#endif /* KMP_BLOCK_SIGNALS */
#if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
- KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS
+ KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_AIX
if (__kmp_stkoffset > 0 && gtid > 0) {
padding = KMP_ALLOCA(gtid * __kmp_stkoffset);
(void)padding;
@@ -1268,7 +1289,8 @@ static void __kmp_atfork_child(void) {
++__kmp_fork_count;
#if KMP_AFFINITY_SUPPORTED
-#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY
+#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \
+ KMP_OS_AIX
// reset the affinity in the child to the initial thread
// affinity in the parent
kmp_set_thread_affinity_mask_initial();
@@ -2325,6 +2347,7 @@ int __kmp_is_address_mapped(void *addr) {
found = (int)addr < (__builtin_wasm_memory_size(0) * PAGESIZE);
#elif KMP_OS_AIX
+ (void)rc;
// FIXME(AIX): Implement this
found = 1;
diff --git a/openmp/runtime/test/lit.cfg b/openmp/runtime/test/lit.cfg
index a3456063c10fc6..e27e52bb4289b9 100644
--- a/openmp/runtime/test/lit.cfg
+++ b/openmp/runtime/test/lit.cfg
@@ -129,7 +129,7 @@ if config.operating_system == 'NetBSD':
if config.operating_system == 'Darwin':
config.available_features.add("darwin")
-if config.operating_system in ['Windows', 'Linux', 'FreeBSD', 'NetBSD', 'DragonFly']:
+if config.operating_system in ['Windows', 'Linux', 'FreeBSD', 'NetBSD', 'DragonFly', 'AIX']:
config.available_features.add('affinity')
if config.operating_system in ['Linux']:
>From 9ba206e809f95d055a9a2932d4ee15f183e9ce40 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Thu, 14 Mar 2024 13:25:40 -0400
Subject: [PATCH 2/4] Fix the calculation of the mask size.
---
openmp/runtime/src/z_Linux_util.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp
index 3fdea2dc4f480e..6dc5ae625a5c1d 100644
--- a/openmp/runtime/src/z_Linux_util.cpp
+++ b/openmp/runtime/src/z_Linux_util.cpp
@@ -280,9 +280,14 @@ void __kmp_affinity_determine_capable(const char *env_var) {
// All versions of AIX support bindprocessor().
size_t mask_size = __kmp_xproc / CHAR_BIT;
+ // Round up to byte boundary.
if (__kmp_xproc % CHAR_BIT)
++mask_size;
+ // Round up to the mask_size_type boundary.
+ if (mask_size % sizeof(__kmp_affin_mask_size))
+ mask_size += sizeof(__kmp_affin_mask_size) -
+ mask_size % sizeof(__kmp_affin_mask_size);
KMP_AFFINITY_ENABLE(mask_size);
KA_TRACE(10,
("__kmp_affinity_determine_capable: "
>From 8e8f0d34d6d10c1c1b9c87dc4973a04f2d138c8e Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Fri, 15 Mar 2024 11:04:40 -0400
Subject: [PATCH 3/4] Addressed comments: put the AIX code to before Linux's.
---
openmp/runtime/src/kmp_affinity.cpp | 198 ++++++++++++++--------------
openmp/runtime/src/kmp_affinity.h | 90 ++++++-------
openmp/runtime/src/z_Linux_util.cpp | 45 ++++---
3 files changed, 166 insertions(+), 167 deletions(-)
diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp
index a6c462eb0ce221..20e68b4f064f1f 100644
--- a/openmp/runtime/src/kmp_affinity.cpp
+++ b/openmp/runtime/src/kmp_affinity.cpp
@@ -2915,7 +2915,9 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
kmp_i18n_id_t *const msg_id) {
*msg_id = kmp_i18n_null;
-#ifndef KMP_OS_AIX
+#if KMP_OS_AIX
+ unsigned num_records = __kmp_xproc;
+#else
const char *filename = __kmp_cpuinfo_get_filename();
const char *envvar = __kmp_cpuinfo_get_envvar();
@@ -2976,9 +2978,7 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
*msg_id = kmp_i18n_str_CantRewindCpuinfo;
return false;
}
-#else // KMP_OS_AIX
- unsigned num_records = __kmp_xproc;
-#endif
+#endif // KMP_OS_AIX
// Allocate the array of records to store the proc info in. The dummy
// element at the end makes the logic in filling them out easier to code.
@@ -3008,7 +3008,99 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
INIT_PROC_INFO(threadInfo[i]);
}
-#ifndef KMP_OS_AIX
+#if KMP_OS_AIX
+ int smt_threads;
+ lpar_info_format1_t cpuinfo;
+ unsigned num_avail = __kmp_xproc;
+
+ if (__kmp_affinity.flags.verbose)
+ KMP_INFORM(AffParseFilename, "KMP_AFFINITY", "system info for topology");
+
+ // Get the number of SMT threads per core.
+ int retval =
+ lpar_get_info(LPAR_INFO_FORMAT1, &cpuinfo, sizeof(lpar_info_format1_t));
+ if (!retval)
+ smt_threads = cpuinfo.smt_threads;
+ else {
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+
+ // Allocate a resource set containing available system resourses.
+ rsethandle_t sys_rset = rs_alloc(RS_SYSTEM);
+ if (sys_rset == NULL) {
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+ // Allocate a resource set for the SRAD info.
+ rsethandle_t srad = rs_alloc(RS_EMPTY);
+ if (srad == NULL) {
+ rs_free(sys_rset);
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+
+ // Get the SRAD system detail level.
+ int sradsdl = rs_getinfo(NULL, R_SRADSDL, 0);
+ if (sradsdl < 0) {
+ rs_free(sys_rset);
+ rs_free(srad);
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+ // Get the number of RADs at that SRAD SDL.
+ int num_rads = rs_numrads(sys_rset, sradsdl, 0);
+ if (num_rads < 0) {
+ rs_free(sys_rset);
+ rs_free(srad);
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+
+ // Get the maximum number of procs that may be contained in a resource set.
+ int max_procs = rs_getinfo(NULL, R_MAXPROCS, 0);
+ if (max_procs < 0) {
+ rs_free(sys_rset);
+ rs_free(srad);
+ CLEANUP_THREAD_INFO;
+ *msg_id = kmp_i18n_str_UnknownTopology;
+ return false;
+ }
+
+ int cur_rad = 0;
+ int num_set = 0;
+ for (int srad_idx = 0; cur_rad < num_rads && srad_idx < VMI_MAXRADS;
+ ++srad_idx) {
+ // Check if the SRAD is available in the RSET.
+ if (rs_getrad(sys_rset, srad, sradsdl, srad_idx, 0) < 0)
+ continue;
+
+ for (int cpu = 0; cpu < max_procs; cpu++) {
+ // Set the info for the cpu if it is in the SRAD.
+ if (rs_op(RS_TESTRESOURCE, srad, NULL, R_PROCS, cpu)) {
+ threadInfo[cpu][osIdIndex] = cpu;
+ threadInfo[cpu][pkgIdIndex] = cur_rad;
+ threadInfo[cpu][coreIdIndex] = cpu / smt_threads;
+ ++num_set;
+ if (num_set >= num_avail) {
+ // Done if all available CPUs have been set.
+ break;
+ }
+ }
+ }
+ ++cur_rad;
+ }
+ rs_free(sys_rset);
+ rs_free(srad);
+
+ // The topology is already sorted.
+
+#else // !KMP_OS_AIX
unsigned num_avail = 0;
*line = 0;
#if KMP_ARCH_S390X
@@ -3256,98 +3348,6 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line,
qsort(threadInfo, num_avail, sizeof(*threadInfo),
__kmp_affinity_cmp_ProcCpuInfo_phys_id);
-#else // KMP_OS_AIX
- int smt_threads;
- lpar_info_format1_t cpuinfo;
- unsigned num_avail = __kmp_xproc;
-
- if (__kmp_affinity.flags.verbose)
- KMP_INFORM(AffParseFilename, "KMP_AFFINITY", "system info for topology");
-
- // Get the number of SMT threads per core.
- int retval =
- lpar_get_info(LPAR_INFO_FORMAT1, &cpuinfo, sizeof(lpar_info_format1_t));
- if (!retval)
- smt_threads = cpuinfo.smt_threads;
- else {
- CLEANUP_THREAD_INFO;
- *msg_id = kmp_i18n_str_UnknownTopology;
- return false;
- }
-
- // Allocate a resource set containing available system resourses.
- rsethandle_t sys_rset = rs_alloc(RS_SYSTEM);
- if (sys_rset == NULL) {
- CLEANUP_THREAD_INFO;
- *msg_id = kmp_i18n_str_UnknownTopology;
- return false;
- }
- // Allocate a resource set for the SRAD info.
- rsethandle_t srad = rs_alloc(RS_EMPTY);
- if (srad == NULL) {
- rs_free(sys_rset);
- CLEANUP_THREAD_INFO;
- *msg_id = kmp_i18n_str_UnknownTopology;
- return false;
- }
-
- // Get the SRAD system detail level.
- int sradsdl = rs_getinfo(NULL, R_SRADSDL, 0);
- if (sradsdl < 0) {
- rs_free(sys_rset);
- rs_free(srad);
- CLEANUP_THREAD_INFO;
- *msg_id = kmp_i18n_str_UnknownTopology;
- return false;
- }
- // Get the number of RADs at that SRAD SDL.
- int num_rads = rs_numrads(sys_rset, sradsdl, 0);
- if (num_rads < 0) {
- rs_free(sys_rset);
- rs_free(srad);
- CLEANUP_THREAD_INFO;
- *msg_id = kmp_i18n_str_UnknownTopology;
- return false;
- }
-
- // Get the maximum number of procs that may be contained in a resource set.
- int max_procs = rs_getinfo(NULL, R_MAXPROCS, 0);
- if (max_procs < 0) {
- rs_free(sys_rset);
- rs_free(srad);
- CLEANUP_THREAD_INFO;
- *msg_id = kmp_i18n_str_UnknownTopology;
- return false;
- }
-
- int cur_rad = 0;
- int num_set = 0;
- for (int srad_idx = 0; cur_rad < num_rads && srad_idx < VMI_MAXRADS;
- ++srad_idx) {
- // Check if the SRAD is available in the RSET.
- if (rs_getrad(sys_rset, srad, sradsdl, srad_idx, 0) < 0)
- continue;
-
- for (int cpu = 0; cpu < max_procs; cpu++) {
- // Set the info for the cpu if it is in the SRAD.
- if (rs_op(RS_TESTRESOURCE, srad, NULL, R_PROCS, cpu)) {
- threadInfo[cpu][osIdIndex] = cpu;
- threadInfo[cpu][pkgIdIndex] = cur_rad;
- threadInfo[cpu][coreIdIndex] = cpu / smt_threads;
- ++num_set;
- if (num_set >= num_avail) {
- // Done if all available CPUs have been set.
- break;
- }
- }
- }
- ++cur_rad;
- }
- rs_free(sys_rset);
- rs_free(srad);
-
- // The topology is already sorted.
-
#endif // KMP_OS_AIX
// The table is now sorted by pkgId / coreId / threadId, but we really don't
@@ -4941,7 +4941,7 @@ void __kmp_affinity_uninitialize(void) {
}
if (__kmp_affin_origMask != NULL) {
if (KMP_AFFINITY_CAPABLE()) {
-#ifdef KMP_OS_AIX
+#if KMP_OS_AIX
// Uninitialize by unbinding the thread.
bindprocessor(BINDTHREAD, thread_self(), PROCESSOR_CLASS_ANY);
#else
@@ -5705,7 +5705,7 @@ extern "C"
"set full mask for thread %d\n",
gtid));
KMP_DEBUG_ASSERT(__kmp_affin_fullMask != NULL);
-#ifdef KMP_OS_AIX
+#if KMP_OS_AIX
return bindprocessor(BINDTHREAD, thread_self(), PROCESSOR_CLASS_ANY);
#else
return __kmp_set_system_affinity(__kmp_affin_fullMask, FALSE);
diff --git a/openmp/runtime/src/kmp_affinity.h b/openmp/runtime/src/kmp_affinity.h
index 3e16f7c289b062..74ecd834304cca 100644
--- a/openmp/runtime/src/kmp_affinity.h
+++ b/openmp/runtime/src/kmp_affinity.h
@@ -409,50 +409,7 @@ class KMPNativeAffinity : public KMPAffinity {
++retval;
return retval;
}
-#ifndef KMP_OS_AIX
- int get_system_affinity(bool abort_on_error) override {
- KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
- "Illegal get affinity operation when not capable");
-#if KMP_OS_LINUX
- long retval =
- syscall(__NR_sched_getaffinity, 0, __kmp_affin_mask_size, mask);
-#elif KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY
- int r = pthread_getaffinity_np(pthread_self(), __kmp_affin_mask_size,
- reinterpret_cast<cpuset_t *>(mask));
- int retval = (r == 0 ? 0 : -1);
-#endif
- if (retval >= 0) {
- return 0;
- }
- int error = errno;
- if (abort_on_error) {
- __kmp_fatal(KMP_MSG(FunctionError, "pthread_getaffinity_np()"),
- KMP_ERR(error), __kmp_msg_null);
- }
- return error;
- }
- int set_system_affinity(bool abort_on_error) const override {
- KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
- "Illegal set affinity operation when not capable");
-#if KMP_OS_LINUX
- long retval =
- syscall(__NR_sched_setaffinity, 0, __kmp_affin_mask_size, mask);
-#elif KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY
- int r = pthread_setaffinity_np(pthread_self(), __kmp_affin_mask_size,
- reinterpret_cast<cpuset_t *>(mask));
- int retval = (r == 0 ? 0 : -1);
-#endif
- if (retval >= 0) {
- return 0;
- }
- int error = errno;
- if (abort_on_error) {
- __kmp_fatal(KMP_MSG(FunctionError, "pthread_setaffinity_np()"),
- KMP_ERR(error), __kmp_msg_null);
- }
- return error;
- }
-#elif KMP_OS_AIX
+#if KMP_OS_AIX
// On AIX, we don't have a way to get CPU(s) a thread is bound to.
// This routine is only used to get the full mask.
int get_system_affinity(bool abort_on_error) override {
@@ -513,7 +470,50 @@ class KMPNativeAffinity : public KMPAffinity {
}
return 0;
}
-#endif // !KMP_OS_AIX
+#else // !KMP_OS_AIX
+ int get_system_affinity(bool abort_on_error) override {
+ KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
+ "Illegal get affinity operation when not capable");
+#if KMP_OS_LINUX
+ long retval =
+ syscall(__NR_sched_getaffinity, 0, __kmp_affin_mask_size, mask);
+#elif KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY
+ int r = pthread_getaffinity_np(pthread_self(), __kmp_affin_mask_size,
+ reinterpret_cast<cpuset_t *>(mask));
+ int retval = (r == 0 ? 0 : -1);
+#endif
+ if (retval >= 0) {
+ return 0;
+ }
+ int error = errno;
+ if (abort_on_error) {
+ __kmp_fatal(KMP_MSG(FunctionError, "pthread_getaffinity_np()"),
+ KMP_ERR(error), __kmp_msg_null);
+ }
+ return error;
+ }
+ int set_system_affinity(bool abort_on_error) const override {
+ KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
+ "Illegal set affinity operation when not capable");
+#if KMP_OS_LINUX
+ long retval =
+ syscall(__NR_sched_setaffinity, 0, __kmp_affin_mask_size, mask);
+#elif KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY
+ int r = pthread_setaffinity_np(pthread_self(), __kmp_affin_mask_size,
+ reinterpret_cast<cpuset_t *>(mask));
+ int retval = (r == 0 ? 0 : -1);
+#endif
+ if (retval >= 0) {
+ return 0;
+ }
+ int error = errno;
+ if (abort_on_error) {
+ __kmp_fatal(KMP_MSG(FunctionError, "pthread_setaffinity_np()"),
+ KMP_ERR(error), __kmp_msg_null);
+ }
+ return error;
+ }
+#endif // KMP_OS_AIX
};
void determine_capable(const char *env_var) override {
__kmp_affinity_determine_capable(env_var);
diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp
index 6dc5ae625a5c1d..29db9d008a49b3 100644
--- a/openmp/runtime/src/z_Linux_util.cpp
+++ b/openmp/runtime/src/z_Linux_util.cpp
@@ -143,7 +143,28 @@ void __kmp_affinity_bind_thread(int which) {
KMP_CPU_FREE_FROM_STACK(mask);
}
-#ifndef KMP_OS_AIX
+#if KMP_OS_AIX
+void __kmp_affinity_determine_capable(const char *env_var) {
+ // All versions of AIX support bindprocessor().
+
+ size_t mask_size = __kmp_xproc / CHAR_BIT;
+ // Round up to byte boundary.
+ if (__kmp_xproc % CHAR_BIT)
+ ++mask_size;
+
+ // Round up to the mask_size_type boundary.
+ if (mask_size % sizeof(__kmp_affin_mask_size))
+ mask_size += sizeof(__kmp_affin_mask_size) -
+ mask_size % sizeof(__kmp_affin_mask_size);
+ KMP_AFFINITY_ENABLE(mask_size);
+ KA_TRACE(10,
+ ("__kmp_affinity_determine_capable: "
+ "AIX OS affinity interface bindprocessor functional (mask size = "
+ "%" KMP_SIZE_T_SPEC ").\n",
+ __kmp_affin_mask_size));
+}
+
+#else // !KMP_OS_AIX
/* Determine if we can access affinity functionality on this version of
* Linux* OS by checking __NR_sched_{get,set}affinity system calls, and set
@@ -274,28 +295,6 @@ void __kmp_affinity_determine_capable(const char *env_var) {
KMP_WARNING(AffCantGetMaskSize, env_var);
}
}
-
-#elif KMP_OS_AIX
-void __kmp_affinity_determine_capable(const char *env_var) {
- // All versions of AIX support bindprocessor().
-
- size_t mask_size = __kmp_xproc / CHAR_BIT;
- // Round up to byte boundary.
- if (__kmp_xproc % CHAR_BIT)
- ++mask_size;
-
- // Round up to the mask_size_type boundary.
- if (mask_size % sizeof(__kmp_affin_mask_size))
- mask_size += sizeof(__kmp_affin_mask_size) -
- mask_size % sizeof(__kmp_affin_mask_size);
- KMP_AFFINITY_ENABLE(mask_size);
- KA_TRACE(10,
- ("__kmp_affinity_determine_capable: "
- "AIX OS affinity interface bindprocessor functional (mask size = "
- "%" KMP_SIZE_T_SPEC ").\n",
- __kmp_affin_mask_size));
-}
-
#endif // KMP_OS_AIX
#endif // (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || \
KMP_OS_DRAGONFLY || KMP_OS_AIX) && KMP_AFFINITY_SUPPORTED
>From 2c7b4347b524555e19bd0be8c5d956ab1b35d9ca Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Thu, 21 Mar 2024 13:01:24 -0400
Subject: [PATCH 4/4] Addressed comments. * Update the comment of function
__kmp_affinity_create_cpuinfo_map() * Avoid compiler warning on unused
argument abort_on_error of get_system_affinity
---
openmp/runtime/src/kmp_affinity.cpp | 3 ++-
openmp/runtime/src/kmp_affinity.h | 2 ++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp
index 20e68b4f064f1f..b574dbbaf54f3d 100644
--- a/openmp/runtime/src/kmp_affinity.cpp
+++ b/openmp/runtime/src/kmp_affinity.cpp
@@ -2910,7 +2910,8 @@ static inline const char *__kmp_cpuinfo_get_envvar() {
}
// Parse /proc/cpuinfo (or an alternate file in the same format) to obtain the
-// affinity map.
+// affinity map. On AIX, the map is obtained through system SRAD (Scheduler
+// Resource Allocation Domain).
static bool __kmp_affinity_create_cpuinfo_map(int *line,
kmp_i18n_id_t *const msg_id) {
*msg_id = kmp_i18n_null;
diff --git a/openmp/runtime/src/kmp_affinity.h b/openmp/runtime/src/kmp_affinity.h
index 74ecd834304cca..7efc090f8863d9 100644
--- a/openmp/runtime/src/kmp_affinity.h
+++ b/openmp/runtime/src/kmp_affinity.h
@@ -416,6 +416,8 @@ class KMPNativeAffinity : public KMPAffinity {
KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
"Illegal get affinity operation when not capable");
+ (void)abort_on_error;
+
// Set the mask with all CPUs that are available.
for (int i = 0; i < __kmp_xproc; ++i)
KMP_CPU_SET(i, this);
More information about the Openmp-commits
mailing list