1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
// RUN: %libomp-compile -D_GNU_SOURCE
// RUN: env OMP_PLACES=threads %libomp-run
// RUN: env OMP_PLACES=cores %libomp-run
// RUN: env OMP_PLACES=sockets %libomp-run
// RUN: env OMP_PLACES=cores RUN_OUT_OF_ORDER=1 %libomp-run
// REQUIRES: linux
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libomp_test_affinity.h"
#include "libomp_test_topology.h"
// Check openmp place list to make sure it follow KMP_HW_SUBSET restriction
static int compare_hw_subset_places(const place_list_t *openmp_places,
topology_obj_type_t type, int nsockets,
int ncores_per_socket,
int nthreads_per_core) {
int i, j, expected_total, expected_per_place;
if (type == TOPOLOGY_OBJ_THREAD) {
expected_total = nsockets * ncores_per_socket * nthreads_per_core;
expected_per_place = 1;
} else if (type == TOPOLOGY_OBJ_CORE) {
expected_total = nsockets * ncores_per_socket;
expected_per_place = nthreads_per_core;
} else {
expected_total = nsockets;
expected_per_place = ncores_per_socket;
}
if (openmp_places->num_places != expected_total) {
fprintf(stderr, "error: KMP_HW_SUBSET did not half each resource layer!\n");
printf("openmp_places places:\n");
topology_print_places(openmp_places);
printf("\n");
return EXIT_FAILURE;
}
for (i = 0; i < openmp_places->num_places; ++i) {
int count = affinity_mask_count(openmp_places->masks[i]);
if (count != expected_per_place) {
fprintf(stderr, "error: place %d has %d OS procs instead of %d\n", i,
count, expected_per_place);
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
static int check_places() {
char buf[100];
topology_obj_type_t type;
const char *value;
int status = EXIT_SUCCESS;
place_list_t *threads, *cores, *sockets, *openmp_places;
threads = topology_alloc_type_places(TOPOLOGY_OBJ_THREAD);
cores = topology_alloc_type_places(TOPOLOGY_OBJ_CORE);
sockets = topology_alloc_type_places(TOPOLOGY_OBJ_SOCKET);
if (threads->num_places <= 1) {
printf("Only one hardware thread to execute on. Skipping test.\n");
return status;
}
value = getenv("OMP_PLACES");
if (!value) {
fprintf(stderr,
"error: OMP_PLACES must be set to one of threads,cores,sockets!\n");
return EXIT_FAILURE;
}
if (strcmp(value, "threads") == 0)
type = TOPOLOGY_OBJ_THREAD;
else if (strcmp(value, "cores") == 0)
type = TOPOLOGY_OBJ_CORE;
else if (strcmp(value, "sockets") == 0)
type = TOPOLOGY_OBJ_SOCKET;
else {
fprintf(stderr,
"error: OMP_PLACES must be one of threads,cores,sockets!\n");
return EXIT_FAILURE;
}
// Calculate of num threads per core, num cores per socket, & num sockets
if (cores->num_places <= 0) {
printf("Invalid number of cores (%d). Skipping test.\n", cores->num_places);
return status;
} else if (sockets->num_places <= 0) {
printf("Invalid number of sockets (%d). Skipping test.\n",
cores->num_places);
return status;
}
int nthreads_per_core = threads->num_places / cores->num_places;
int ncores_per_socket = cores->num_places / sockets->num_places;
int nsockets = sockets->num_places;
if (nsockets * ncores_per_socket * nthreads_per_core != threads->num_places) {
printf("Only uniform topologies can be tested. Skipping test.\n");
return status;
}
// Use half the resources of every level
if (nthreads_per_core > 1)
nthreads_per_core /= 2;
if (ncores_per_socket > 1)
ncores_per_socket /= 2;
if (nsockets > 1)
nsockets /= 2;
if (getenv("RUN_OUT_OF_ORDER")) {
snprintf(buf, sizeof(buf), "%dt,%ds,%dc", nthreads_per_core, nsockets,
ncores_per_socket);
} else {
snprintf(buf, sizeof(buf), "%ds,%dc,%dt", nsockets, ncores_per_socket,
nthreads_per_core);
}
setenv("KMP_HW_SUBSET", buf, 1);
openmp_places = topology_alloc_openmp_places();
status = compare_hw_subset_places(openmp_places, type, nsockets,
ncores_per_socket, nthreads_per_core);
topology_free_places(threads);
topology_free_places(cores);
topology_free_places(sockets);
topology_free_places(openmp_places);
return status;
}
int main() {
if (!topology_using_full_mask()) {
printf("Thread does not have access to all logical processors. Skipping "
"test.\n");
return EXIT_SUCCESS;
}
return check_places();
}
|