~ubuntu-branches/ubuntu/raring/fftw3/raring-proposed

« back to all changes in this revision

Viewing changes to libbench2/timer.c

  • Committer: Bazaar Package Importer
  • Author(s): Paul Brossier
  • Date: 2006-05-31 13:44:05 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060531134405-ol9hrbg6bh81sg0c
Tags: 3.1.1-1
* New upstream release (closes: #350327, #338487, #338501)
* Add --enable-portable-binary to use -mtune instead of -march
* Use --with-gcc-arch=G5 / pentium4 on powerpc / i386
* Updated Standards-Version

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 *
19
19
 */
20
20
 
21
 
/* $Id: timer.c,v 1.6 2003/05/12 22:22:16 stevenj Exp $ */
 
21
/* $Id: timer.c,v 1.13 2006-01-30 16:09:32 athena Exp $ */
22
22
 
23
23
#include "bench.h"
24
24
#include <stdio.h>
44
44
double time_min;
45
45
int time_repeat;
46
46
 
47
 
#if defined(HAVE_GETTIMEOFDAY) && !defined(HAVE_TIMER)
48
 
typedef struct timeval mytime;
49
 
 
50
 
static mytime get_time(void)
51
 
{
52
 
     struct timeval tv;
53
 
     gettimeofday(&tv, 0);
54
 
     return tv;
55
 
}
56
 
 
57
 
static double elapsed(mytime t1, mytime t0)
58
 
{
59
 
     return (double)(t1.tv_sec - t0.tv_sec) +
60
 
          (double)(t1.tv_usec - t0.tv_usec) * 1.0E-6;
61
 
}
62
 
 
63
 
#define HAVE_TIMER
64
 
#endif
65
 
 
66
 
#if !defined(HAVE_TIMER) && (defined(__WIN32__) || defined(_WIN32) || defined(_WINDOWS))
 
47
#if !defined(HAVE_TIMER) && (defined(__WIN32__) || defined(_WIN32) || defined(_WINDOWS) || defined(__CYGWIN__))
67
48
#include <windows.h>
68
49
typedef LARGE_INTEGER mytime;
69
50
 
85
66
#define HAVE_TIMER
86
67
#endif
87
68
 
 
69
 
 
70
#if defined(HAVE_GETTIMEOFDAY) && !defined(HAVE_TIMER)
 
71
typedef struct timeval mytime;
 
72
 
 
73
static mytime get_time(void)
 
74
{
 
75
     struct timeval tv;
 
76
     gettimeofday(&tv, 0);
 
77
     return tv;
 
78
}
 
79
 
 
80
static double elapsed(mytime t1, mytime t0)
 
81
{
 
82
     return (double)(t1.tv_sec - t0.tv_sec) +
 
83
          (double)(t1.tv_usec - t0.tv_usec) * 1.0E-6;
 
84
}
 
85
 
 
86
#define HAVE_TIMER
 
87
#endif
 
88
 
88
89
#ifndef HAVE_TIMER
89
90
#error "timer not defined"
90
91
#endif
91
92
 
92
 
/*
93
 
 * Routines to calibrate the slow timer.  Derived from Larry McVoy's
94
 
 * lmbench, distributed under the GNU General Public License.
95
 
 *
96
 
 *
97
 
 
98
 
From: "Staelin, Carl" <staelin@exch.hpl.hp.com>
99
 
To: Larry McVoy <lm@bitmover.com>, athena@fftw.org, stevenj@alum.mit.edu
100
 
Date: Sat, 7 Jul 2001 23:50:49 -0700 
101
 
 
102
 
Matteo,
103
 
 
104
 
You have my permission to use the enough_duration, 
105
 
duration, time_N, find_N, test_time, and 
106
 
compute_enough from lib_timing.c routines
107
 
under the LGPL license.  You may also use the
108
 
BENCH* macros from bench.h under the LGPL
109
 
if you find them useful.
110
 
 
111
 
*/
112
 
 
113
 
 
114
 
typedef char *TYPE;
115
 
static const double tmin_try = 1.0e-6; /* seconds */
116
93
static const double tmax_try = 1.0;    /* seconds */
117
 
static const double tolerance = 0.001;
118
 
 
119
 
static TYPE **work(int n, TYPE **p)
120
 
{
121
 
#define ENOUGH_DURATION_TEN(one)        one one one one one one one one one one
122
 
     while (n-- > 0) {
123
 
          ENOUGH_DURATION_TEN(p = (TYPE **) *p;);
124
 
     }
125
 
     return (p);
126
 
}
127
 
 
128
 
/* do N units of work */
129
 
static double duration(int n)
130
 
{
131
 
     TYPE   *x = (TYPE *)&x;
132
 
     TYPE  **p = (TYPE **)&x;
 
94
static const int nmin = 128, nmax = 133;
 
95
 
 
96
static double time_one(int n)
 
97
{
 
98
     float X[16], Y[16];
 
99
     int i;
133
100
     mytime t0, t1;
134
101
 
 
102
     for (i = 0; i < 16; ++i)
 
103
          X[i] = 0;
 
104
 
135
105
     t0 = get_time();
136
 
     p = work(n, p);
 
106
     for (i = 0; i < n; ++i)
 
107
          bench_fft8(X, X+1, Y, Y+1, 2, 2);
137
108
     t1 = get_time();
138
109
     return (elapsed(t1, t0));
139
110
}
143
114
     int     i;
144
115
     double  tmin;
145
116
 
146
 
     tmin = duration(n);
 
117
     tmin = time_one(n);
147
118
     for (i = 1; i < time_repeat; ++i) {
148
 
          double t = duration(n);
 
119
          double t = time_one(n);
149
120
          if (t < tmin)
150
121
               tmin = t;
151
122
     }
152
123
     return tmin;
153
124
}
154
125
 
155
 
/* return the amount of work needed to run TMIN seconds */
156
 
static int find_n(double tmin)
 
126
static int good_enough_p(int n, double *tp)
157
127
{
158
 
     int tries;
159
 
     int n = 10000;
160
 
     double t;
161
 
        
162
 
     t = time_n(n);
163
 
 
164
 
     for (tries = 0; tries < 10; ++tries) {
165
 
          if (0.98 * tmin < t && t < 1.02 * tmin)
166
 
               return n;
167
 
          if (t < tmin_try)
168
 
               n *= 10;
169
 
          else {
170
 
               double k = n;
171
 
 
172
 
               k /= t;
173
 
               k *= tmin;
174
 
               n = (int) (k + 1);
 
128
     int i;
 
129
     double t = 0.0;
 
130
 
 
131
     /* vary nmin and see if time scales proportionally */
 
132
     for (i = nmin; i < nmax; ++i) {
 
133
          double t1 = time_n(n * i);
 
134
 
 
135
          if (t1 <= 0)
 
136
               return 0; /* not enough resolution */
 
137
 
 
138
          if (t1 >= tmax_try) {
 
139
               t = t1;
 
140
               break;
175
141
          }
176
 
          t = time_n(n);
177
 
     }
178
 
     return (-1);
179
 
}
180
 
 
181
 
/* Verify that small modifications affect the runtime proportionally */
182
 
static int acceptable(double tmin)
183
 
{
184
 
     int n;
185
 
     unsigned i;
186
 
     static const double test_points[] = { 1.015, 1.02, 1.035 };
187
 
     double baseline;
188
 
     
189
 
     n = find_n(tmin);
190
 
     if (n <= 0)
191
 
          return 0;
192
 
 
193
 
     baseline = time_n(n);
194
 
 
195
 
     for (i = 0; i < sizeof(test_points) / sizeof(double); ++i) {
196
 
          double usecs = time_n((int)((double) n * test_points[i]));
197
 
          double expected = baseline * test_points[i];
198
 
          double diff = expected > usecs ? expected - usecs : usecs - expected;
199
 
          if (diff / expected > tolerance)
200
 
               return 0;
201
 
     }
 
142
 
 
143
          t = (i == nmin) ? t1 : t;
 
144
 
 
145
          if (t1 >= (t * (i + 0.5) / nmin))
 
146
               return 0;
 
147
 
 
148
          if (t1 <= (t * (i - 0.5) / nmin))
 
149
               return 0;
 
150
     }
 
151
 
 
152
     *tp = t;
202
153
     return 1;
203
154
}
204
155
 
205
156
static double calibrate(void)
206
157
{
207
 
     double tmin;
208
 
 
209
 
     for (tmin = tmin_try; tmin < tmax_try && !acceptable(tmin); tmin *= 2.0)
210
 
          ;
211
 
     return tmin;
 
158
     double t = tmax_try;
 
159
     int n;
 
160
 
 
161
     for (n = 1; n < (1 << 20); n += n) 
 
162
          if (good_enough_p(n, &t))
 
163
               break;
 
164
 
 
165
     return t;
212
166
}
213
167
 
214
168
 
230
184
          time_min = calibrate();
231
185
}
232
186
 
233
 
static mytime t0;
 
187
static mytime t0[BENCH_NTIMERS];
234
188
 
235
 
void timer_start(void)
 
189
void timer_start(int n)
236
190
{
237
 
     t0 = get_time();
 
191
     BENCH_ASSERT(n >= 0 && n < BENCH_NTIMERS);
 
192
     t0[n] = get_time();
238
193
}
239
194
 
240
 
double timer_stop(void)
 
195
double timer_stop(int n)
241
196
{
242
197
     mytime t1;
 
198
     BENCH_ASSERT(n >= 0 && n < BENCH_NTIMERS);
243
199
     t1 = get_time();
244
 
     return elapsed(t1, t0);
 
200
     return elapsed(t1, t0[n]);
245
201
}
246
202