| // RUN: %libomp-compile | |
| // RUN: env OMP_PROC_BIND=close OMP_PLACES=threads %libomp-run | |
| // RUN: env OMP_PROC_BIND=close OMP_PLACES=cores %libomp-run | |
| // RUN: env OMP_PROC_BIND=close OMP_PLACES=sockets %libomp-run | |
| // RUN: env KMP_AFFINITY=compact %libomp-run | |
| // RUN: env KMP_AFFINITY=scatter %libomp-run | |
| // REQUIRES: affinity | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <omp.h> | |
| #define XSTR(x) #x | |
| #define STR(x) XSTR(x) | |
| #define streqls(s1, s2) (!strcmp(s1, s2)) | |
| #define check(condition) \ | |
| if (!(condition)) { \ | |
| fprintf(stderr, "error: %s: %d: " STR(condition) "\n", __FILE__, \ | |
| __LINE__); \ | |
| exit(1); \ | |
| } | |
| #define DEBUG 0 | |
| #if DEBUG | |
| #include <stdarg.h> | |
| #endif | |
| #define BUFFER_SIZE 1024 | |
| char buf[BUFFER_SIZE]; | |
| #pragma omp threadprivate(buf) | |
| static int debug_printf(const char* format, ...) { | |
| int retval = 0; | |
| #if DEBUG | |
| va_list args; | |
| va_start(args, format); | |
| retval = vprintf(format, args); | |
| va_end(args); | |
| #endif | |
| return retval; | |
| } | |
| static void display_affinity_environment() { | |
| #if DEBUG | |
| printf("Affinity Environment:\n"); | |
| printf(" OMP_PROC_BIND=%s\n", getenv("OMP_PROC_BIND")); | |
| printf(" OMP_PLACES=%s\n", getenv("OMP_PLACES")); | |
| printf(" KMP_AFFINITY=%s\n", getenv("KMP_AFFINITY")); | |
| #endif | |
| } | |
| // Reads in a list of integers into ids array (not going past ids_size) | |
| // e.g., if affinity = "0-4,6,8-10,14,16,17-20,23" | |
| // then ids = [0,1,2,3,4,6,8,9,10,14,16,17,18,19,20,23] | |
| void list_to_ids(const char* affinity, int* ids, int ids_size) { | |
| int id, b, e, ids_index; | |
| char *aff, *begin, *end, *absolute_end; | |
| aff = strdup(affinity); | |
| absolute_end = aff + strlen(aff); | |
| ids_index = 0; | |
| begin = end = aff; | |
| while (end < absolute_end) { | |
| end = begin; | |
| while (*end != '\0' && *end != ',') | |
| end++; | |
| *end = '\0'; | |
| if (strchr(begin, '-') != NULL) { | |
| // Range | |
| sscanf(begin, "%d-%d", &b, &e); | |
| } else { | |
| // Single Number | |
| sscanf(begin, "%d", &b); | |
| e = b; | |
| } | |
| for (id = b; id <= e; ++id) { | |
| ids[ids_index++] = id; | |
| if (ids_index >= ids_size) { | |
| free(aff); | |
| return; | |
| } | |
| } | |
| begin = end + 1; | |
| } | |
| free(aff); | |
| } | |
| void check_thread_affinity() { | |
| int i; | |
| const char *formats[2] = {"%{thread_affinity}", "%A"}; | |
| for (i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i) { | |
| omp_set_affinity_format(formats[i]); | |
| #pragma omp parallel | |
| { | |
| int j, k; | |
| int place = omp_get_place_num(); | |
| int num_procs = omp_get_place_num_procs(place); | |
| int *ids = (int *)malloc(sizeof(int) * num_procs); | |
| int *ids2 = (int *)malloc(sizeof(int) * num_procs); | |
| char buf[256]; | |
| size_t n = omp_capture_affinity(buf, 256, NULL); | |
| check(n <= 256); | |
| omp_get_place_proc_ids(place, ids); | |
| list_to_ids(buf, ids2, num_procs); | |
| #pragma omp for schedule(static) ordered | |
| for (k = 0; k < omp_get_num_threads(); ++k) { | |
| #pragma omp ordered | |
| { | |
| debug_printf("Thread %d: captured affinity = %s\n", | |
| omp_get_thread_num(), buf); | |
| for (j = 0; j < num_procs; ++j) { | |
| debug_printf("Thread %d: ids[%d] = %d ids2[%d] = %d\n", | |
| omp_get_thread_num(), j, ids[j], j, ids2[j]); | |
| check(ids[j] == ids2[j]); | |
| } | |
| } | |
| } | |
| free(ids); | |
| free(ids2); | |
| } | |
| } | |
| } | |
| int main(int argc, char** argv) { | |
| omp_set_nested(1); | |
| display_affinity_environment(); | |
| check_thread_affinity(); | |
| return 0; | |
| } |