comparison src/fftw-3.3.8/tests/fftw-bench.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 /* See bench.c. We keep a few common subroutines in this file so
2 that they can be re-used in the MPI test program. */
3
4 #include <math.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include "tests/fftw-bench.h"
8
9 /* define to enable code that traps floating-point exceptions.
10 Disabled by default because I don't want to worry about the
11 portability of such code. feenableexcept() seems to be a GNU
12 thing */
13 #undef TRAP_FP_EXCEPTIONS
14
15 #ifdef TRAP_FP_EXCEPTIONS
16 # include <signal.h>
17 # include <fenv.h>
18 #endif
19
20 #ifdef _OPENMP
21 # include <omp.h>
22 #endif
23
24 #ifdef HAVE_SMP
25 int threads_ok = 1;
26 #endif
27
28 FFTW(plan) the_plan = 0;
29
30 static const char *wisdat = "wis.dat";
31 unsigned the_flags = 0;
32 int paranoid = 0;
33 int usewisdom = 0;
34 int havewisdom = 0;
35 int nthreads = 1;
36 int amnesia = 0;
37
38 extern void install_hook(void); /* in hook.c */
39 extern void uninstall_hook(void); /* in hook.c */
40
41 #ifdef FFTW_RANDOM_ESTIMATOR
42 extern unsigned FFTW(random_estimate_seed);
43 #endif
44
45 #ifdef TRAP_FP_EXCEPTIONS
46 static void sigfpe_handler(int sig, siginfo_t *info, void *context)
47 {
48 /* fftw code is not supposed to generate FP exceptions */
49 UNUSED(sig); UNUSED(info); UNUSED(context);
50 fprintf(stderr, "caught FPE, aborting\n");
51 abort();
52 }
53
54 static void setup_sigfpe_handler(void)
55 {
56 struct sigaction a;
57 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW);
58 memset(&a, 0, sizeof(a));
59 a.sa_sigaction = sigfpe_handler;
60 a.sa_flags = SA_SIGINFO;
61 if (sigaction(SIGFPE, &a, NULL) == -1) {
62 fprintf(stderr, "cannot install sigfpe handler\n");
63 exit(1);
64 }
65 }
66 #else
67 static void setup_sigfpe_handler(void)
68 {
69 }
70 #endif
71
72 void useropt(const char *arg)
73 {
74 int x;
75 double y;
76
77 if (!strcmp(arg, "patient")) the_flags |= FFTW_PATIENT;
78 else if (!strcmp(arg, "estimate")) the_flags |= FFTW_ESTIMATE;
79 else if (!strcmp(arg, "estimatepat")) the_flags |= FFTW_ESTIMATE_PATIENT;
80 else if (!strcmp(arg, "exhaustive")) the_flags |= FFTW_EXHAUSTIVE;
81 else if (!strcmp(arg, "unaligned")) the_flags |= FFTW_UNALIGNED;
82 else if (!strcmp(arg, "nosimd")) the_flags |= FFTW_NO_SIMD;
83 else if (!strcmp(arg, "noindirectop")) the_flags |= FFTW_NO_INDIRECT_OP;
84 else if (!strcmp(arg, "wisdom-only")) the_flags |= FFTW_WISDOM_ONLY;
85 else if (sscanf(arg, "flag=%d", &x) == 1) the_flags |= x;
86 else if (sscanf(arg, "bflag=%d", &x) == 1) the_flags |= 1U << x;
87 else if (!strcmp(arg, "paranoid")) paranoid = 1;
88 else if (!strcmp(arg, "wisdom")) usewisdom = 1;
89 else if (!strcmp(arg, "amnesia")) amnesia = 1;
90 else if (sscanf(arg, "nthreads=%d", &x) == 1) nthreads = x;
91 #ifdef FFTW_RANDOM_ESTIMATOR
92 else if (sscanf(arg, "eseed=%d", &x) == 1) FFTW(random_estimate_seed) = x;
93 #endif
94 else if (sscanf(arg, "timelimit=%lg", &y) == 1) {
95 FFTW(set_timelimit)(y);
96 }
97
98 else fprintf(stderr, "unknown user option: %s. Ignoring.\n", arg);
99 }
100
101 void rdwisdom(void)
102 {
103 FILE *f;
104 double tim;
105 int success = 0;
106
107 if (havewisdom) return;
108
109 #ifdef HAVE_SMP
110 if (threads_ok) {
111 BENCH_ASSERT(FFTW(init_threads)());
112 FFTW(plan_with_nthreads)(nthreads);
113 FFTW(make_planner_thread_safe)();
114 #ifdef _OPENMP
115 omp_set_num_threads(nthreads);
116 #endif
117 }
118 else if (nthreads > 1 && verbose > 1) {
119 fprintf(stderr, "bench: WARNING - nthreads = %d, but threads not supported\n", nthreads);
120 nthreads = 1;
121 }
122 #endif
123
124 if (!usewisdom) return;
125
126 timer_start(USER_TIMER);
127 if ((f = fopen(wisdat, "r"))) {
128 if (!import_wisdom(f))
129 fprintf(stderr, "bench: ERROR reading wisdom\n");
130 else
131 success = 1;
132 fclose(f);
133 }
134 tim = timer_stop(USER_TIMER);
135
136 if (success) {
137 if (verbose > 1) printf("READ WISDOM (%g seconds): ", tim);
138
139 if (verbose > 3)
140 export_wisdom(stdout);
141 if (verbose > 1)
142 printf("\n");
143 }
144 havewisdom = 1;
145 }
146
147 void wrwisdom(void)
148 {
149 FILE *f;
150 double tim;
151 if (!havewisdom) return;
152
153 timer_start(USER_TIMER);
154 if ((f = fopen(wisdat, "w"))) {
155 export_wisdom(f);
156 fclose(f);
157 }
158 tim = timer_stop(USER_TIMER);
159 if (verbose > 1) printf("write wisdom took %g seconds\n", tim);
160 }
161
162 static unsigned preserve_input_flags(bench_problem *p)
163 {
164 /*
165 * fftw3 cannot preserve input for multidimensional c2r transforms.
166 * Enforce FFTW_DESTROY_INPUT
167 */
168 if (p->kind == PROBLEM_REAL &&
169 p->sign > 0 &&
170 !p->in_place &&
171 p->sz->rnk > 1)
172 p->destroy_input = 1;
173
174 if (p->destroy_input)
175 return FFTW_DESTROY_INPUT;
176 else
177 return FFTW_PRESERVE_INPUT;
178 }
179
180 int can_do(bench_problem *p)
181 {
182 double tim;
183
184 if (verbose > 2 && p->pstring)
185 printf("Planning %s...\n", p->pstring);
186 rdwisdom();
187
188 timer_start(USER_TIMER);
189 the_plan = mkplan(p, preserve_input_flags(p) | the_flags | FFTW_ESTIMATE);
190 tim = timer_stop(USER_TIMER);
191 if (verbose > 2) printf("estimate-planner time: %g s\n", tim);
192
193 if (the_plan) {
194 FFTW(destroy_plan)(the_plan);
195 return 1;
196 }
197 return 0;
198 }
199
200 void setup(bench_problem *p)
201 {
202 double tim;
203
204 setup_sigfpe_handler();
205
206 if (amnesia) {
207 FFTW(forget_wisdom)();
208 havewisdom = 0;
209 }
210
211 /* Regression test: check that fftw_malloc exists and links
212 * properly */
213 {
214 void *ptr = FFTW(malloc(42));
215 BENCH_ASSERT(FFTW(alignment_of)(ptr) == 0);
216 FFTW(free(ptr));
217 }
218
219 rdwisdom();
220 install_hook();
221
222 #ifdef HAVE_SMP
223 if (verbose > 1 && nthreads > 1) printf("NTHREADS = %d\n", nthreads);
224 #endif
225
226 timer_start(USER_TIMER);
227 the_plan = mkplan(p, preserve_input_flags(p) | the_flags);
228 tim = timer_stop(USER_TIMER);
229 if (verbose > 1) printf("planner time: %g s\n", tim);
230
231 BENCH_ASSERT(the_plan);
232
233 {
234 double add, mul, nfma, cost, pcost;
235 FFTW(flops)(the_plan, &add, &mul, &nfma);
236 cost = FFTW(estimate_cost)(the_plan);
237 pcost = FFTW(cost)(the_plan);
238 if (verbose > 1) {
239 FFTW(print_plan)(the_plan);
240 printf("\n");
241 printf("flops: %0.0f add, %0.0f mul, %0.0f fma\n",
242 add, mul, nfma);
243 printf("estimated cost: %f, pcost = %f\n", cost, pcost);
244 }
245 }
246 }
247
248
249 void doit(int iter, bench_problem *p)
250 {
251 int i;
252 FFTW(plan) q = the_plan;
253
254 UNUSED(p);
255 for (i = 0; i < iter; ++i)
256 FFTW(execute)(q);
257 }
258
259 void done(bench_problem *p)
260 {
261 UNUSED(p);
262
263 FFTW(destroy_plan)(the_plan);
264 uninstall_hook();
265 }
266
267 void cleanup(void)
268 {
269 initial_cleanup();
270
271 wrwisdom();
272 #ifdef HAVE_SMP
273 FFTW(cleanup_threads)();
274 #else
275 FFTW(cleanup)();
276 #endif
277
278 # ifdef FFTW_DEBUG_MALLOC
279 {
280 /* undocumented memory checker */
281 FFTW_EXTERN void FFTW(malloc_print_minfo)(int v);
282 FFTW(malloc_print_minfo)(verbose);
283 }
284 # endif
285
286 final_cleanup();
287 }