-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdriver.c
420 lines (342 loc) · 11.5 KB
/
driver.c
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
/*******************************************************************
*
* driver.c - Driver program for Project 5
*
* In kernels.c, students will generate an arbitrary number of rotate and
* smooth test functions, which they then register with the driver
* program using the add_rotate_function() and add_smooth_function()
* functions.
* For Project 5 you will generate my_rotate and my_smooth functions.
* The driver program runs and measures the registered test functions
* and reports their performance.
*
* Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights
* reserved. May not be used, modified, or copied without permission.
*
********************************************************************/
#include <stdio.h>
#include "defs.h"
/* Team structure that identifies the students */
extern team_t team;
#define DIM_CNT 4
/* Misc constants */
#define BSIZE 32 /* cache block size in bytes */
#define MAX_DIM 4352 /* 4096 + 256 */
#define ODD_DIM 96 /* not a power of 2 */
/* fast versions of min and max */
#define min(a,b) (a < b ? a : b)
#define max(a,b) (a > b ? a : b)
/* The range of image dimensions that we will be testing */
static int test_dim_rotate[] = {512, 1024, 2048,4096};
static int test_dim_smooth[] = {256, 512, 1024, 2048};
/*
* An image is a dimxdim matrix of pixels stored in a 1D array. The
* data array holds three images (the input original, a copy of the original,
* and the output result array. There is also an additional BSIZE bytes
* of padding for alignment to cache block boundaries.
*/
static pixel data[(3*MAX_DIM*MAX_DIM) + (BSIZE/sizeof(pixel))];
/* Various image pointers */
static pixel *orig = NULL; /* original image */
static pixel *copy_of_orig = NULL; /* copy of original for checking result */
static pixel *result = NULL; /* result image */
/*
* random_in_interval - Returns random integer in interval [low, high)
*/
static int random_in_interval(int low, int high)
{
int size = high - low;
return (rand()% size) + low;
}
/*
* create - creates a dimxdim image aligned to a BSIZE byte boundary
*/
static void create(int dim)
{
int i, j;
/* Align the images to BSIZE byte boundaries */
orig = data;
while ((unsigned)orig % BSIZE){
//((char *)orig)++;
orig += sizeof(char);
}
result = orig + dim*dim;
copy_of_orig = result + dim*dim;
for (i = 0; i < dim; i++) {
for (j = 0; j < dim; j++) {
/* Original image initialized to random colors */
orig[RIDX(i,j,dim)].red = random_in_interval(0, 65536);
orig[RIDX(i,j,dim)].green = random_in_interval(0, 65536);
orig[RIDX(i,j,dim)].blue = random_in_interval(0, 65536);
/* Copy of original image for checking result */
copy_of_orig[RIDX(i,j,dim)].red = orig[RIDX(i,j,dim)].red;
copy_of_orig[RIDX(i,j,dim)].green = orig[RIDX(i,j,dim)].green;
copy_of_orig[RIDX(i,j,dim)].blue = orig[RIDX(i,j,dim)].blue;
/* Result image initialized to all black */
result[RIDX(i,j,dim)].red = 0;
result[RIDX(i,j,dim)].green = 0;
result[RIDX(i,j,dim)].blue = 0;
}
}
return;
}
/*
* compare_pixels - Returns 1 if the two arguments don't have same RGB
* values, 0 o.w.
*/
static int compare_pixels(pixel p1, pixel p2)
{
return
(p1.red != p2.red) ||
(p1.green != p2.green) ||
(p1.blue != p2.blue);
}
/* Make sure the orig array is unchanged */
static int check_orig(int dim)
{
int i, j;
for (i = 0; i < dim; i++)
for (j = 0; j < dim; j++)
if (compare_pixels(orig[RIDX(i,j,dim)], copy_of_orig[RIDX(i,j,dim)])) {
printf("\n");
printf("Error: Original image has been changed!\n");
return 1;
}
return 0;
}
/*
* check_rotate - Make sure the rotate actually works.
* The orig array should not have been tampered with!
*/
static int check_rotate(int dim)
{
int err = 0;
int i, j;
int badi = 0;
int badj = 0;
pixel orig_bad, res_bad;
/* return 1 if the original image has been changed */
if (check_orig(dim))
return 1;
for (i = 0; i < dim; i++)
for (j = 0; j < dim; j++)
if (compare_pixels(orig[RIDX(i,j,dim)],
result[RIDX(dim-1-j,i,dim)])) {
err++;
badi = i;
badj = j;
orig_bad = orig[RIDX(i,j,dim)];
res_bad = result[RIDX(dim-1-j,i,dim)];
}
if (err) {
printf("\n");
printf("ERROR: Dimension=%d, %d errors\n", dim, err);
printf("E.g., The following two pixels should have equal value:\n");
printf("src[%d][%d].{red,green,blue} = {%d,%d,%d}\n",
badi, badj, orig_bad.red, orig_bad.green, orig_bad.blue);
printf("dst[%d][%d].{red,green,blue} = {%d,%d,%d}\n",
(dim-1-badj), badi, res_bad.red, res_bad.green, res_bad.blue);
}
return err;
}
static pixel check_average(int dim, int i, int j, pixel *src) {
pixel result;
int num = 0;
int ii, jj;
int sum0, sum1, sum2;
int top_left_i, top_left_j;
int bottom_right_i, bottom_right_j;
top_left_i = max(i-1, 0);
top_left_j = max(j-1, 0);
bottom_right_i = min(i+1, dim-1);
bottom_right_j = min(j+1, dim-1);
sum0 = sum1 = sum2 = 0;
for(ii=top_left_i; ii <= bottom_right_i; ii++) {
for(jj=top_left_j; jj <= bottom_right_j; jj++) {
num++;
sum0 += (int) src[RIDX(ii,jj,dim)].red;
sum1 += (int) src[RIDX(ii,jj,dim)].green;
sum2 += (int) src[RIDX(ii,jj,dim)].blue;
}
}
result.red = (unsigned short) (sum0/num);
result.green = (unsigned short) (sum1/num);
result.blue = (unsigned short) (sum2/num);
return result;
}
/*
* check_smooth - Make sure the smooth function actually works. The
* orig array should not have been tampered with!
*/
static int check_smooth(int dim) {
int err = 0;
int i, j;
int badi = 0;
int badj = 0;
pixel right, wrong;
/* return 1 if original image has been changed */
if (check_orig(dim))
return 1;
for (i = 0; i < dim; i++) {
for (j = 0; j < dim; j++) {
pixel smoothed = check_average(dim, i, j, orig);
if (compare_pixels(result[RIDX(i,j,dim)], smoothed)) {
err++;
badi = i;
badj = j;
wrong = result[RIDX(i,j,dim)];
right = smoothed;
}
}
}
if (err) {
printf("\n");
printf("ERROR: Dimension=%d, %d errors\n", dim, err);
printf("E.g., \n");
printf("You have dst[%d][%d].{red,green,blue} = {%d,%d,%d}\n",
badi, badj, wrong.red, wrong.green, wrong.blue);
printf("It should be dst[%d][%d].{red,green,blue} = {%d,%d,%d}\n",
badi, badj, right.red, right.green, right.blue);
}
return err;
}
void run_rotate_benchmark(int dim)
{
int temp_int;
unsigned long long temp_ull;
my_rotate(dim, orig, result, &temp_int, &temp_ull);
}
void test_rotate()
{
int test_num;
int i=0;
int naive_time_rusage=0;
int naive_ave_time_rusage=0;
unsigned long long naive_time_rdtsc = 0;
unsigned long long naive_ave_time_rdtsc = 0;
int my_time_rusage=0;
int my_ave_time_rusage=0;
unsigned long long my_time_rdtsc = 0;
unsigned long long my_ave_time_rdtsc = 0;
char dim_string[] = "Dimension";
char naive_string[] = "naive_rotate";
char my_string[] = "my_rotate";
char rusage_header[] = "Time in milliseconds";
char rdtsc_header[] = "Cycles used";
printf("\nTesting Rotate:\n");
printf("%-10s%-26s%-13s\n","",rusage_header,rdtsc_header);
printf("==========================================================\n");
printf("%-10s%-13s%-13s%-13s%-13s\n",dim_string,naive_string,my_string,naive_string,my_string);
printf("==========================================================\n");
for (test_num = 0; test_num < DIM_CNT; test_num++)
{
int dim;
/* Create a test image of the required dimension */
dim = test_dim_rotate[test_num];
create(dim);
/* Check that the code works */
run_rotate_benchmark(dim);
if (check_rotate(dim))
{
printf("Benchmark \"rotate()\" failed correctness check for dimension %d.\n", dim);
return;
}
create(dim);
/* The code below tests performance of the rotate algorithms. It measures performance using three different system utilities and prints these out in the output */
/* First measure performance of the naive rotate algorithm */
for (i=0;i<10;i++){
naive_rotate(dim,orig,result,&naive_time_rusage,&naive_time_rdtsc);
naive_ave_time_rusage += naive_time_rusage;
naive_ave_time_rdtsc += naive_time_rdtsc;
}
naive_ave_time_rusage = naive_ave_time_rusage / 10;
naive_ave_time_rdtsc = naive_ave_time_rdtsc / 10;
/* measure performance of your implementation */
for (i=0;i<10;i++){
my_rotate(dim,orig,result,&my_time_rusage,&my_time_rdtsc);
my_ave_time_rusage += my_time_rusage;
my_ave_time_rdtsc += my_time_rdtsc;
}
my_ave_time_rusage = my_ave_time_rusage / 10;
my_ave_time_rdtsc = my_ave_time_rdtsc / 10;
printf("%-10d%-13d%-13d%-13llu%-13llu\n",dim,naive_ave_time_rusage,my_ave_time_rusage, naive_ave_time_rdtsc, my_ave_time_rdtsc);
}
return;
}
void run_smooth_benchmark(int dim)
{
int temp_int;
unsigned long long temp_ull;
my_smooth(dim, orig, result, &temp_int, &temp_ull);
}
void test_smooth()
{
int test_num;
int i=0;
int naive_time_rusage=0;
int naive_ave_time_rusage=0;
unsigned long long naive_time_rdtsc = 0;
unsigned long long naive_ave_time_rdtsc = 0;
int my_time_rusage=0;
int my_ave_time_rusage=0;
unsigned long long my_time_rdtsc = 0;
unsigned long long my_ave_time_rdtsc = 0;
char dim_string[] = "Dimension";
char naive_string[] = "naive_smooth";
char my_string[] = "my_smooth";
char rusage_header[] = "Time in milliseconds";
char rdtsc_header[] = "Cycles used";
printf("\nTesting Smooth:\n");
printf("%-10s%-26s%-13s\n","",rusage_header,rdtsc_header);
printf("==========================================================\n");
printf("%-10s%-13s%-13s%-13s%-13s\n",dim_string,naive_string,my_string,naive_string,my_string);
printf("==========================================================\n");
for(test_num=0; test_num < DIM_CNT; test_num++)
{
int dim;
/* Create a test image of the required dimension */
dim = test_dim_smooth[test_num];
create(dim);
/* Check that the code works */
run_smooth_benchmark(dim);
if (check_smooth(dim)) {
printf("Benchmark \"smooth()\" failed correctness check for dimension %d.\n", dim);
return;
}
create(dim);
/* The code below tests performance of the rotate algorithms. It measures performance using three different system utilities and prints these out in the output */
/* First measure performance of the naive smooth algorithm */
for (i=0;i<10;i++){
naive_smooth(dim,orig,result,&naive_time_rusage,&naive_time_rdtsc);
naive_ave_time_rusage += naive_time_rusage;
naive_ave_time_rdtsc += naive_time_rdtsc;
}
naive_ave_time_rusage = naive_ave_time_rusage / 10;
naive_ave_time_rdtsc = naive_ave_time_rdtsc / 10;
/* measure performance of your implementtion for the smooth algorithm */
for (i=0;i<10;i++){
my_smooth(dim,orig,result,&my_time_rusage,&my_time_rdtsc);
my_ave_time_rusage += my_time_rusage;
my_ave_time_rdtsc += my_time_rdtsc;
}
my_ave_time_rusage = my_ave_time_rusage / 10;
my_ave_time_rdtsc = my_ave_time_rdtsc / 10;
printf("%-10d%-13d%-13d%-13llu%-13llu\n",dim,naive_ave_time_rusage,my_ave_time_rusage, naive_ave_time_rdtsc, my_ave_time_rdtsc);
}
return;
}
void usage(char *progname)
{
fprintf(stderr, "Usage: %s \n", progname);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -h Print this message\n");
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
int seed = 1729;
srand(seed);
test_rotate();
test_smooth();
return 0;
}