pmm  1.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
pmm_comp.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008-2010 Robert Higgins
3  Author: Robert Higgins <robert.higgins@ucd.ie>
4 
5  This file is part of PMM.
6 
7  PMM is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  PMM is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with PMM. If not, see <http://www.gnu.org/licenses/>.
19 */
20 /*!
21  *
22  * @file pmm_comp.c
23  *
24  * @brief Program to compare two models
25  *
26  * This file contains the pmm_comp program, which is a simple utility to
27  * compare two models
28  */
29 #if HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <getopt.h>
36 #include <math.h>
37 #include <gsl/gsl_statistics_double.h>
38 
39 
40 #include "pmm_model.h"
41 #include "pmm_octave.h"
42 #include "pmm_cfgparser.h"
43 #include "pmm_log.h"
44 #include "pmm_param.h"
45 
46 /*!
47  * structure storing options for pmm_comp tool
48  */
49 typedef struct pmm_comp_options {
53 
54 
55 /*!
56  * print command line usage for pmm_comp tool
57  */
58 void
60 {
61  printf("Usage: pmm_comp -a model_a -b model_b\n");
62  printf("Options:\n");
63  printf(" -a model_a : approximation that will be compared\n");
64  printf(" -b model_b : base model which will be compared to\n");
65  printf("\n");
66 }
67 
68 /*!
69  * parse arguments for pmm_comp tool
70  *
71  * @param opts pointer to options structure
72  * @param argc number of command line arguments
73  * @param argv command line arguments character array pointer
74  */
75 void
76 parse_args(struct pmm_comp_options *opts, int argc, char **argv)
77 {
78  int c;
79  int option_index;
80 
81  opts->approx_model_file = (void*)NULL;
82  opts->base_model_file = (void*)NULL;
83 
84 
85 
86  while(1) {
87  static struct option long_options[] =
88  {
89  {"approx-model", required_argument, 0, 'a'},
90  {"base-model", required_argument, 0, 'b'},
91  {"help", no_argument, 0, 'h'},
92  {0, 0, 0, 0}
93  };
94 
95  option_index = 0;
96 
97  c = getopt_long(argc, argv, "a:b:h", long_options, &option_index);
98 
99  // getopt_long returns -1 when arg list is exhausted
100  if(c == -1) {
101  break;
102  }
103 
104  switch(c) {
105  case 'a':
106  opts->approx_model_file = optarg;
107  break;
108 
109  case 'b':
110  opts->base_model_file = optarg;
111  break;
112 
113  case 'h':
114  usage();
115  exit(EXIT_SUCCESS);
116 
117  default:
118  usage();
119  exit(EXIT_FAILURE);
120  }
121  }
122 
123  if(optind < argc) {
124  usage();
125  exit(EXIT_FAILURE);
126  }
127 
128  if(opts->approx_model_file == NULL ||
129  opts->base_model_file == NULL)
130  {
131  fprintf(stderr, "Error: model files must be specified.\n");
132  usage();
133  exit(EXIT_FAILURE);
134  }
135 
136  return;
137 }
138 
139 /*!
140  * find the correlation between two models
141  *
142  * @param approx_model pointer to so called approximation model
143  * @param base_model pointer to base model
144  *
145  * @return the correlation factor
146  */
147 double
148 correlate_models(struct pmm_model *approx_model, struct pmm_model *base_model)
149 {
150  //TODO free allocated memory on return by error to prevent leaks
151  int n; /* number of unique points in base model b */
152  int c; /* counter */
153  int i, j;
154  double correlation;
155  double *base_speed, *approx_speed;
156 
157  int **base_points;
158 
159  struct pmm_benchmark *b, *b_avg;
160  struct pmm_octave_data *oct_data;
161 
162  octave_init();
163 
164  b = base_model->bench_list->first;
165 
167 
168  base_points = malloc(n * sizeof *base_points);
169  base_speed = malloc(n * sizeof *base_speed);
170 
171  if(base_speed == NULL || base_points == NULL) {
172  ERRPRINTF("Error allocating memory.\n");
173  return -1.0;
174  }
175 
176  oct_data = fill_octave_input_matrices(approx_model, PMM_ALL);
177  if(oct_data == NULL) {
178  ERRPRINTF("Error preparing octave input data.\n");
179  return -1.0;
180  }
181 
182  if(octave_triangulate(oct_data) < 0) {
183  ERRPRINTF("Error calcuating triangulation of data.\n");
184  return -1.0;
185  }
186 
187  c = 0;
188  while(b != NULL && c < n) {
190 
191  if(b_avg == NULL) {
192  ERRPRINTF("Error getting average of benchmark:\n");
194  return -1.0;
195  }
196 
197  base_speed[c] = b_avg->flops;
198 
199  base_points[c] = init_param_array_copy(b_avg->p, b_avg->n_p);
200 
201  free_benchmark(&b_avg);
202 
204  c++;
205  }
206 
207  if(b != NULL && c != n-1) {
208  ERRPRINTF("Error, unexpected number of benchmarks\n");
209  return -1.0;
210  }
211 
212  approx_speed = octave_interp_array(oct_data, base_points,
213  base_model->n_p, n);
214 
215  if(approx_speed == NULL) {
216  ERRPRINTF("Error interpolating approximation\n");
217  return -1.0;
218  }
219 
220  correlation = gsl_stats_correlation(base_speed, 1, approx_speed, 1, n);
221 
222  for(j=0; j<base_model->n_p; j++)
223  printf("p%d ", j);
224 
225  printf("base_speed approx_speed diff %%diff\n");
226 
227  for(i=0; i<n; i++) {
228 
229  for(j=0; j<base_model->n_p; j++)
230  printf("%d ", base_points[i][j]);
231 
232  printf("%f %f %f %f\n", base_speed[i], approx_speed[i], fabs(base_speed[i]-approx_speed[i]), fabs(base_speed[i]-approx_speed[i])/base_speed[i]);
233  free(base_points[i]);
234  base_points[i] = NULL;
235  }
236  free(base_points);
237  base_points = NULL;
238  free(base_speed);
239  base_speed = NULL;
240  free(approx_speed);
241  approx_speed = NULL;
242 
243  return correlation;
244 }
245 
246 /*!
247  * pmm_comp compares pairs of model files
248  *
249  * shows statistics such as correlation, number of points, time spent
250  * benchmarking, etc.
251  */
252 int
253 main(int argc, char **argv)
254 {
255 
256  struct pmm_comp_options opts;
257  struct pmm_model *approx_model, *base_model;
258  int ret;
259 
260  double correlation;
261 
262  parse_args(&opts, argc, argv);
263 
264  printf("approx model:%s\n", opts.approx_model_file);
265  printf("base model:%s\n", opts.base_model_file);
266 
267 
268  approx_model = new_model();
269  base_model = new_model();
270 
271  if(approx_model == NULL || base_model == NULL) {
272  ERRPRINTF("Error allocating new model.\n");
273  exit(EXIT_FAILURE);
274  }
275 
276 
277  approx_model->model_path = opts.approx_model_file;
278  base_model->model_path = opts.base_model_file;
279 
280 
281  xmlparser_init();
282 
283 
284  ret = parse_model(approx_model);
285  if(ret == -1) {
286  ERRPRINTF("Error file does not exist:%s\n", approx_model->model_path);
287  exit(EXIT_FAILURE);
288  }
289  else if(ret < -1) {
290  ERRPRINTF("Error parsing approx model.\n");
291  exit(EXIT_FAILURE);
292  }
293 
294  ret = parse_model(base_model);
295  if(ret == -1) {
296  ERRPRINTF("Error file does not exist:%s\n", base_model->model_path);
297  exit(EXIT_FAILURE);
298  }
299  else if(ret < -1) {
300  ERRPRINTF("Error base parsing base model.\n");
301  exit(EXIT_FAILURE);
302  }
303 
304 
305  correlation = correlate_models(approx_model, base_model);
306 
307  printf("model correlation:%f\n", correlation);
308  printf("base model points:%d\n", base_model->completion);
309  printf("base model execution time:%f\n", calc_model_stats(base_model));
310  printf("approx model points:%d\n", approx_model->completion);
311  printf("approx model execution time:%f\n", calc_model_stats(approx_model));
312 
314 
315  return 0;
316 }