1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
/* 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"
#if defined(HAVE_THREADS) || defined(HAVE_OPENMP)
#define HAVE_SMP
#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 */
#if HAVE_CELL
extern void FFTW(cell_set_nspe)(int); /* in fftw-cell.h */
#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;
#if HAVE_CELL
else if (sscanf(arg, "nspe=%d", &x) == 1) FFTW(cell_set_nspe)(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
BENCH_ASSERT(FFTW(init_threads)());
FFTW(plan_with_nthreads)(nthreads);
#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;
FFTW(flops)(the_plan, &add, &mul, &nfma);
cost = FFTW(estimate_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\n", cost);
}
}
}
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();
}
|