Chris@10: /* See bench.c. We keep a few common subroutines in this file so Chris@10: that they can be re-used in the MPI test program. */ Chris@10: Chris@10: #include Chris@10: #include Chris@10: #include Chris@10: #include "fftw-bench.h" Chris@10: Chris@10: #ifdef _OPENMP Chris@10: # include Chris@10: #endif Chris@10: Chris@10: #ifdef HAVE_SMP Chris@10: int threads_ok = 1; Chris@10: #endif Chris@10: Chris@10: FFTW(plan) the_plan = 0; Chris@10: Chris@10: static const char *wisdat = "wis.dat"; Chris@10: unsigned the_flags = 0; Chris@10: int paranoid = 0; Chris@10: int usewisdom = 0; Chris@10: int havewisdom = 0; Chris@10: int nthreads = 1; Chris@10: int amnesia = 0; Chris@10: Chris@10: extern void install_hook(void); /* in hook.c */ Chris@10: extern void uninstall_hook(void); /* in hook.c */ Chris@10: Chris@10: #ifdef FFTW_RANDOM_ESTIMATOR Chris@10: extern unsigned FFTW(random_estimate_seed); Chris@10: #endif Chris@10: Chris@10: void useropt(const char *arg) Chris@10: { Chris@10: int x; Chris@10: double y; Chris@10: Chris@10: if (!strcmp(arg, "patient")) the_flags |= FFTW_PATIENT; Chris@10: else if (!strcmp(arg, "estimate")) the_flags |= FFTW_ESTIMATE; Chris@10: else if (!strcmp(arg, "estimatepat")) the_flags |= FFTW_ESTIMATE_PATIENT; Chris@10: else if (!strcmp(arg, "exhaustive")) the_flags |= FFTW_EXHAUSTIVE; Chris@10: else if (!strcmp(arg, "unaligned")) the_flags |= FFTW_UNALIGNED; Chris@10: else if (!strcmp(arg, "nosimd")) the_flags |= FFTW_NO_SIMD; Chris@10: else if (!strcmp(arg, "noindirectop")) the_flags |= FFTW_NO_INDIRECT_OP; Chris@10: else if (!strcmp(arg, "wisdom-only")) the_flags |= FFTW_WISDOM_ONLY; Chris@10: else if (sscanf(arg, "flag=%d", &x) == 1) the_flags |= x; Chris@10: else if (sscanf(arg, "bflag=%d", &x) == 1) the_flags |= 1U << x; Chris@10: else if (!strcmp(arg, "paranoid")) paranoid = 1; Chris@10: else if (!strcmp(arg, "wisdom")) usewisdom = 1; Chris@10: else if (!strcmp(arg, "amnesia")) amnesia = 1; Chris@10: else if (sscanf(arg, "nthreads=%d", &x) == 1) nthreads = x; Chris@10: #ifdef FFTW_RANDOM_ESTIMATOR Chris@10: else if (sscanf(arg, "eseed=%d", &x) == 1) FFTW(random_estimate_seed) = x; Chris@10: #endif Chris@10: else if (sscanf(arg, "timelimit=%lg", &y) == 1) { Chris@10: FFTW(set_timelimit)(y); Chris@10: } Chris@10: Chris@10: else fprintf(stderr, "unknown user option: %s. Ignoring.\n", arg); Chris@10: } Chris@10: Chris@10: void rdwisdom(void) Chris@10: { Chris@10: FILE *f; Chris@10: double tim; Chris@10: int success = 0; Chris@10: Chris@10: if (havewisdom) return; Chris@10: Chris@10: #ifdef HAVE_SMP Chris@10: if (threads_ok) { Chris@10: BENCH_ASSERT(FFTW(init_threads)()); Chris@10: FFTW(plan_with_nthreads)(nthreads); Chris@10: #ifdef _OPENMP Chris@10: omp_set_num_threads(nthreads); Chris@10: #endif Chris@10: } Chris@10: else if (nthreads > 1 && verbose > 1) { Chris@10: fprintf(stderr, "bench: WARNING - nthreads = %d, but threads not supported\n", nthreads); Chris@10: nthreads = 1; Chris@10: } Chris@10: #endif Chris@10: Chris@10: if (!usewisdom) return; Chris@10: Chris@10: timer_start(USER_TIMER); Chris@10: if ((f = fopen(wisdat, "r"))) { Chris@10: if (!import_wisdom(f)) Chris@10: fprintf(stderr, "bench: ERROR reading wisdom\n"); Chris@10: else Chris@10: success = 1; Chris@10: fclose(f); Chris@10: } Chris@10: tim = timer_stop(USER_TIMER); Chris@10: Chris@10: if (success) { Chris@10: if (verbose > 1) printf("READ WISDOM (%g seconds): ", tim); Chris@10: Chris@10: if (verbose > 3) Chris@10: export_wisdom(stdout); Chris@10: if (verbose > 1) Chris@10: printf("\n"); Chris@10: } Chris@10: havewisdom = 1; Chris@10: } Chris@10: Chris@10: void wrwisdom(void) Chris@10: { Chris@10: FILE *f; Chris@10: double tim; Chris@10: if (!havewisdom) return; Chris@10: Chris@10: timer_start(USER_TIMER); Chris@10: if ((f = fopen(wisdat, "w"))) { Chris@10: export_wisdom(f); Chris@10: fclose(f); Chris@10: } Chris@10: tim = timer_stop(USER_TIMER); Chris@10: if (verbose > 1) printf("write wisdom took %g seconds\n", tim); Chris@10: } Chris@10: Chris@10: static unsigned preserve_input_flags(bench_problem *p) Chris@10: { Chris@10: /* Chris@10: * fftw3 cannot preserve input for multidimensional c2r transforms. Chris@10: * Enforce FFTW_DESTROY_INPUT Chris@10: */ Chris@10: if (p->kind == PROBLEM_REAL && Chris@10: p->sign > 0 && Chris@10: !p->in_place && Chris@10: p->sz->rnk > 1) Chris@10: p->destroy_input = 1; Chris@10: Chris@10: if (p->destroy_input) Chris@10: return FFTW_DESTROY_INPUT; Chris@10: else Chris@10: return FFTW_PRESERVE_INPUT; Chris@10: } Chris@10: Chris@10: int can_do(bench_problem *p) Chris@10: { Chris@10: double tim; Chris@10: Chris@10: if (verbose > 2 && p->pstring) Chris@10: printf("Planning %s...\n", p->pstring); Chris@10: rdwisdom(); Chris@10: Chris@10: timer_start(USER_TIMER); Chris@10: the_plan = mkplan(p, preserve_input_flags(p) | the_flags | FFTW_ESTIMATE); Chris@10: tim = timer_stop(USER_TIMER); Chris@10: if (verbose > 2) printf("estimate-planner time: %g s\n", tim); Chris@10: Chris@10: if (the_plan) { Chris@10: FFTW(destroy_plan)(the_plan); Chris@10: return 1; Chris@10: } Chris@10: return 0; Chris@10: } Chris@10: Chris@10: void setup(bench_problem *p) Chris@10: { Chris@10: double tim; Chris@10: Chris@10: if (amnesia) { Chris@10: FFTW(forget_wisdom)(); Chris@10: havewisdom = 0; Chris@10: } Chris@10: Chris@10: /* Regression test: check that fftw_malloc exists and links Chris@10: * properly */ Chris@10: FFTW(free(FFTW(malloc(42)))); Chris@10: Chris@10: rdwisdom(); Chris@10: install_hook(); Chris@10: Chris@10: #ifdef HAVE_SMP Chris@10: if (verbose > 1 && nthreads > 1) printf("NTHREADS = %d\n", nthreads); Chris@10: #endif Chris@10: Chris@10: timer_start(USER_TIMER); Chris@10: the_plan = mkplan(p, preserve_input_flags(p) | the_flags); Chris@10: tim = timer_stop(USER_TIMER); Chris@10: if (verbose > 1) printf("planner time: %g s\n", tim); Chris@10: Chris@10: BENCH_ASSERT(the_plan); Chris@10: Chris@10: { Chris@10: double add, mul, nfma, cost, pcost; Chris@10: FFTW(flops)(the_plan, &add, &mul, &nfma); Chris@10: cost = FFTW(estimate_cost)(the_plan); Chris@10: pcost = FFTW(cost)(the_plan); Chris@10: if (verbose > 1) { Chris@10: FFTW(print_plan)(the_plan); Chris@10: printf("\n"); Chris@10: printf("flops: %0.0f add, %0.0f mul, %0.0f fma\n", Chris@10: add, mul, nfma); Chris@10: printf("estimated cost: %f, pcost = %f\n", cost, pcost); Chris@10: } Chris@10: } Chris@10: } Chris@10: Chris@10: Chris@10: void doit(int iter, bench_problem *p) Chris@10: { Chris@10: int i; Chris@10: FFTW(plan) q = the_plan; Chris@10: Chris@10: UNUSED(p); Chris@10: for (i = 0; i < iter; ++i) Chris@10: FFTW(execute)(q); Chris@10: } Chris@10: Chris@10: void done(bench_problem *p) Chris@10: { Chris@10: UNUSED(p); Chris@10: Chris@10: FFTW(destroy_plan)(the_plan); Chris@10: uninstall_hook(); Chris@10: } Chris@10: Chris@10: void cleanup(void) Chris@10: { Chris@10: initial_cleanup(); Chris@10: Chris@10: wrwisdom(); Chris@10: #ifdef HAVE_SMP Chris@10: FFTW(cleanup_threads)(); Chris@10: #else Chris@10: FFTW(cleanup)(); Chris@10: #endif Chris@10: Chris@10: # ifdef FFTW_DEBUG_MALLOC Chris@10: { Chris@10: /* undocumented memory checker */ Chris@10: FFTW_EXTERN void FFTW(malloc_print_minfo)(int v); Chris@10: FFTW(malloc_print_minfo)(verbose); Chris@10: } Chris@10: # endif Chris@10: Chris@10: final_cleanup(); Chris@10: }