1 #include "cado.h" // IWYU pragma: keep
2 #include <stdio.h>
3 #include <ctype.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <hwloc.h>
7 #include "cpubinding.h"
8 #include "macros.h"
9 #include "params.h"
10 #include "misc.h"
11
12 /* Example quick use:
13 * $build_tree/tests/linalg/bwc/test_cpubinding -s "NUMANode:4 Socket:1 Core:12 PU:2" thr=8x8 cpubinding="NUMANode=>2x2 Core*12=>4x4"
14 */
15
usage()16 void usage() {
17 fprintf(stderr, "cpubinding example program\n"
18 "Options:\n"
19 "--input-topology-file <filename> take <filename> as an hwloc hardware description\n"
20 "--input-topology-string <string> take <string> as an hwloc synthetic hardware description\n"
21 "thr=<int>x<int> give results for this target mapping\n"
22 "cpubinding=<string> use this mapping (or file)\n"
23 );
24 exit(1);
25 }
26
27 int verbose = 0;
28
do_cpubinding_tests(const char * cpubinding_conf)29 int do_cpubinding_tests(const char * cpubinding_conf)
30 {
31 FILE * f = fopen(cpubinding_conf, "r");
32 if (f == NULL) {
33 fprintf(stderr, "%s: fopen failed\n", cpubinding_conf);
34 exit(1);
35 }
36
37 char line[1024];
38
39 int nb_ok = 0;
40 int nb_nok = 0;
41 int idx = 0;
42 for( ; fgets(line, sizeof(line), f) ; ) {
43 int pos = 0;
44 int want = 0;
45 const char * find_magic2 = "# EXPECT_FIND2";
46 const char * find_magic = "# EXPECT_FIND";
47 const char * fail_magic = "# EXPECT_FAIL";
48 if (strncmp(line, find_magic2, strlen(find_magic2)) == 0) {
49 #if HWLOC_API_VERSION >= 0x020000
50 pos += strlen(find_magic2);
51 want = 1;
52 #else
53 continue;
54 #endif
55 } else if (strncmp(line, find_magic, strlen(find_magic)) == 0) {
56 pos += strlen(find_magic);
57 want = 1;
58 } else if (strncmp(line, fail_magic, strlen(fail_magic)) == 0) {
59 pos += strlen(fail_magic);
60 want = 0;
61 } else {
62 continue;
63 }
64
65 int pos2;
66 int t[2];
67 int rc = sscanf(line + pos, "%d %d %n", &t[0], &t[1], &pos2);
68 for(int n = strlen(line); n && isspace(line[n-1]); line[--n]='\0');
69 ASSERT_ALWAYS(rc >= 2);
70
71 if (verbose) printf("doing subtest %d: %s\n", idx, line);
72 idx++;
73
74 param_list pl2;
75 param_list_init(pl2);
76 param_list_add_key(pl2, "cpubinding", cpubinding_conf, PARAMETER_FROM_CMDLINE);
77 param_list_add_key(pl2, "input-topology-string", line + pos + pos2, PARAMETER_FROM_CMDLINE);
78
79 char * msg;
80 void * cc = cpubinding_get_info(&msg, pl2, t);
81 /* don't make the tests too verbose */
82 if (msg) {
83 if (verbose) puts(msg);
84 free(msg);
85 }
86 int ok = want == (cc != NULL);
87 if (verbose) printf("result: %s\n", ok_NOK(ok));
88 nb_ok += ok;
89 nb_nok += !ok;
90
91 cpubinding_do_pinning(cc, 0, 0);
92 cpubinding_free_info(cc, t);
93
94 param_list_clear(pl2);
95 }
96 fclose(f);
97 return !nb_nok;
98 }
99
main(int argc,char * argv[])100 int main(int argc, char * argv[])
101 {
102 const char * cpubinding_conf = NULL;
103 param_list pl;
104 param_list_init(pl);
105 argv++,argc--;
106 param_list_configure_alias(pl, "input-topology-file", "-i");
107 param_list_configure_alias(pl, "input-topology-string", "-s");
108 param_list_configure_alias(pl, "cpubinding", "-c");
109 param_list_configure_switch(pl, "-v", &verbose);
110 for( ; argc ; ) {
111 if (param_list_update_cmdline(pl, &argc, &argv)) { continue; }
112 /* Do perhaps some other things on the argument that haven't
113 * been eaten at all. Like check whether it is a valid file to
114 * source in order to get more options. See
115 * param_list_read_stream and param_list_read_file for that. */
116 fprintf (stderr, "Unknown option: %s\n", argv[0]);
117 usage();
118 }
119
120 int seen_i = param_list_lookup_string(pl, "input-topology-file") != NULL;
121 int seen_s = param_list_lookup_string(pl, "input-topology-string") != NULL;
122
123 if (seen_i && seen_s) {
124 fprintf(stderr, "Cannot have both -i and -s\n");
125 exit(1);
126 }
127
128 cpubinding_conf = param_list_lookup_string(pl, "cpubinding");
129
130 int thr[2] = {1,1};
131 int parsed_thr = param_list_parse_int_and_int(pl, "thr", thr, "x");
132
133 if (param_list_warn_unused(pl)) {
134 usage();
135 }
136
137 char * msg;
138
139 int rc = 0;
140 if (parsed_thr) {
141 /* This mode is here because this binary also serves as a quick
142 * debug program, just to see how a given mapping string is
143 * interpreted.
144 */
145 void * cc = cpubinding_get_info(&msg, pl, thr);
146 if (msg) {
147 puts(msg);
148 free(msg);
149 }
150 cpubinding_do_pinning(cc, 0, 0);
151 cpubinding_free_info(cc, thr);
152 } else if (cpubinding_conf) {
153 rc = do_cpubinding_tests(cpubinding_conf) ? EXIT_SUCCESS : EXIT_FAILURE;
154 } else {
155 fprintf(stderr, "don't know what to do !\n");
156 exit(1);
157 }
158
159 param_list_clear(pl);
160
161 return rc;
162 }
163