3 #include "config_portability.h"
4 #include <stdio.h> /* fprintf() fflush() */
5 #include "strutil.h" /* SAFESTRCPY() */
8 /* These should be in a header file, median.h */
9 extern double Median();
10 extern double TrimmedMedian();
11 extern void AdjustedMean();
12 extern void AdjustedMedian();
13 extern char *DefineHistogram();
14 extern char *DefineHistogramPred();
15 extern void PrintHistogram();
16 extern void ModalDev();
37 double Lifetime_mse[LIFETIMES];
38 double Lifetime_mpe[LIFETIMES];
39 int Lifetime_count = 0;
40 extern int Median_sorted;
42 const char *Names[PREDS];
43 #define NAME(i) (Names[i])
46 PrintPredData(tp,where)
47 struct thruput_pred *tp;
50 struct value_el *data = tp->data;
51 int prev = MODMINUS(where,1,HISTORYSIZE);
54 fprintf(stdout,"%d %3.4f ",(int)data[where].time, data[where].value);
56 for(i=0; i < PREDS; i++)
58 fprintf(stdout,"| %3.4f %3.4f %3.4f ",PRED(i,data[prev]),
59 TPMSE(tp,i)/TPCOUNT(tp,i),
60 TPMAE(tp,i)/TPCOUNT(tp,i));
62 fprintf(stdout,"| %d %d | ",MedWIN(6,data[prev]),MeanWIN(7,data[prev]));
63 for(i=STATIC_PREDS; i < SECOND_ORDER_PREDS; i++)
65 fprintf(stdout,"%d ",TPPREDNUM(tp,i));
68 for(i=SECOND_ORDER_PREDS; i < PREDS; i++)
70 fprintf(stdout,"%d ",TPPREDNUM(tp,i));
81 struct thruput_pred *tp;
89 struct value_el *data = tp->data;
91 double run_mean = tp->run_mean;
92 double total = tp->total;
94 double min_run_p_error = MAXDOUBLE;
96 double min_run_sq_error = MAXDOUBLE;
99 double absolute_error;
101 double min_win_sq_error = MAXDOUBLE;
102 double min_win_p_error = MAXDOUBLE;
103 int min_win_sq_i = 0;
105 double min_tot_sq_error = MAXDOUBLE;
106 double min_tot_p_error = MAXDOUBLE;
107 int min_tot_sq_i = 0;
113 datasize = MODMINUS(head,tail,HISTORYSIZE) - 1;
114 if(ERR_WIN > datasize)
115 error_window = datasize;
117 error_window = ERR_WIN;
119 last_error = MODMINUS(head,error_window,HISTORYSIZE);
123 value = data[head].value;
124 prev = MODMINUS(head,1,HISTORYSIZE);
127 * was the value within one deviation of the total prediction?
129 avg_err = TPMAE(tp,TOT_MSE_PRED)/TPCOUNT(tp,TOT_MSE_PRED);
130 if((value > (PRED(TOT_MSE_PRED,data[prev])-avg_err)) &&
131 (value < (PRED(TOT_MSE_PRED,data[prev])+avg_err)))
135 if((value > (PRED(TOT_MSE_PRED,data[prev])-2*avg_err)) &&
136 (value < (PRED(TOT_MSE_PRED,data[prev])+2*avg_err)))
141 avg_err = TPMAE(tp,TOT_MAE_PRED)/TPCOUNT(tp,TOT_MAE_PRED);
142 if((value > (PRED(TOT_MAE_PRED,data[prev])-avg_err)) &&
143 (value < (PRED(TOT_MAE_PRED,data[prev])+avg_err)))
147 if((value > (PRED(TOT_MAE_PRED,data[prev])-2*avg_err)) &&
148 (value < (PRED(TOT_MAE_PRED,data[prev])+2*avg_err)))
153 ModalDev(Histogram,MedianPred,1.0,&hi,&lo);
154 if((value > lo) && (value < hi))
156 ModalDev(Histogram,MedianPred,2.0,&hi,&lo);
157 if((value > lo) && (value < hi))
164 * calculate the error our last prediction made
165 * now that we have the actual value
167 for(i=0; i < PREDS; i++)
170 error = data[head].value - PRED(i,data[prev]);
171 if(TPCOUNT(tp,i) < MIN_DATA_HISTORY)
173 sq_error = error * error;
175 SQERR(i,data[head]) = SQERR(i,data[prev])+sq_error;
176 TPMSE(tp,i) += sq_error;
178 error = -1.0 * error;
179 absolute_error = error;
180 ERR(i,data[head]) = ERR(i,data[prev])+absolute_error;
181 TPMAE(tp,i) += absolute_error;
182 TPCOUNT(tp,i) += 1.0;
188 * now calculate MSE values over different lifetimes
190 if(datasize > LIFETIMES)
193 for(i=0; i < LIFETIMES; i++)
195 error = data[head].value -
196 PRED(TOT_MSE_PRED,data[curr]);
197 Lifetime_mse[i] += (error * error);
198 error = data[head].value -
199 PRED(TOT_MAE_PRED,data[curr]);
201 error = -1.0 * error;
202 Lifetime_mpe[i] += (error / data[head].value);
203 curr = MODMINUS(curr,1,HISTORYSIZE);
214 * use the current running mean
216 NAME(0) = "Last value";
217 PRED(0,data[head]) = value;
221 * use the current value as a prediction of the next value
223 tot_sum = run_mean * total;
224 tot_sum += data[head].value;
226 run_mean = tot_sum/total;
227 tp->run_mean = run_mean;
229 NAME(1) = "Running Mean";
230 PRED(1,data[head]) = run_mean;
233 * use the Van Jacobson method
235 prev_pred = PRED(2,data[prev]);
236 NAME(2) = "Van Jacobson";
237 PRED(2,data[head]) = prev_pred + GAIN*(value - prev_pred);
240 * tell the median routines that the array is no longer valid
244 PRED(3,data[head]) = Median(tp,MED_N);
245 NAME(4) = "Trimmed Median";
246 PRED(4,data[head]) = TrimmedMedian(tp,MED_N,MED_ALPHA);
249 * Now use TrimmedMean to give a sliding window mean
251 NAME(5) = "Sliding Window Mean";
252 PRED(5,data[head]) = TrimmedMedian(tp,MED_N,0.0);
253 NAME(6) = "Adjusted Median";
254 AdjustedMedian(tp,6,WIN_MIN,WIN_MAX);
255 NAME(7) = "Adjusted Mean";
256 AdjustedMean(tp,7,WIN_MIN,WIN_MAX);
258 for(i=0; i < STATIC_PREDS; i++)
260 if((TPMSE(tp,i)/TPCOUNT(tp,i)) < min_run_sq_error)
262 min_run_sq_error = TPMSE(tp,i)/TPCOUNT(tp,i);
266 if((TPMAE(tp,i)/TPCOUNT(tp,i)) < min_run_p_error)
268 min_run_p_error = TPMAE(tp,i)/TPCOUNT(tp,i);
273 (SQERR(i,data[head]) - SQERR(i,data[last_error])) /
274 (double)error_window;
275 if(win_error < min_win_sq_error)
277 min_win_sq_error = win_error;
282 (ERR(i,data[head]) - ERR(i,data[last_error])) /
283 (double)error_window;
284 if(win_error < min_win_p_error)
286 min_win_p_error = win_error;
293 NAME(MSE_PRED) = "Min MSE Pred";
294 PRED(MSE_PRED,data[head]) = PRED(min_run_sq_i,data[head]);
295 TPPREDNUM(tp,MSE_PRED) = min_run_sq_i;
296 NAME(MAE_PRED) = "Min MAE Pred";
297 PRED(MAE_PRED,data[head]) = PRED(min_run_p_i,data[head]);
298 TPPREDNUM(tp,MAE_PRED) = min_run_p_i;
299 NAME(WIN_MSE_PRED) = "Win MSE Pred";
300 PRED(WIN_MSE_PRED,data[head]) = PRED(min_win_sq_i,data[head]);
301 TPPREDNUM(tp,WIN_MSE_PRED) = min_win_sq_i;
302 NAME(WIN_MAE_PRED) = "Win MAE Pred";
303 PRED(WIN_MAE_PRED,data[head]) = PRED(min_win_p_i,data[head]);
304 TPPREDNUM(tp,WIN_MAE_PRED) = min_win_p_i;
306 for(i=STATIC_PREDS; i < SECOND_ORDER_PREDS; i++)
308 if((TPMSE(tp,i)/TPCOUNT(tp,i)) < min_tot_sq_error)
310 min_tot_sq_error = TPMSE(tp,i)/TPCOUNT(tp,i);
311 min_tot_sq_i = TPPREDNUM(tp,i);
313 if((TPMAE(tp,i)/TPCOUNT(tp,i)) < min_tot_p_error)
315 min_tot_p_error = TPMAE(tp,i)/TPCOUNT(tp,i);
316 min_tot_p_i = TPPREDNUM(tp,i);
319 NAME(TOT_MSE_PRED) = "Total MSE Pred";
320 PRED(TOT_MSE_PRED,data[head]) = PRED(min_tot_sq_i,data[head]);
321 TPPREDNUM(tp,TOT_MSE_PRED) = min_tot_sq_i;
322 NAME(TOT_MAE_PRED) = "Total MAE Pred";
323 PRED(TOT_MAE_PRED,data[head]) = PRED(min_tot_p_i,data[head]);
324 TPPREDNUM(tp,TOT_MAE_PRED) = min_tot_p_i;
327 ModalDev(Histogram,MedianPred,2.0,&hi,&lo);
328 fprintf(stdout,"%d %10.5f\n",data[head].time,
329 PRED(TOT_MAE_PRED,data[prev]));
339 InitThruputPrediction(struct thruput_pred *tp)
346 /* ** NOT yet as we don't quite know what min and max values to use
348 Histogram = DefineHistogram(MODES,
352 MeanPred = DefineHistogramPred(Histogram);
353 MedianPred = DefineHistogramPred(Histogram);
354 MiddlePred = DefineHistogramPred(Histogram);
361 memset(tp->data,0,sizeof(tp->data));
363 for(i=0; i < PREDS; i++)
372 /* not sure if exptime is right, I just wanted to avoid namespace collisions */
374 UpdateThruputPrediction(struct thruput_pred *tp,float value, time_t exptime)
379 struct value_el *data = tp->data;
381 int data_size = MODMINUS(head,tail,HISTORYSIZE);
383 tp->data[tp->head].time = exptime;
384 tp->data[tp->head].value = value;
387 * a negative tail value says that we haven't filled the
388 * pipe yet. See if this does it.
390 if(data_size > MIN_DATA_HISTORY)
392 ThruputPrediction(tp);
397 for(i=0; i < PREDS; i++)
399 PRED(i,data[head]) = tp->data[head].value;
402 ERR(i,data[head]) = 0.0;
403 SQERR(i,data[head]) = 0.0;
404 MedWIN(i,data[head]) = WIN_INIT;
405 MeanWIN(i,data[head]) = WIN_INIT;
407 TPPREDNUM(tp,TOT_MSE_PRED) = 0;
408 TPPREDNUM(tp,TOT_MAE_PRED) = 0;
413 tp->head = MODPLUS(head,1,HISTORYSIZE);
416 * if we have incremented head forward to that it is sitting on
417 * top of tail, then we need to bump tail. The entire buffer is
418 * being used to fill the window.
420 if(tp->head == tp->tail)
421 tp->tail = MODPLUS(tp->tail,1,HISTORYSIZE);
428 #define PRED_ARGS "f:d:s:l:h:"
432 CalculateThruputPredictors(fname,tp)
434 struct thruput_pred *tp;
444 fd = fopen(fname,"r");
449 "CalculateThruputPredictors: unable to open file %s\n",
455 while(fgets(line_buf,255,fd))
462 for(i=1; i < TSFIELD; i++)
475 for(i=1; i < VALFIELD; i++)
487 UpdateThruputPrediction(tp,value,ltime);
495 struct thruput_pred Tp;
513 fprintf(stderr,"usage: testpred filename\n");
520 Histostates = STATES;
524 while((c = getopt(argc,argv,PRED_ARGS)) != EOF)
529 SAFESTRCPY(fname,optarg);
532 Histodim = atoi(optarg);
535 Histostates = atoi(optarg);
538 Histomin = atof(optarg);
541 Histomax = atof(optarg);
548 fprintf(stderr,"usage: predictor -f fname [-d,s,l,h]\n");
553 InitThruputPrediction(&Tp);
555 #if !defined(PRINTPRED)
556 fprintf(stdout,"Calculating throughput predictors...");
560 CalculateThruputPredictors(fname,&Tp);
562 fprintf(stdout,"done.\n");
565 for(i=0; i < PREDS; i++)
568 fprintf(stdout,"Predictor %d, MSE: %3.4f MAE: %3.4f, %s\n",
569 i,TPMSE(&Tp,i)/TPCOUNT(&Tp,i),
570 TPMAE(&Tp,i)/TPCOUNT(&Tp,i),
574 fprintf(stdout,"MSE within 1 dev: %3.2f, 2 dev: %3.2f\n",
575 Onedev_mse/Devcounts,Twodev_mse/Devcounts);
576 fprintf(stdout,"MAE within 1 dev: %3.2f, 2 dev: %3.2f\n",
577 Onedev_mpe/Devcounts,Twodev_mpe/Devcounts);
578 fprintf(stdout,"Modal within 1 dev: %3.2f, 2 dev: %3.2f\n",
579 Onedev_modal/Devcounts,Twodev_modal/Devcounts);
583 fprintf(stdout,"\nlook ahead MSE MAE\n");
584 for(i=0; i < LIFETIMES; i++)
588 for(j=0; j <= i; j++)
590 temp_mse += (Lifetime_mse[j]/(double)Lifetime_count);
591 temp_mpe += (Lifetime_mpe[j]/(double)Lifetime_count);
593 fprintf(stdout,"%d %f %f\n",i,
599 fprintf(stdout,"Histogram\n");
600 PrintHistogram(Histogram);
601 fprintf(stdout,"\n");