1 | // RUN: %libomp-compile |
2 | // RUN: env OMP_PROC_BIND=close OMP_PLACES=threads %libomp-run |
3 | // RUN: env OMP_PROC_BIND=close OMP_PLACES=cores %libomp-run |
4 | // RUN: env OMP_PROC_BIND=close OMP_PLACES=sockets %libomp-run |
5 | // RUN: env KMP_AFFINITY=compact %libomp-run |
6 | // RUN: env KMP_AFFINITY=scatter %libomp-run |
7 | // REQUIRES: affinity |
8 | |
9 | #include <stdio.h> |
10 | #include <stdlib.h> |
11 | #include <string.h> |
12 | #include <omp.h> |
13 | |
14 | #define XSTR(x) #x |
15 | #define STR(x) XSTR(x) |
16 | |
17 | #define streqls(s1, s2) (!strcmp(s1, s2)) |
18 | |
19 | #define check(condition) \ |
20 | if (!(condition)) { \ |
21 | fprintf(stderr, "error: %s: %d: " STR(condition) "\n", __FILE__, \ |
22 | __LINE__); \ |
23 | exit(1); \ |
24 | } |
25 | |
26 | #define DEBUG 0 |
27 | |
28 | #if DEBUG |
29 | #include <stdarg.h> |
30 | #endif |
31 | |
32 | #define BUFFER_SIZE 1024 |
33 | |
34 | char buf[BUFFER_SIZE]; |
35 | #pragma omp threadprivate(buf) |
36 | |
37 | static int debug_printf(const char* format, ...) { |
38 | int retval = 0; |
39 | #if DEBUG |
40 | va_list args; |
41 | va_start(args, format); |
42 | retval = vprintf(format, args); |
43 | va_end(args); |
44 | #endif |
45 | return retval; |
46 | } |
47 | |
48 | static void display_affinity_environment() { |
49 | #if DEBUG |
50 | printf("Affinity Environment:\n" ); |
51 | printf(" OMP_PROC_BIND=%s\n" , getenv("OMP_PROC_BIND" )); |
52 | printf(" OMP_PLACES=%s\n" , getenv("OMP_PLACES" )); |
53 | printf(" KMP_AFFINITY=%s\n" , getenv("KMP_AFFINITY" )); |
54 | #endif |
55 | } |
56 | |
57 | // Reads in a list of integers into ids array (not going past ids_size) |
58 | // e.g., if affinity = "0-4,6,8-10,14,16,17-20,23" |
59 | // then ids = [0,1,2,3,4,6,8,9,10,14,16,17,18,19,20,23] |
60 | void list_to_ids(const char* affinity, int* ids, int ids_size) { |
61 | int id, b, e, ids_index; |
62 | char *aff, *begin, *end, *absolute_end; |
63 | aff = strdup(s: affinity); |
64 | absolute_end = aff + strlen(s: aff); |
65 | ids_index = 0; |
66 | begin = end = aff; |
67 | while (end < absolute_end) { |
68 | end = begin; |
69 | while (*end != '\0' && *end != ',') |
70 | end++; |
71 | *end = '\0'; |
72 | if (strchr(s: begin, c: '-') != NULL) { |
73 | // Range |
74 | sscanf(s: begin, format: "%d-%d" , &b, &e); |
75 | } else { |
76 | // Single Number |
77 | sscanf(s: begin, format: "%d" , &b); |
78 | e = b; |
79 | } |
80 | for (id = b; id <= e; ++id) { |
81 | ids[ids_index++] = id; |
82 | if (ids_index >= ids_size) { |
83 | free(ptr: aff); |
84 | return; |
85 | } |
86 | } |
87 | begin = end + 1; |
88 | } |
89 | free(ptr: aff); |
90 | } |
91 | |
92 | void check_thread_affinity() { |
93 | int i; |
94 | const char *formats[2] = {"%{thread_affinity}" , "%A" }; |
95 | for (i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i) { |
96 | omp_set_affinity_format(formats[i]); |
97 | #pragma omp parallel |
98 | { |
99 | int j, k; |
100 | int place = omp_get_place_num(); |
101 | int num_procs = omp_get_place_num_procs(place); |
102 | int *ids = (int *)malloc(size: sizeof(int) * num_procs); |
103 | int *ids2 = (int *)malloc(size: sizeof(int) * num_procs); |
104 | char buf[256]; |
105 | size_t n = omp_capture_affinity(buf, 256, NULL); |
106 | check(n <= 256); |
107 | omp_get_place_proc_ids(place, ids); |
108 | list_to_ids(affinity: buf, ids: ids2, ids_size: num_procs); |
109 | |
110 | #pragma omp for schedule(static) ordered |
111 | for (k = 0; k < omp_get_num_threads(); ++k) { |
112 | #pragma omp ordered |
113 | { |
114 | debug_printf("Thread %d: captured affinity = %s\n" , |
115 | omp_get_thread_num(), buf); |
116 | for (j = 0; j < num_procs; ++j) { |
117 | debug_printf("Thread %d: ids[%d] = %d ids2[%d] = %d\n" , |
118 | omp_get_thread_num(), j, ids[j], j, ids2[j]); |
119 | check(ids[j] == ids2[j]); |
120 | } |
121 | } |
122 | } |
123 | |
124 | free(ptr: ids); |
125 | free(ptr: ids2); |
126 | } |
127 | } |
128 | } |
129 | |
130 | int main(int argc, char** argv) { |
131 | omp_set_nested(1); |
132 | display_affinity_environment(); |
133 | check_thread_affinity(); |
134 | return 0; |
135 | } |
136 | |