/src/fftw3/kernel/timer.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2003, 2007-14 Matteo Frigo |
3 | | * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of the GNU General Public License as published by |
7 | | * the Free Software Foundation; either version 2 of the License, or |
8 | | * (at your option) any later version. |
9 | | * |
10 | | * This program is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | * GNU General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU General Public License |
16 | | * along with this program; if not, write to the Free Software |
17 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
18 | | * |
19 | | */ |
20 | | |
21 | | |
22 | | #include "kernel/ifftw.h" |
23 | | |
24 | | #ifdef HAVE_UNISTD_H |
25 | | # include <unistd.h> |
26 | | #endif |
27 | | |
28 | | #ifndef WITH_SLOW_TIMER |
29 | | # include "cycle.h" |
30 | | #endif |
31 | | |
32 | | #ifndef FFTW_TIME_LIMIT |
33 | 0 | #define FFTW_TIME_LIMIT 2.0 /* don't run for more than two seconds */ |
34 | | #endif |
35 | | |
36 | | /* the following code is disabled for now, because it seems to |
37 | | require that we #include <windows.h> in ifftw.h to |
38 | | typedef LARGE_INTEGER crude_time, and this pulls in the whole |
39 | | Windows universe and leads to namespace conflicts (unless |
40 | | we did some hack like assuming sizeof(LARGE_INTEGER) == sizeof(long long). |
41 | | gettimeofday is provided by MinGW, which we use to cross-compile |
42 | | FFTW for Windows, and this seems to work well enough */ |
43 | | #if 0 && (defined(__WIN32__) || defined(_WIN32) || defined(_WIN64)) |
44 | | crude_time X(get_crude_time)(void) |
45 | | { |
46 | | crude_time tv; |
47 | | QueryPerformanceCounter(&tv); |
48 | | return tv; |
49 | | } |
50 | | |
51 | | static double elapsed_since(crude_time t0) |
52 | | { |
53 | | crude_time t1, freq; |
54 | | QueryPerformanceCounter(&t1); |
55 | | QueryPerformanceFrequency(&freq); |
56 | | return (((double) (t1.QuadPart - t0.QuadPart))) / |
57 | | ((double) freq.QuadPart); |
58 | | } |
59 | | |
60 | | # define TIME_MIN_SEC 1.0e-2 |
61 | | |
62 | | #elif defined(HAVE_GETTIMEOFDAY) |
63 | | crude_time X(get_crude_time)(void) |
64 | 283 | { |
65 | 283 | crude_time tv; |
66 | 283 | gettimeofday(&tv, 0); |
67 | 283 | return tv; |
68 | 283 | } |
69 | | |
70 | 0 | #define elapsed_sec(t1,t0) ((double)(t1.tv_sec - t0.tv_sec) + \ |
71 | 0 | (double)(t1.tv_usec - t0.tv_usec) * 1.0E-6) |
72 | | |
73 | | static double elapsed_since(crude_time t0) |
74 | 0 | { |
75 | 0 | crude_time t1; |
76 | 0 | gettimeofday(&t1, 0); |
77 | 0 | return elapsed_sec(t1, t0); |
78 | 0 | } |
79 | | |
80 | | # define TIME_MIN_SEC 1.0e-3 |
81 | | |
82 | | #else /* !HAVE_GETTIMEOFDAY */ |
83 | | |
84 | | /* Note that the only system where we are likely to need to fall back |
85 | | on the clock() function is Windows, for which CLOCKS_PER_SEC is 1000 |
86 | | and thus the clock wraps once every 50 days. This should hopefully |
87 | | be longer than the time required to create any single plan! */ |
88 | | crude_time X(get_crude_time)(void) { return clock(); } |
89 | | |
90 | | #define elapsed_sec(t1,t0) ((double) ((t1) - (t0)) / CLOCKS_PER_SEC) |
91 | | |
92 | | static double elapsed_since(crude_time t0) |
93 | | { |
94 | | return elapsed_sec(clock(), t0); |
95 | | } |
96 | | |
97 | | # define TIME_MIN_SEC 2.0e-1 /* from fftw2 */ |
98 | | |
99 | | #endif /* !HAVE_GETTIMEOFDAY */ |
100 | | |
101 | | double X(elapsed_since)(const planner *plnr, const problem *p, crude_time t0) |
102 | 0 | { |
103 | 0 | double t = elapsed_since(t0); |
104 | 0 | if (plnr->cost_hook) |
105 | 0 | t = plnr->cost_hook(p, t, COST_MAX); |
106 | 0 | return t; |
107 | 0 | } |
108 | | |
109 | | #ifdef WITH_SLOW_TIMER |
110 | | /* excruciatingly slow; only use this if there is no choice! */ |
111 | | typedef crude_time ticks; |
112 | | # define getticks X(get_crude_time) |
113 | | # define elapsed(t1,t0) elapsed_sec(t1,t0) |
114 | | # define TIME_MIN TIME_MIN_SEC |
115 | | # define TIME_REPEAT 4 /* from fftw2 */ |
116 | | # define HAVE_TICK_COUNTER |
117 | | #endif |
118 | | |
119 | | #ifdef HAVE_TICK_COUNTER |
120 | | |
121 | | # ifndef TIME_MIN |
122 | | # define TIME_MIN 100.0 |
123 | | # endif |
124 | | |
125 | | # ifndef TIME_REPEAT |
126 | 0 | # define TIME_REPEAT 8 |
127 | | # endif |
128 | | |
129 | | static double measure(plan *pln, const problem *p, int iter) |
130 | 0 | { |
131 | 0 | ticks t0, t1; |
132 | 0 | int i; |
133 | |
|
134 | 0 | t0 = getticks(); |
135 | 0 | for (i = 0; i < iter; ++i) |
136 | 0 | pln->adt->solve(pln, p); |
137 | 0 | t1 = getticks(); |
138 | 0 | return elapsed(t1, t0); |
139 | 0 | } |
140 | | |
141 | | |
142 | | double X(measure_execution_time)(const planner *plnr, |
143 | | plan *pln, const problem *p) |
144 | 0 | { |
145 | 0 | int iter; |
146 | 0 | int repeat; |
147 | |
|
148 | 0 | X(plan_awake)(pln, AWAKE_ZERO); |
149 | 0 | p->adt->zero(p); |
150 | |
|
151 | 0 | start_over: |
152 | 0 | for (iter = 1; iter; iter *= 2) { |
153 | 0 | double tmin = 0; |
154 | 0 | int first = 1; |
155 | 0 | crude_time begin = X(get_crude_time)(); |
156 | | |
157 | | /* repeat the measurement TIME_REPEAT times */ |
158 | 0 | for (repeat = 0; repeat < TIME_REPEAT; ++repeat) { |
159 | 0 | double t = measure(pln, p, iter); |
160 | | |
161 | 0 | if (plnr->cost_hook) |
162 | 0 | t = plnr->cost_hook(p, t, COST_MAX); |
163 | 0 | if (t < 0) |
164 | 0 | goto start_over; |
165 | | |
166 | 0 | if (first || t < tmin) |
167 | 0 | tmin = t; |
168 | 0 | first = 0; |
169 | | |
170 | | /* do not run for too long */ |
171 | 0 | if (X(elapsed_since)(plnr, p, begin) > FFTW_TIME_LIMIT) |
172 | 0 | break; |
173 | 0 | } |
174 | | |
175 | 0 | if (tmin >= TIME_MIN) { |
176 | 0 | X(plan_awake)(pln, SLEEPY); |
177 | 0 | return tmin / (double) iter; |
178 | 0 | } |
179 | 0 | } |
180 | 0 | goto start_over; /* may happen if timer is screwed up */ |
181 | 0 | } |
182 | | |
183 | | #else /* no cycle counter */ |
184 | | |
185 | | double X(measure_execution_time)(const planner *plnr, |
186 | | plan *pln, const problem *p) |
187 | | { |
188 | | UNUSED(plnr); |
189 | | UNUSED(p); |
190 | | UNUSED(pln); |
191 | | return -1.0; |
192 | | } |
193 | | |
194 | | #endif |