annotate src/fftw-3.3.5/tests/fftw-bench.c @ 169:223a55898ab9 tip default

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