| // 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> |
| #include "helper.h" |
| #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; |
| } |