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