File: kmp-hw-subset.c

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (133 lines) | stat: -rw-r--r-- 4,509 bytes parent folder | download | duplicates (12)
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();
}