Mercurial > hg > sv-dependency-builds
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 } |