aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/kmp_affinity.cpp
diff options
context:
space:
mode:
authorJonathan Peyton <jonathan.l.peyton@intel.com>2018-12-13 23:14:24 +0000
committerJonathan Peyton <jonathan.l.peyton@intel.com>2018-12-13 23:14:24 +0000
commit09185848651b1cfab16634c40b3151ec5dad9567 (patch)
treebbc9ce7321bfe7cc7955973ab5f0bb2df93a794c /runtime/src/kmp_affinity.cpp
parent12258aa8d931d81cb7673994caa96bcc457256f8 (diff)
[OpenMP] Implement OpenMP 5.0 affinity format functionality
This patch adds the affinity format functionality introduced in OpenMP 5.0. This patch adds: Two new environment variables: OMP_DISPLAY_AFFINITY=TRUE|FALSE OMP_AFFINITY_FORMAT=<string> and Four new API: 1) omp_set_affinity_format() 2) omp_get_affinity_format() 3) omp_display_affinity() 4) omp_capture_affinity() The affinity format functionality has two ICV's associated with it: affinity-display-var (bool) and affinity-format-var (string). The affinity-display-var enables/disables the functionality through the envirable OMP_DISPLAY_AFFINITY. The affinity-format-var is a formatted string with the special field types beginning with a '%' character similar to printf For example, the affinity-format-var could be: "OMP: host:%H pid:%P OStid:%i num_threads:%N thread_num:%n affinity:{%A}" The affinity-format-var is displayed by every thread implicitly at the beginning of a parallel region when any thread's affinity has changed (including a brand new thread being spawned), or explicitly using the omp_display_affinity() API. The omp_capture_affinity() function can capture the affinity-format-var in a char buffer. And omp_set|get_affinity_format() allow the user to set|get the affinity-format-var explicitly at runtime. omp_capture_affinity() and omp_get_affinity_format() both return the number of characters needed to hold the entire string it tried to make (not including NULL character). If not enough buffer space is available, both these functions truncate their output. Differential Revision: https://reviews.llvm.org/D55148 git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349089 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'runtime/src/kmp_affinity.cpp')
-rw-r--r--runtime/src/kmp_affinity.cpp140
1 files changed, 110 insertions, 30 deletions
diff --git a/runtime/src/kmp_affinity.cpp b/runtime/src/kmp_affinity.cpp
index a9a21cf..775862e 100644
--- a/runtime/src/kmp_affinity.cpp
+++ b/runtime/src/kmp_affinity.cpp
@@ -83,55 +83,135 @@ void KMPAffinity::destroy_api() {
}
}
+#define KMP_ADVANCE_SCAN(scan) \
+ while (*scan != '\0') { \
+ scan++; \
+ }
+
// Print the affinity mask to the character array in a pretty format.
+// The format is a comma separated list of non-negative integers or integer
+// ranges: e.g., 1,2,3-5,7,9-15
+// The format can also be the string "{<empty>}" if no bits are set in mask
char *__kmp_affinity_print_mask(char *buf, int buf_len,
kmp_affin_mask_t *mask) {
+ int start = 0, finish = 0, previous = 0;
+ bool first_range;
+ KMP_ASSERT(buf);
KMP_ASSERT(buf_len >= 40);
+ KMP_ASSERT(mask);
char *scan = buf;
char *end = buf + buf_len - 1;
- // Find first element / check for empty set.
- int i;
- i = mask->begin();
- if (i == mask->end()) {
+ // Check for empty set.
+ if (mask->begin() == mask->end()) {
KMP_SNPRINTF(scan, end - scan + 1, "{<empty>}");
- while (*scan != '\0')
- scan++;
+ KMP_ADVANCE_SCAN(scan);
KMP_ASSERT(scan <= end);
return buf;
}
- KMP_SNPRINTF(scan, end - scan + 1, "{%d", i);
- while (*scan != '\0')
- scan++;
- i++;
- for (; i != mask->end(); i = mask->next(i)) {
- if (!KMP_CPU_ISSET(i, mask)) {
- continue;
+ first_range = true;
+ start = mask->begin();
+ while (1) {
+ // Find next range
+ // [start, previous] is inclusive range of contiguous bits in mask
+ for (finish = mask->next(start), previous = start;
+ finish == previous + 1 && finish != mask->end();
+ finish = mask->next(finish)) {
+ previous = finish;
}
- // Check for buffer overflow. A string of the form ",<n>" will have at most
- // 10 characters, plus we want to leave room to print ",...}" if the set is
- // too large to print for a total of 15 characters. We already left room for
- // '\0' in setting end.
- if (end - scan < 15) {
- break;
+ // The first range does not need a comma printed before it, but the rest
+ // of the ranges do need a comma beforehand
+ if (!first_range) {
+ KMP_SNPRINTF(scan, end - scan + 1, "%s", ",");
+ KMP_ADVANCE_SCAN(scan);
+ } else {
+ first_range = false;
}
- KMP_SNPRINTF(scan, end - scan + 1, ",%-d", i);
- while (*scan != '\0')
- scan++;
- }
- if (i != mask->end()) {
- KMP_SNPRINTF(scan, end - scan + 1, ",...");
- while (*scan != '\0')
- scan++;
+ // Range with three or more contiguous bits in the affinity mask
+ if (previous - start > 1) {
+ KMP_SNPRINTF(scan, end - scan + 1, "%d-%d", static_cast<int>(start),
+ static_cast<int>(previous));
+ } else {
+ // Range with one or two contiguous bits in the affinity mask
+ KMP_SNPRINTF(scan, end - scan + 1, "%d", static_cast<int>(start));
+ KMP_ADVANCE_SCAN(scan);
+ if (previous - start > 0) {
+ KMP_SNPRINTF(scan, end - scan + 1, ",%d", static_cast<int>(previous));
+ }
+ }
+ KMP_ADVANCE_SCAN(scan);
+ // Start over with new start point
+ start = finish;
+ if (start == mask->end())
+ break;
+ // Check for overflow
+ if (end - scan < 2)
+ break;
}
- KMP_SNPRINTF(scan, end - scan + 1, "}");
- while (*scan != '\0')
- scan++;
+
+ // Check for overflow
KMP_ASSERT(scan <= end);
return buf;
}
+#undef KMP_ADVANCE_SCAN
+
+// Print the affinity mask to the string buffer object in a pretty format
+// The format is a comma separated list of non-negative integers or integer
+// ranges: e.g., 1,2,3-5,7,9-15
+// The format can also be the string "{<empty>}" if no bits are set in mask
+kmp_str_buf_t *__kmp_affinity_str_buf_mask(kmp_str_buf_t *buf,
+ kmp_affin_mask_t *mask) {
+ int start = 0, finish = 0, previous = 0;
+ bool first_range;
+ KMP_ASSERT(buf);
+ KMP_ASSERT(mask);
+
+ __kmp_str_buf_clear(buf);
+
+ // Check for empty set.
+ if (mask->begin() == mask->end()) {
+ __kmp_str_buf_print(buf, "%s", "{<empty>}");
+ return buf;
+ }
+
+ first_range = true;
+ start = mask->begin();
+ while (1) {
+ // Find next range
+ // [start, previous] is inclusive range of contiguous bits in mask
+ for (finish = mask->next(start), previous = start;
+ finish == previous + 1 && finish != mask->end();
+ finish = mask->next(finish)) {
+ previous = finish;
+ }
+
+ // The first range does not need a comma printed before it, but the rest
+ // of the ranges do need a comma beforehand
+ if (!first_range) {
+ __kmp_str_buf_print(buf, "%s", ",");
+ } else {
+ first_range = false;
+ }
+ // Range with three or more contiguous bits in the affinity mask
+ if (previous - start > 1) {
+ __kmp_str_buf_print(buf, "%d-%d", static_cast<int>(start),
+ static_cast<int>(previous));
+ } else {
+ // Range with one or two contiguous bits in the affinity mask
+ __kmp_str_buf_print(buf, "%d", static_cast<int>(start));
+ if (previous - start > 0) {
+ __kmp_str_buf_print(buf, ",%d", static_cast<int>(previous));
+ }
+ }
+ // Start over with new start point
+ start = finish;
+ if (start == mask->end())
+ break;
+ }
+ return buf;
+}
void __kmp_affinity_entire_machine_mask(kmp_affin_mask_t *mask) {
KMP_CPU_ZERO(mask);