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(affinity); 64 absolute_end = aff + strlen(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(begin, '-') != NULL) { 73 // Range 74 sscanf(begin, "%d-%d", &b, &e); 75 } else { 76 // Single Number 77 sscanf(begin, "%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(aff); 84 return; 85 } 86 } 87 begin = end + 1; 88 } 89 free(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(sizeof(int) * num_procs); 103 int *ids2 = (int *)malloc(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(buf, ids2, 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(ids); 125 free(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