Chris@10: /* Chris@10: * Copyright (c) 2003, 2007-11 Matteo Frigo Chris@10: * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology Chris@10: * Chris@10: * This program is free software; you can redistribute it and/or modify Chris@10: * it under the terms of the GNU General Public License as published by Chris@10: * the Free Software Foundation; either version 2 of the License, or Chris@10: * (at your option) any later version. Chris@10: * Chris@10: * This program is distributed in the hope that it will be useful, Chris@10: * but WITHOUT ANY WARRANTY; without even the implied warranty of Chris@10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Chris@10: * GNU General Public License for more details. Chris@10: * Chris@10: * You should have received a copy of the GNU General Public License Chris@10: * along with this program; if not, write to the Free Software Chris@10: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Chris@10: * Chris@10: */ Chris@10: Chris@10: Chris@10: #include "ifftw.h" Chris@10: Chris@10: #ifdef HAVE_UNISTD_H Chris@10: # include Chris@10: #endif Chris@10: Chris@10: #ifndef WITH_SLOW_TIMER Chris@10: # include "cycle.h" Chris@10: #endif Chris@10: Chris@10: #ifndef FFTW_TIME_LIMIT Chris@10: #define FFTW_TIME_LIMIT 2.0 /* don't run for more than two seconds */ Chris@10: #endif Chris@10: Chris@10: /* the following code is disabled for now, because it seems to Chris@10: require that we #include in ifftw.h to Chris@10: typedef LARGE_INTEGER crude_time, and this pulls in the whole Chris@10: Windows universe and leads to namespace conflicts (unless Chris@10: we did some hack like assuming sizeof(LARGE_INTEGER) == sizeof(long long). Chris@10: gettimeofday is provided by MinGW, which we use to cross-compile Chris@10: FFTW for Windows, and this seems to work well enough */ Chris@10: #if 0 && (defined(__WIN32__) || defined(_WIN32) || defined(_WIN64)) Chris@10: crude_time X(get_crude_time)(void) Chris@10: { Chris@10: crude_time tv; Chris@10: QueryPerformanceCounter(&tv); Chris@10: return tv; Chris@10: } Chris@10: Chris@10: static double elapsed_since(crude_time t0) Chris@10: { Chris@10: crude_time t1, freq; Chris@10: QueryPerformanceCounter(&t1); Chris@10: QueryPerformanceFrequency(&freq); Chris@10: return (((double) (t1.QuadPart - t0.QuadPart))) / Chris@10: ((double) freq.QuadPart); Chris@10: } Chris@10: Chris@10: # define TIME_MIN_SEC 1.0e-2 Chris@10: Chris@10: #elif defined(HAVE_GETTIMEOFDAY) Chris@10: crude_time X(get_crude_time)(void) Chris@10: { Chris@10: crude_time tv; Chris@10: gettimeofday(&tv, 0); Chris@10: return tv; Chris@10: } Chris@10: Chris@10: #define elapsed_sec(t1,t0) ((double)(t1.tv_sec - t0.tv_sec) + \ Chris@10: (double)(t1.tv_usec - t0.tv_usec) * 1.0E-6) Chris@10: Chris@10: static double elapsed_since(crude_time t0) Chris@10: { Chris@10: crude_time t1; Chris@10: gettimeofday(&t1, 0); Chris@10: return elapsed_sec(t1, t0); Chris@10: } Chris@10: Chris@10: # define TIME_MIN_SEC 1.0e-3 Chris@10: Chris@10: #else /* !HAVE_GETTIMEOFDAY */ Chris@10: Chris@10: /* Note that the only system where we are likely to need to fall back Chris@10: on the clock() function is Windows, for which CLOCKS_PER_SEC is 1000 Chris@10: and thus the clock wraps once every 50 days. This should hopefully Chris@10: be longer than the time required to create any single plan! */ Chris@10: crude_time X(get_crude_time)(void) { return clock(); } Chris@10: Chris@10: #define elapsed_sec(t1,t0) ((double) ((t1) - (t0)) / CLOCKS_PER_SEC) Chris@10: Chris@10: static double elapsed_since(crude_time t0) Chris@10: { Chris@10: return elapsed_sec(clock(), t0); Chris@10: } Chris@10: Chris@10: # define TIME_MIN_SEC 2.0e-1 /* from fftw2 */ Chris@10: Chris@10: #endif /* !HAVE_GETTIMEOFDAY */ Chris@10: Chris@10: double X(elapsed_since)(const planner *plnr, const problem *p, crude_time t0) Chris@10: { Chris@10: double t = elapsed_since(t0); Chris@10: if (plnr->cost_hook) Chris@10: t = plnr->cost_hook(p, t, COST_MAX); Chris@10: return t; Chris@10: } Chris@10: Chris@10: #ifdef WITH_SLOW_TIMER Chris@10: /* excruciatingly slow; only use this if there is no choice! */ Chris@10: typedef crude_time ticks; Chris@10: # define getticks X(get_crude_time) Chris@10: # define elapsed(t1,t0) elapsed_sec(t1,t0) Chris@10: # define TIME_MIN TIME_MIN_SEC Chris@10: # define TIME_REPEAT 4 /* from fftw2 */ Chris@10: # define HAVE_TICK_COUNTER Chris@10: #endif Chris@10: Chris@10: #ifdef HAVE_TICK_COUNTER Chris@10: Chris@10: # ifndef TIME_MIN Chris@10: # define TIME_MIN 100.0 Chris@10: # endif Chris@10: Chris@10: # ifndef TIME_REPEAT Chris@10: # define TIME_REPEAT 8 Chris@10: # endif Chris@10: Chris@10: static double measure(plan *pln, const problem *p, int iter) Chris@10: { Chris@10: ticks t0, t1; Chris@10: int i; Chris@10: Chris@10: t0 = getticks(); Chris@10: for (i = 0; i < iter; ++i) Chris@10: pln->adt->solve(pln, p); Chris@10: t1 = getticks(); Chris@10: return elapsed(t1, t0); Chris@10: } Chris@10: Chris@10: Chris@10: double X(measure_execution_time)(const planner *plnr, Chris@10: plan *pln, const problem *p) Chris@10: { Chris@10: int iter; Chris@10: int repeat; Chris@10: Chris@10: X(plan_awake)(pln, AWAKE_ZERO); Chris@10: p->adt->zero(p); Chris@10: Chris@10: start_over: Chris@10: for (iter = 1; iter; iter *= 2) { Chris@10: double tmin = 0; Chris@10: int first = 1; Chris@10: crude_time begin = X(get_crude_time)(); Chris@10: Chris@10: /* repeat the measurement TIME_REPEAT times */ Chris@10: for (repeat = 0; repeat < TIME_REPEAT; ++repeat) { Chris@10: double t = measure(pln, p, iter); Chris@10: Chris@10: if (plnr->cost_hook) Chris@10: t = plnr->cost_hook(p, t, COST_MAX); Chris@10: if (t < 0) Chris@10: goto start_over; Chris@10: Chris@10: if (first || t < tmin) Chris@10: tmin = t; Chris@10: first = 0; Chris@10: Chris@10: /* do not run for too long */ Chris@10: if (X(elapsed_since)(plnr, p, begin) > FFTW_TIME_LIMIT) Chris@10: break; Chris@10: } Chris@10: Chris@10: if (tmin >= TIME_MIN) { Chris@10: X(plan_awake)(pln, SLEEPY); Chris@10: return tmin / (double) iter; Chris@10: } Chris@10: } Chris@10: goto start_over; /* may happen if timer is screwed up */ Chris@10: } Chris@10: Chris@10: #else /* no cycle counter */ Chris@10: Chris@10: double X(measure_execution_time)(const planner *plnr, Chris@10: plan *pln, const problem *p) Chris@10: { Chris@10: UNUSED(plnr); Chris@10: UNUSED(p); Chris@10: UNUSED(pln); Chris@10: return -1.0; Chris@10: } Chris@10: Chris@10: #endif