Files
csapp2025/perflab/poly/cpe.c
2025-04-12 10:18:45 +08:00

118 lines
3.3 KiB
C

/* Compute CPE for function */
#include <stdlib.h>
#include <stdio.h>
#include "fcyc.h"
#include "cpe.h"
#include "lsquare.h"
#include "clock.h"
/* Find number of cycles taken by function.
Do this by running number of trials until best two within TOL of
each other
*/
double measure_function(elem_fun_t f, int cnt)
{
/* Need to fudge fact that fcyc wants a function taking an
long int *, while our function takes an long int */
test_funct tf = (test_funct) f;
return fcyc(tf, (int *) (int) cnt);
}
#define MAXCNT 100
#define LIM RAND_MAX
/* LCM of unrolling degree */
#ifdef USE_UNI
#define UNROLL 32
#else /* USE_UNI */
#define UNROLL 1
#endif
static long int get_cnt(long int index, long int samples,
long int maxcnt, sample_t smethod, double bias)
{
long int mincnt = (long int) (bias*maxcnt);
double weight;
long int val;
switch (smethod) {
case UNI_SAMPLE:
weight = (double) index/(samples - 1);
break;
case RAN_SAMPLE:
weight = (double) (rand() % LIM) / (double) (LIM-1);
break;
default:
fprintf(stderr, "Undefined sampling method %d\n", smethod);
exit(1);
}
val = mincnt + weight*(maxcnt-mincnt);
return UNROLL * (val/UNROLL);
}
#define SEED 31415
/* Find cpe for function f, which allows cnt up to maxcnt, using
specified number of sample points.
If data_file, then print data so that can plot points with Excel
smethod determines method for generating samples
*/
double find_cpe_full(elem_fun_t f, long int maxcnt, long int samples, FILE *data_file,
sample_t smethod, double bias, long int verbose)
{
long int i;
long int cnt;
double cpe;
double overhead = 0;
double *cnt_val = calloc(samples, sizeof(double));
double *cycle_val = calloc(samples, sizeof(double));
/* Do the samples */
srand(SEED);
for (i = 0; i < samples; i++) {
cnt = get_cnt(i, samples, maxcnt, smethod, bias);
cnt_val[i] = cnt;
cycle_val[i] = measure_function(f, cnt);
if (cycle_val[i] < 1.0) {
fprintf(stderr, "Got %.2f cycles for count %ld\n", cycle_val[i], cnt);
}
}
/* Fit data */
cpe = ls_slope(cnt_val, cycle_val, samples);
if (data_file)
overhead = ls_intercept(cnt_val, cycle_val, samples);
if (data_file && verbose > 1) {
/* Print x values */
fprintf(data_file, "Cnt\t0");
for (i = 0; i < samples; i++)
fprintf(data_file, "\t%.0f", cnt_val[i]);
fprintf(data_file, "\n");
/* Print y values */
fprintf(data_file, "Cycs.\t");
for (i = 0; i < samples; i++)
fprintf(data_file, "\t%.2f", cycle_val[i]);
fprintf(data_file, "\n");
/* Print ax*b values */
fprintf(data_file, "Interp.\t%.2f", overhead);
for (i = 0; i < samples; i++)
fprintf(data_file, "\t%.2f", cpe*cnt_val[i]+overhead);
fprintf(data_file, "\n");
}
if (data_file && verbose) {
/* Print results */
fprintf(data_file, "cpe\t%.2f\tovhd\t%.2f\tavgerr\t\\%.3f\tmaxerr\t\\%.3f\n",
cpe, overhead,
ls_error(cnt_val, cycle_val, samples, LS_AVG),
ls_error(cnt_val, cycle_val, samples, LS_MAX));
}
free(cnt_val);
free(cycle_val);
return cpe;
}
/* Use default parameters */
double find_cpe(elem_fun_t f, int maxcnt)
{
return find_cpe_full(f, maxcnt, 100, stdout, RAN_SAMPLE, 0.3, 0);
}