comparison src/fftw-3.3.8/tools/fftw-wisdom.c @ 167:bd3cc4d1df30

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