Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
141 Kevin 1
/*
2
 * fcyc.c - Estimate the time (in CPU cycles) used by a function f 
3
 * 
4
 * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
5
 * May not be used, modified, or copied without permission.
6
 *
7
 * Uses the cycle timer routines in clock.c to estimate the
8
 * the time in CPU cycles for a function f.
9
 */
10
#include <stdlib.h>
11
#include <sys/times.h>
12
#include <stdio.h>
13
 
14
#include "fcyc.h"
15
#include "clock.h"
16
 
17
/* Default values */
18
#define K 3                  /* Value of K in K-best scheme */
19
#define MAXSAMPLES 20        /* Give up after MAXSAMPLES */
20
#define EPSILON 0.01         /* K samples should be EPSILON of each other*/
21
#define COMPENSATE 0         /* 1-> try to compensate for clock ticks */
22
#define CLEAR_CACHE 0        /* Clear cache before running test function */
23
#define CACHE_BYTES (1<<19)  /* Max cache size in bytes */
24
#define CACHE_BLOCK 32       /* Cache block size in bytes */
25
 
26
static int kbest = K;
27
static int maxsamples = MAXSAMPLES;
28
static double epsilon = EPSILON;
29
static int compensate = COMPENSATE;
30
static int clear_cache = CLEAR_CACHE;
31
static int cache_bytes = CACHE_BYTES;
32
static int cache_block = CACHE_BLOCK;
33
 
34
static int *cache_buf = NULL;
35
 
36
static double *values = NULL;
37
static int samplecount = 0;
38
 
39
/* for debugging only */
40
#define KEEP_VALS 0
41
#define KEEP_SAMPLES 0
42
 
43
#if KEEP_SAMPLES
44
static double *samples = NULL;
45
#endif
46
 
47
/* 
48
 * init_sampler - Start new sampling process 
49
 */
50
static void init_sampler()
51
{
52
    if (values)
53
	free(values);
54
    values = calloc(kbest, sizeof(double));
55
#if KEEP_SAMPLES
56
    if (samples)
57
	free(samples);
58
    /* Allocate extra for wraparound analysis */
59
    samples = calloc(maxsamples+kbest, sizeof(double));
60
#endif
61
    samplecount = 0;
62
}
63
 
64
/* 
65
 * add_sample - Add new sample  
66
 */
67
static void add_sample(double val)
68
{
69
    int pos = 0;
70
    if (samplecount < kbest) {
71
	pos = samplecount;
72
	values[pos] = val;
73
    } else if (val < values[kbest-1]) {
74
	pos = kbest-1;
75
	values[pos] = val;
76
    }
77
#if KEEP_SAMPLES
78
    samples[samplecount] = val;
79
#endif
80
    samplecount++;
81
    /* Insertion sort */
82
    while (pos > 0 && values[pos-1] > values[pos]) {
83
	double temp = values[pos-1];
84
	values[pos-1] = values[pos];
85
	values[pos] = temp;
86
	pos--;
87
    }
88
}
89
 
90
/* 
91
 * has_converged- Have kbest minimum measurements converged within epsilon? 
92
 */
93
static int has_converged()
94
{
95
    return
96
	(samplecount >= kbest) &&
97
	((1 + epsilon)*values[0] >= values[kbest-1]);
98
}
99
 
100
/* 
101
 * clear - Code to clear cache 
102
 */
103
static volatile int sink = 0;
104
 
105
static void clear()
106
{
107
    int x = sink;
108
    int *cptr, *cend;
109
    int incr = cache_block/sizeof(int);
110
    if (!cache_buf) {
111
	cache_buf = malloc(cache_bytes);
112
	if (!cache_buf) {
113
	    fprintf(stderr, "Fatal error.  Malloc returned null when trying to clear cache\n");
114
	    exit(1);
115
	}
116
    }
117
    cptr = (int *) cache_buf;
118
    cend = cptr + cache_bytes/sizeof(int);
119
    while (cptr < cend) {
120
	x += *cptr;
121
	cptr += incr;
122
    }
123
    sink = x;
124
}
125
 
126
/*
127
 * fcyc - Use K-best scheme to estimate the running time of function f
128
 */
129
double fcyc(test_funct f, void *argp)
130
{
131
    double result;
132
    init_sampler();
133
    if (compensate) {
134
	do {
135
	    double cyc;
136
	    if (clear_cache)
137
		clear();
138
	    start_comp_counter();
139
	    f(argp);
140
	    cyc = get_comp_counter();
141
	    add_sample(cyc);
142
	} while (!has_converged() && samplecount < maxsamples);
143
    } else {
144
	do {
145
	    double cyc;
146
	    if (clear_cache)
147
		clear();
148
	    start_counter();
149
	    f(argp);
150
	    cyc = get_counter();
151
	    add_sample(cyc);
152
	} while (!has_converged() && samplecount < maxsamples);
153
    }
154
#ifdef DEBUG
155
    {
156
	int i;
157
	printf(" %d smallest values: [", kbest);
158
	for (i = 0; i < kbest; i++)
159
	    printf("%.0f%s", values[i], i==kbest-1 ? "]\n" : ", ");
160
    }
161
#endif
162
    result = values[0];
163
#if !KEEP_VALS
164
    free(values); 
165
    values = NULL;
166
#endif
167
    return result;  
168
}
169
 
170
 
171
/*************************************************************
172
 * Set the various parameters used by the measurement routines 
173
 ************************************************************/
174
 
175
/* 
176
 * set_fcyc_clear_cache - When set, will run code to clear cache 
177
 *     before each measurement. 
178
 *     Default = 0
179
 */
180
void set_fcyc_clear_cache(int clear)
181
{
182
    clear_cache = clear;
183
}
184
 
185
/* 
186
 * set_fcyc_cache_size - Set size of cache to use when clearing cache 
187
 *     Default = 1<<19 (512KB)
188
 */
189
void set_fcyc_cache_size(int bytes)
190
{
191
    if (bytes != cache_bytes) {
192
	cache_bytes = bytes;
193
	if (cache_buf) {
194
	    free(cache_buf);
195
	    cache_buf = NULL;
196
	}
197
    }
198
}
199
 
200
/* 
201
 * set_fcyc_cache_block - Set size of cache block 
202
 *     Default = 32
203
 */
204
void set_fcyc_cache_block(int bytes) {
205
    cache_block = bytes;
206
}
207
 
208
 
209
/* 
210
 * set_fcyc_compensate- When set, will attempt to compensate for 
211
 *     timer interrupt overhead 
212
 *     Default = 0
213
 */
214
void set_fcyc_compensate(int compensate_arg)
215
{
216
    compensate = compensate_arg;
217
}
218
 
219
/* 
220
 * set_fcyc_k - Value of K in K-best measurement scheme
221
 *     Default = 3
222
 */
223
void set_fcyc_k(int k)
224
{
225
    kbest = k;
226
}
227
 
228
/* 
229
 * set_fcyc_maxsamples - Maximum number of samples attempting to find 
230
 *     K-best within some tolerance.
231
 *     When exceeded, just return best sample found.
232
 *     Default = 20
233
 */
234
void set_fcyc_maxsamples(int maxsamples_arg)
235
{
236
    maxsamples = maxsamples_arg;
237
}
238
 
239
/* 
240
 * set_fcyc_epsilon - Tolerance required for K-best
241
 *     Default = 0.01
242
 */
243
void set_fcyc_epsilon(double epsilon_arg)
244
{
245
    epsilon = epsilon_arg;
246
}
247
 
248
 
249
 
250
 
251