annotate src/fftw-3.3.5/tools/fftw-wisdom.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 2cd0e3b3e1fd
children
rev   line source
Chris@42 1 /* Re-use libbench2 and the test program, but override bench_main so that
Chris@42 2 we can have different command-line syntax. */
Chris@42 3 #include "my-getopt.h"
Chris@42 4 #include "bench.h"
Chris@42 5
Chris@42 6 #include <stdio.h>
Chris@42 7 #include <stdlib.h>
Chris@42 8 #include <ctype.h>
Chris@42 9 #include <fftw3.h>
Chris@42 10 #include <string.h>
Chris@42 11 #include <time.h>
Chris@42 12
Chris@42 13 #if defined(HAVE_THREADS) || defined(HAVE_OPENMP)
Chris@42 14 # define HAVE_SMP
Chris@42 15 extern int threads_ok;
Chris@42 16 #endif
Chris@42 17
Chris@42 18 #define CONCAT(prefix, name) prefix ## name
Chris@42 19 #if defined(BENCHFFT_SINGLE)
Chris@42 20 #define FFTW(x) CONCAT(fftwf_, x)
Chris@42 21 #elif defined(BENCHFFT_LDOUBLE)
Chris@42 22 #define FFTW(x) CONCAT(fftwl_, x)
Chris@42 23 #elif defined(BENCHFFT_QUAD)
Chris@42 24 #define FFTW(x) CONCAT(fftwq_, x)
Chris@42 25 #else
Chris@42 26 #define FFTW(x) CONCAT(fftw_, x)
Chris@42 27 #endif
Chris@42 28
Chris@42 29 /* from bench.c: */
Chris@42 30 extern unsigned the_flags;
Chris@42 31 extern int usewisdom;
Chris@42 32 extern int nthreads;
Chris@42 33
Chris@42 34 /* dummy routines to replace those in hook.c */
Chris@42 35 void install_hook(void) {}
Chris@42 36 void uninstall_hook(void) {}
Chris@42 37
Chris@42 38 int verbose;
Chris@42 39
Chris@42 40 static void do_problem(bench_problem *p)
Chris@42 41 {
Chris@42 42 if (verbose)
Chris@42 43 printf("Planning transform: %s\n", p->pstring);
Chris@42 44 /* BENCH_ASSERT(can_do(p)); */
Chris@42 45 problem_alloc(p);
Chris@42 46 setup(p);
Chris@42 47 done(p);
Chris@42 48 }
Chris@42 49
Chris@42 50 static void add_problem(const char *pstring,
Chris@42 51 bench_problem ***p, int *ip, int *np)
Chris@42 52 {
Chris@42 53 if (*ip >= *np) {
Chris@42 54 *np = *np * 2 + 1;
Chris@42 55 *p = (bench_problem **) realloc(*p, sizeof(bench_problem *) * *np);
Chris@42 56 }
Chris@42 57 (*p)[(*ip)++] = problem_parse(pstring);
Chris@42 58 }
Chris@42 59
Chris@42 60 static int sz(const bench_problem *p)
Chris@42 61 {
Chris@42 62 return tensor_sz(p->sz) * tensor_sz(p->vecsz);
Chris@42 63 }
Chris@42 64
Chris@42 65 static int prob_size_cmp(const void *p1_, const void *p2_)
Chris@42 66 {
Chris@42 67 const bench_problem * const *p1 = (const bench_problem * const *) p1_;
Chris@42 68 const bench_problem * const *p2 = (const bench_problem * const *) p2_;
Chris@42 69 return (sz(*p1) - sz(*p2));
Chris@42 70 }
Chris@42 71
Chris@42 72 static struct my_option options[] =
Chris@42 73 {
Chris@42 74 {"help", NOARG, 'h'},
Chris@42 75 {"version", NOARG, 'V'},
Chris@42 76 {"verbose", NOARG, 'v'},
Chris@42 77
Chris@42 78 {"canonical", NOARG, 'c'},
Chris@42 79 {"time-limit", REQARG, 't'},
Chris@42 80
Chris@42 81 {"output-file", REQARG, 'o'},
Chris@42 82
Chris@42 83 {"impatient", NOARG, 'i'},
Chris@42 84 {"measure", NOARG, 'm'},
Chris@42 85 {"estimate", NOARG, 'e'},
Chris@42 86 {"exhaustive", NOARG, 'x'},
Chris@42 87
Chris@42 88 {"no-system-wisdom", NOARG, 'n'},
Chris@42 89 {"wisdom-file", REQARG, 'w'},
Chris@42 90
Chris@42 91 #ifdef HAVE_SMP
Chris@42 92 {"threads", REQARG, 'T'},
Chris@42 93 #endif
Chris@42 94
Chris@42 95 /* options to restrict configuration to rdft-only, etcetera? */
Chris@42 96
Chris@42 97 {0, NOARG, 0}
Chris@42 98 };
Chris@42 99
Chris@42 100 static void help(FILE *f, const char *program_name)
Chris@42 101 {
Chris@42 102 fprintf(
Chris@42 103 f,
Chris@42 104 "Usage: %s [options] [sizes]\n"
Chris@42 105 " Create wisdom (pre-planned/optimized transforms) for specified sizes,\n"
Chris@42 106 " writing wisdom to stdout (or to a file, using -o).\n"
Chris@42 107 "\nOptions:\n"
Chris@42 108 " -h, --help: print this help\n"
Chris@42 109 " -V, --version: print version/copyright info\n"
Chris@42 110 " -v, --verbose: verbose output\n"
Chris@42 111 " -c, --canonical: plan/optimize canonical set of sizes\n"
Chris@42 112 " -t <h>, --time-limit=<h>: time limit in hours (default: 0, no limit)\n"
Chris@42 113 " -o FILE, --output-file=FILE: output to FILE instead of stdout\n"
Chris@42 114 " -m, --measure: plan in MEASURE mode (PATIENT is default)\n"
Chris@42 115 " -e, --estimate: plan in ESTIMATE mode (not recommended)\n"
Chris@42 116 " -x, --exhaustive: plan in EXHAUSTIVE mode (may be slow)\n"
Chris@42 117 " -n, --no-system-wisdom: don't read /etc/fftw/ system wisdom file\n"
Chris@42 118 " -w FILE, --wisdom-file=FILE: read wisdom from FILE (stdin if -)\n"
Chris@42 119 #ifdef HAVE_SMP
Chris@42 120 " -T N, --threads=N: plan with N threads\n"
Chris@42 121 #endif
Chris@42 122 "\nSize syntax: <type><inplace><direction><geometry>\n"
Chris@42 123 " <type> = c/r/k for complex/real(r2c,c2r)/r2r\n"
Chris@42 124 " <inplace> = i/o for in/out-of place\n"
Chris@42 125 " <direction> = f/b for forward/backward, omitted for k transforms\n"
Chris@42 126 " <geometry> = <n1>[x<n2>[x...]], e.g. 10x12x14\n"
Chris@42 127 " -- for k transforms, after each dimension is a <kind>:\n"
Chris@42 128 " <kind> = f/b/h/e00/e01/e10/e11/o00/o01/o10/o11\n"
Chris@42 129 " for R2HC/HC2R/DHT/REDFT00/.../RODFT11\n"
Chris@42 130 , program_name);
Chris@42 131 }
Chris@42 132
Chris@42 133 /* powers of two and ten up to 2^20, for now */
Chris@42 134 static char canonical_sizes[][32] = {
Chris@42 135 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024",
Chris@42 136 "2048", "4096", "8192", "16384", "32768", "65536", "131072",
Chris@42 137 "262144", "524288", "1048576",
Chris@42 138
Chris@42 139 "10", "100", "1000", "10000", "100000", "1000000",
Chris@42 140
Chris@42 141 "2x2", "4x4", "8x8", "10x10", "16x16", "32x32", "64x64", "100x100",
Chris@42 142 "128x128", "256x256", "512x512", "1000x1000", "1024x1024",
Chris@42 143
Chris@42 144 "2x2x2", "4x4x4", "8x8x8", "10x10x10", "16x16x16", "32x32x32",
Chris@42 145 "64x64x64", "100x100x100"
Chris@42 146 };
Chris@42 147
Chris@42 148 #define NELEM(array)(sizeof(array) / sizeof((array)[0]))
Chris@42 149
Chris@42 150 int bench_main(int argc, char *argv[])
Chris@42 151 {
Chris@42 152 int c;
Chris@42 153 unsigned i;
Chris@42 154 int impatient = 0;
Chris@42 155 int system_wisdom = 1;
Chris@42 156 int canonical = 0;
Chris@42 157 double hours = 0;
Chris@42 158 FILE *output_file;
Chris@42 159 char *output_fname = 0;
Chris@42 160 bench_problem **problems = 0;
Chris@42 161 int nproblems = 0, iproblem = 0;
Chris@42 162 time_t begin;
Chris@42 163
Chris@42 164 verbose = 0;
Chris@42 165 usewisdom = 0;
Chris@42 166
Chris@42 167 bench_srand(1);
Chris@42 168 #ifdef HAVE_SMP
Chris@42 169 /* do not configure FFTW with threads, unless the
Chris@42 170 user requests -T */
Chris@42 171 threads_ok = 0;
Chris@42 172 #endif
Chris@42 173
Chris@42 174 while ((c = my_getopt(argc, argv, options)) != -1) {
Chris@42 175 switch (c) {
Chris@42 176 case 'h':
Chris@42 177 help(stdout, argv[0]);
Chris@42 178 exit(EXIT_SUCCESS);
Chris@42 179 break;
Chris@42 180
Chris@42 181 case 'V':
Chris@42 182 printf("fftw-wisdom tool for FFTW version " VERSION ".\n");
Chris@42 183 printf(
Chris@42 184 "\n"
Chris@42 185 "Copyright (c) 2003, 2007-14 Matteo Frigo\n"
Chris@42 186 "Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology\n"
Chris@42 187 "\n"
Chris@42 188 "This program is free software; you can redistribute it and/or modify\n"
Chris@42 189 "it under the terms of the GNU General Public License as published by\n"
Chris@42 190 "the Free Software Foundation; either version 2 of the License, or\n"
Chris@42 191 "(at your option) any later version.\n"
Chris@42 192 "\n"
Chris@42 193 "This program is distributed in the hope that it will be useful,\n"
Chris@42 194 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
Chris@42 195 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
Chris@42 196 "GNU General Public License for more details.\n"
Chris@42 197 "\n"
Chris@42 198 "You should have received a copy of the GNU General Public License\n"
Chris@42 199 "along with this program; if not, write to the Free Software\n"
Chris@42 200 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
Chris@42 201 );
Chris@42 202 exit(EXIT_SUCCESS);
Chris@42 203 break;
Chris@42 204
Chris@42 205 case 'v':
Chris@42 206 verbose = 1;
Chris@42 207 break;
Chris@42 208
Chris@42 209 case 'c':
Chris@42 210 canonical = 1;
Chris@42 211 break;
Chris@42 212
Chris@42 213 case 't':
Chris@42 214 hours = atof(my_optarg);
Chris@42 215 break;
Chris@42 216
Chris@42 217 case 'o':
Chris@42 218 if (output_fname)
Chris@42 219 bench_free(output_fname);
Chris@42 220
Chris@42 221 if (!strcmp(my_optarg, "-"))
Chris@42 222 output_fname = 0;
Chris@42 223 else {
Chris@42 224 output_fname = (char *) bench_malloc(sizeof(char) *
Chris@42 225 (strlen(my_optarg) + 1));
Chris@42 226 strcpy(output_fname, my_optarg);
Chris@42 227 }
Chris@42 228 break;
Chris@42 229
Chris@42 230 case 'm':
Chris@42 231 case 'i':
Chris@42 232 impatient = 1;
Chris@42 233 break;
Chris@42 234
Chris@42 235 case 'e':
Chris@42 236 the_flags |= FFTW_ESTIMATE;
Chris@42 237 break;
Chris@42 238
Chris@42 239 case 'x':
Chris@42 240 the_flags |= FFTW_EXHAUSTIVE;
Chris@42 241 break;
Chris@42 242
Chris@42 243 case 'n':
Chris@42 244 system_wisdom = 0;
Chris@42 245 break;
Chris@42 246
Chris@42 247 case 'w': {
Chris@42 248 FILE *w = stdin;
Chris@42 249 if (strcmp(my_optarg, "-") && !(w = fopen(my_optarg, "r"))) {
Chris@42 250 fprintf(stderr,
Chris@42 251 "fftw-wisdom: error opening \"%s\": ", my_optarg);
Chris@42 252 perror("");
Chris@42 253 exit(EXIT_FAILURE);
Chris@42 254 }
Chris@42 255 if (!FFTW(import_wisdom_from_file)(w)) {
Chris@42 256 fprintf(stderr, "fftw_wisdom: error reading wisdom "
Chris@42 257 "from \"%s\"\n", my_optarg);
Chris@42 258 exit(EXIT_FAILURE);
Chris@42 259 }
Chris@42 260 if (w != stdin)
Chris@42 261 fclose(w);
Chris@42 262 break;
Chris@42 263 }
Chris@42 264
Chris@42 265 #ifdef HAVE_SMP
Chris@42 266 case 'T':
Chris@42 267 nthreads = atoi(my_optarg);
Chris@42 268 if (nthreads < 1) nthreads = 1;
Chris@42 269 threads_ok = 1;
Chris@42 270 BENCH_ASSERT(FFTW(init_threads)());
Chris@42 271 break;
Chris@42 272 #endif
Chris@42 273
Chris@42 274 case '?':
Chris@42 275 /* `my_getopt' already printed an error message. */
Chris@42 276 cleanup();
Chris@42 277 return EXIT_FAILURE;
Chris@42 278
Chris@42 279 default:
Chris@42 280 abort ();
Chris@42 281 }
Chris@42 282 }
Chris@42 283
Chris@42 284 if (!impatient)
Chris@42 285 the_flags |= FFTW_PATIENT;
Chris@42 286
Chris@42 287 if (system_wisdom)
Chris@42 288 if (!FFTW(import_system_wisdom)() && verbose)
Chris@42 289 fprintf(stderr, "fftw-wisdom: system-wisdom import failed\n");
Chris@42 290
Chris@42 291 if (canonical) {
Chris@42 292 for (i = 0; i < NELEM(canonical_sizes); ++i) {
Chris@42 293 unsigned j;
Chris@42 294 char types[][8] = {
Chris@42 295 "cof", "cob", "cif", "cib", "rof", "rob", "rif", "rib"
Chris@42 296 };
Chris@42 297
Chris@42 298 for (j = 0; j < NELEM(types); ++j) {
Chris@42 299 char ps[64];
Chris@42 300 if (!strchr(canonical_sizes[i],'x')
Chris@42 301 || !strchr(types[j],'o')) {
Chris@42 302 #ifdef HAVE_SNPRINTF
Chris@42 303 snprintf(ps, sizeof(ps), "%s%s", types[j], canonical_sizes[i]);
Chris@42 304 #else
Chris@42 305 sprintf(ps, "%s%s", types[j], canonical_sizes[i]);
Chris@42 306 #endif
Chris@42 307 add_problem(ps, &problems, &iproblem, &nproblems);
Chris@42 308 }
Chris@42 309 }
Chris@42 310 }
Chris@42 311 }
Chris@42 312
Chris@42 313 while (my_optind < argc) {
Chris@42 314 if (!strcmp(argv[my_optind], "-")) {
Chris@42 315 char s[1025];
Chris@42 316 while (1 == fscanf(stdin, "%1024s", s))
Chris@42 317 add_problem(s, &problems, &iproblem, &nproblems);
Chris@42 318 }
Chris@42 319 else
Chris@42 320 add_problem(argv[my_optind], &problems, &iproblem, &nproblems);
Chris@42 321 ++my_optind;
Chris@42 322 }
Chris@42 323
Chris@42 324 nproblems = iproblem;
Chris@42 325 qsort(problems, nproblems, sizeof(bench_problem *), prob_size_cmp);
Chris@42 326
Chris@42 327 if (!output_fname)
Chris@42 328 output_file = stdout;
Chris@42 329 else
Chris@42 330 if (!(output_file = fopen(output_fname, "w"))) {
Chris@42 331 fprintf(stderr,
Chris@42 332 "fftw-wisdom: error creating \"%s\"", output_fname);
Chris@42 333 perror("");
Chris@42 334 exit(EXIT_FAILURE);
Chris@42 335 }
Chris@42 336
Chris@42 337 begin = time((time_t*)0);
Chris@42 338 for (iproblem = 0; iproblem < nproblems; ++iproblem) {
Chris@42 339 if (hours <= 0
Chris@42 340 || hours > (time((time_t*)0) - begin) / 3600.0)
Chris@42 341 do_problem(problems[iproblem]);
Chris@42 342 problem_destroy(problems[iproblem]);
Chris@42 343
Chris@42 344 }
Chris@42 345 free(problems);
Chris@42 346
Chris@42 347 if (verbose && hours > 0
Chris@42 348 && hours < (time((time_t*)0) - begin) / 3600.0)
Chris@42 349 fprintf(stderr, "EXCEEDED TIME LIMIT OF %g HOURS.\n", hours);
Chris@42 350
Chris@42 351 FFTW(export_wisdom_to_file)(output_file);
Chris@42 352 if (output_file != stdout)
Chris@42 353 fclose(output_file);
Chris@42 354 if (output_fname)
Chris@42 355 bench_free(output_fname);
Chris@42 356
Chris@42 357 cleanup();
Chris@42 358
Chris@42 359 return EXIT_SUCCESS;
Chris@42 360 }