pmm  1.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
pmm_view.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_view.c
23  * @author Robert Higgins
24  * @date Sept 2009
25  * @brief Basic viewer program for models constructed by PMM
26  *
27  * Program overview:
28  *
29  * Arguments:
30  * -r routine
31  * -c configuration file
32  * -m
33  * -h
34  *
35  *
36  * Structure:
37  * Parse arguments, read configuration, find routine, plot history or model
38  *
39  */
40 #if HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43 
44 #include <stdio.h>
45 #include <stdlib.h>
46 
47 // TODO platform specific code follows, need to fix this
48 #include <unistd.h>
49 #include <sys/time.h>
50 #include <time.h>
51 #include <paths.h>
52 #include <sys/types.h>
53 #include <sys/stat.h> // for stat
54 #include <fcntl.h>
55 #include <pthread.h>
56 #include <libgen.h>
57 #include <string.h>
58 
59 #include "pmm_model.h"
60 #include "pmm_octave.h"
61 #include "pmm_interval.h"
62 #include "pmm_log.h"
63 #include "pmm_argparser.h"
64 #include "pmm_cfgparser.h"
65 #include "gnuplot_i.h"
66 
67 
68 void plot_model(gnuplot_ctrl *plot_handle, struct pmm_model *model,
69  struct pmm_view_options *options);
70 void
71 plot_slice_model(gnuplot_ctrl *plot_handle, struct pmm_model *model,
72  struct pmm_view_options *options);
73 void splot_model(gnuplot_ctrl *plot_handle, struct pmm_model *model,
74  struct pmm_view_options *options);
75 void
76 plot_slice_interp_model(gnuplot_ctrl *plot_handle, struct pmm_model *model,
77  struct pmm_view_options *options);
78 
79 int
80 bench_in_slice(struct pmm_view_options *options, struct pmm_benchmark *b);
81 void
82 splot_slice_model(gnuplot_ctrl *plot_handle, struct pmm_model *model,
83  struct pmm_view_options *options);
84 
85 void
86 set_splot_labels_ranges(gnuplot_ctrl *plot_handle, struct pmm_model *model,
87  char **plot_title_buf);
88 void
89 set_plot_labels_ranges(gnuplot_ctrl *plot_handle, struct pmm_model *model,
90  char **plot_title_buf);
91 
92 int draw_plot_intervals(gnuplot_ctrl *plot_handle, struct pmm_model *model);
93 int draw_splot_intervals(gnuplot_ctrl *plot_handle, struct pmm_model *model);
94 
95 void empty_model(struct pmm_model *m);
96 
97 int
98 test_model_files_modified(struct pmm_model **m_array, int n);
99 int
101 
102 // TODO remove reference to this global variable in pmm_model.c and put the
103 // history maniuplation in a seperate file that can be included only where
104 // needed (i.e. not here!)
105 pthread_rwlock_t history_rwlock;
106 
107 
108 /*!
109  * Program first parses command line args and to determine the action to take
110  * which is either:
111  *
112  * print list of models available for plotting (according to config file)
113  * plot a model
114  * print out the raw data of a model
115  *
116  */
117 
118 int
119 main(int argc, char **argv) {
120 
121  struct pmm_view_options options; // structure containing all options
122  struct pmm_config *cfg; // pointer to pmm configuration
123 
124  struct pmm_model **models; // array of models to plot
125  int n_p; // number of parameters to models
126 
127  gnuplot_ctrl *plot_handle; // handle to the gnuplot process
128 
129  int ret;
130  int i, j;
131 
132  // parse arguments
133  ret = parse_pmm_view_args(&options, argc, argv);
134  if(ret < 0) {
135  printf("Error parsing arguments.\n");
136  usage_pmm_view();
137  exit(EXIT_FAILURE);
138  }
139 
140  xmlparser_init();
141 
142 
143  if(options.action == PMM_VIEW_PRINT_LIST) {
144 
145  cfg = new_config();
146 
147  if(options.config_file != NULL) {
148  ret = asprintf(&(cfg->configfile), "%s", options.config_file);
149  if(ret < 0) {
150  ERRPRINTF("Error: asprintf failed with return code: %d\n", ret);
151  exit(EXIT_FAILURE);
152  }
153  }
154 
155  //read config
156  parse_config(cfg);
157 
158  //print routines
159  printf("Routine list:\n");
160  for(i=0; i<cfg->used; i++) {
161  printf("%s\n", cfg->routines[i]->name);
162  }
163 
164  }
165  else if(options.action == PMM_VIEW_DISPLAY_ROUTINE ||
166  options.action == PMM_VIEW_DISPLAY_FILE) {
167 
168 
169  models = malloc(options.n_plots * sizeof *models);
170  if(models == NULL) {
171  ERRPRINTF("Error allocating memory.\n");
172  exit(EXIT_FAILURE);
173  }
174 
175  if(options.action == PMM_VIEW_DISPLAY_ROUTINE) {
176  for(i = 0; i < options.n_plots; i++) {
177  printf("Displaying model for routine: %s\n",
178  options.routine_names[i]);
179  }
180 
181  cfg = new_config();
182 
183  if(options.config_file != NULL) {
184  ret = asprintf(&(cfg->configfile), "%s", options.config_file);
185  if(ret < 0) {
186  ERRPRINTF("Error: asprintf failed with return code: %d\n",
187  ret);
188  exit(EXIT_FAILURE);
189  }
190  }
191 
192  //read config
193  parse_config(cfg);
194 
195  // for each routine specified on command line
196  for(j = 0; j < options.n_plots; j++) {
197 
198  models[j] = NULL; // set this to null so we can test later
199 
200  // search for routine in config
201  for(i = 0; i < cfg->used; i++) {
202 
203  if(strcmp(options.routine_names[j], cfg->routines[i]->name)
204  == 0)
205  {
206  models[j] = cfg->routines[i]->model;
207  }
208  }
209 
210  // if we done fine the routine, exit
211  if(models[j] == NULL) {
212  printf("Failed to find model for routine: %s.\n",
213  options.routine_names[j]);
214  exit(EXIT_FAILURE);
215  }
216 
217 
218  }
219 
220  }
221  else if(options.action == PMM_VIEW_DISPLAY_FILE) {
222  for(i = 0; i < options.n_plots; i++) {
223  models[i] = new_model();
224 
225  if(models[i] == NULL) {
226  ERRPRINTF("Error allocating model.\n");
227  exit(EXIT_FAILURE);
228  }
229 
230  // use asprintf as free_model must free model_path pointer
231  ret = asprintf(&(models[i]->model_path), "%s",
232  options.model_files[i]);
233  if(ret < 0) {
234  ERRPRINTF("Error: asprintf failed with return code: %d\n",
235  ret);
236  exit(EXIT_FAILURE);
237  }
238 
239  printf("Displaying model from file: %s\n",
240  options.model_files[i]);
241  }
242  }
243 
244 
245  // parse models from files on disk
246  n_p=0;
247  for(i = 0; i < options.n_plots; i++) {
248 
249  // if model has not yet been parsed ...
250  if(models[i]->completion == 0) {
251 
252  ret = parse_model(models[i]);
253  if(ret == -1) {
254  ERRPRINTF("Error file does not exist:%s\n",
255  models[i]->model_path);
256  exit(EXIT_FAILURE);
257  }
258  else if(ret < -1) {
259  ERRPRINTF("Error parsing models[%d]: %s.\n",
260  i, models[i]->model_path);
261  exit(EXIT_FAILURE);
262  }
263 
264  }
265 
266  // test number of parameters are all the same and all not greater
267  // than 2 (where no slices are specified)
268  if(n_p == 0) {
269  n_p = models[i]->n_p;
270 
271  if(n_p > 2 && options.slice_arr_size == -1) {
272  printf("Cannot plot full models in terms of >2 parameters, "
273  "specify a slice to view.\n");
274  exit(EXIT_FAILURE);
275  }
276  }
277  else if(n_p != models[i]->n_p) {
278  ERRPRINTF("Cannot plot models with different numbers of "
279  "parameters together");
280  exit(EXIT_FAILURE);
281  }
282 
283  }
284 
285 
286 
287 
288  // init gnuplot handle and plot models
289  plot_handle = gnuplot_init();
290 
291  if(options.wait_period <= 0) {
292 
293 
294  if(options.plot_output_file != NULL) {
295 
296  // test extension
297  {
298  char *ext;
299 
300  ext = strrchr(options.plot_output_file, '.');
301  if(ext == NULL) {
302  printf("specify an extension (.ps or .png) to your "
303  "output file.\n");
304  exit(EXIT_FAILURE);
305  }
306 
307  if(strcmp(ext, ".ps") == 0) {
308 
309  if(options.plot_output_grayscale == 1) {
310  gnuplot_setterm(plot_handle,
311  "postscript enhanced monochrome font \"Helvetica\" 20");
312  }
313  else {
314  gnuplot_setterm(plot_handle,
315  "postscript enhanced color font \"Helvetica\" 20");
316  }
317  }
318  else if( strcmp(ext, ".eps") == 0) {
319  if(options.plot_output_grayscale == 1) {
320  gnuplot_setterm(plot_handle,
321  "postscript eps enhanced monochrome font \"Helvetica\" 20");
322  }
323  else {
324  gnuplot_setterm(plot_handle,
325  "postscript enhanced color font \"Helvetica\" 20");
326  }
327  }
328  else if(strcmp(ext, ".png") == 0) {
329  gnuplot_setterm(plot_handle, "png size 800,600");
330  }
331  else {
332  printf("specify an extension (.ps or .png) to your "
333  "output file.\n");
334  exit(EXIT_FAILURE);
335  }
336 
337 
338 
339  printf("writing to file:%s\n",
340  options.plot_output_file);
341 
342  gnuplot_cmd(plot_handle, "set output \"%s\"",
343  options.plot_output_file);
344  }
345  }
346 
347 
348  if(options.slice_arr_size != -1) {
349  if(options.slice_arr_size >= n_p) {
350  ERRPRINTF("Too many parameteres defined in slice (%d) of "
351  "model with %d parameters.\n",
352  options.slice_arr_size,
353  n_p);
354  exit(EXIT_FAILURE);
355  }
356 
357  if(options.slice_arr_size < n_p-2) {
358  ERRPRINTF("Not enough parameters defined in slice (%d) of "
359  "model with %d parameters.\n",
360  options.slice_arr_size,
361  n_p);
362  exit(EXIT_FAILURE);
363  }
364 
365  for(i=0; i<options.slice_arr_size; i++) {
366  if(options.slice_i_arr[i] < 0 ||
367  options.slice_i_arr[i] > n_p-1) {
368  ERRPRINTF("Slice parameter index %d out of bounds.\n",
369  options.slice_i_arr[i]);
370  exit(EXIT_FAILURE);
371  }
372  else if(options.n_plots != 1) {
373  ERRPRINTF("Cannot plot slices for more than 1 model"
374  " at present.\n");
375  exit(EXIT_FAILURE);
376  }
377 
378  if(options.slice_val_arr[i] < 0) {
379  if(options.action == PMM_VIEW_DISPLAY_FILE) {
380  ERRPRINTF("Cannot specify max/min in slice when "
381  "plotting a model file directly (max/min "
382  "only defined in config file.\n");
383  exit(EXIT_FAILURE);
384  }
385  else {
386  if(options.slice_val_arr[i] == -1) {
387  options.slice_val_arr[i] = models[0]->parent_routine->pd_set->pd_array[options.slice_i_arr[i]].end;
388  }
389  else if(options.slice_val_arr[i] == -2) {
390  options.slice_val_arr[i] = models[0]->parent_routine->pd_set->pd_array[options.slice_i_arr[i]].start;
391  }
392  else {
393  ERRPRINTF("Slice value should positive.\n");
394  exit(EXIT_FAILURE);
395  }
396  }
397 
398 
399  }
400  }
401 
402  if(options.slice_arr_size == n_p-1) {
403  if(options.slice_interpolate == 0) {
404  plot_slice_model(plot_handle, models[0], &options);
405  }
406  else {
407  plot_slice_interp_model(plot_handle, models[0],
408  &options);
409  }
410  }
411  else {
412  if(options.slice_interpolate == 0) {
413  ERRPRINTF("Interpolation plot of multidimensional "
414  "model is not supported");
415  exit(EXIT_FAILURE);
416  }
417  else {
418  splot_slice_model(plot_handle, models[0], &options);
419  }
420  }
421  }
422  else if(n_p == 1 || (n_p <= 1 && options.plot_params_index == 0))
423  {
424  for(i = 0; i < options.n_plots; i++) {
425  plot_model(plot_handle, models[i], &options);
426  }
427 
428  }
429  else if(n_p == 2 || (n_p <= 2 && options.plot_params_index == 1))
430  {
431  for(i = 0; i < options.n_plots; i++) {
432  splot_model(plot_handle, models[i], &options);
433  }
434  }
435 
436 
437  // now enter interactive mode
438  if(options.enter_interactive == 1) {
439  gnuplot_prompt(plot_handle);
440  }
441  // or wait for user to decide termination
442  // unless we have printed to file, exit immidiately then ...
443  else if(options.plot_output_file == NULL) {
444  printf("press any key to close ...\n");
445  getchar();
446  }
447  }
448  else {
449  // this will initialise all mtimes for the models
450  test_model_files_modified(models, options.n_plots);
451  for(;;) {
452 
453  gnuplot_resetplot(plot_handle);
454 
455  if(n_p == 1) {
456  for(i = 0; i < options.n_plots; i++) {
457  plot_model(plot_handle, models[i], &options);
458  }
459 
460  }
461  else if(n_p == 2) {
462  for(i = 0; i < options.n_plots; i++) {
463  splot_model(plot_handle, models[i], &options);
464  }
465  }
466 
467  printf("replotting in %d secs (minimum).\n",
468  options.wait_period);
469 
470  sleep(options.wait_period);
471 
472  // if the models are not modified, don't bother
473  // reploting, just sleep for the period until they are
474  while((ret = test_model_files_modified(models, options.n_plots))
475  != 1) {
476  DBGPRINTF("models not updated. Sleeping again ...\n");
477  sleep(options.wait_period);
478  }
479  if(ret < 0) {
480  ERRPRINTF("Error testing modification of model files\n");
481  exit(EXIT_FAILURE);
482  }
483 
484  for(i = 0; i < options.n_plots; i++) {
485  empty_model(models[i]);
486  ret = parse_model(models[i]);
487  if(ret == -1) {
488  ERRPRINTF("Error: model file does not exist:%s\n",
489  models[i]->model_path);
490  }
491  else if(ret < -1) {
492  ERRPRINTF("Error parsing model.\n");
493  }
494  }
495  }
496  }
497 
498 
499  if(options.action == PMM_VIEW_DISPLAY_ROUTINE) {
500  free_config(&cfg);
501  }
502  else if(options.action == PMM_VIEW_DISPLAY_FILE) {
503  for(i = 0; i < options.n_plots; i++) {
504  free_model(&(models[i]));
505  }
506  }
507 
508  gnuplot_close(plot_handle);
509  }
510 
512 
513  exit(EXIT_SUCCESS);
514 
515 
516 }
517 
518 /*!
519  * Test an array of models to see if their model files have been
520  * modified. Note that we test all models and update the stored mtime
521  * for each.
522  *
523  * @param m_array pointer to array of models
524  * @param n number of models in array
525  *
526  * @return 0 if none of the files have been modified, 1 if any of the
527  * model files have been modified, -1 on error.
528  */
529 int
530 test_model_files_modified(struct pmm_model **m_array, int n)
531 {
532  int i;
533  int ret;
534  int is_modified = 0;
535 
536  for(i=0; i<n; i++) {
537  ret = test_model_file_modified(m_array[i]);
538  if(ret == 1) {
539  is_modified = 1;
540  }
541  else if(ret < 0) {
542  ERRPRINTF("Error testing the mtime of %d-th model file.\n", i);
543  print_model(PMM_ERR, m_array[i]);
544 
545  return -1;
546  }
547  }
548 
549  return is_modified;
550 }
551 
552 /*!
553  * Tests if a model file has been modified since the stored mtime
554  *
555  * @param m pointer to the model
556  *
557  * @return 0 if not modified, 1 if modified and -1 on error
558  */
559 int
561 {
562 
563  int ret;
564  struct stat file_stats;
565 
566  ret = stat(m->model_path, &file_stats);
567  if(ret < 0) {
568  ERRPRINTF("Error stat-ing file: %s\n", m->model_path);
569  return -1;
570  }
571 
572  if(m->mtime < file_stats.st_mtime) {
573  m->mtime = file_stats.st_mtime;
574  return 1;
575  }
576  else {
577  return 0;
578  }
579 }
580 
581 /*!
582  * free memeber structures and zero a model
583  *
584  * @param m pointer to model
585  */
586 void
588 {
589 
590  if(m->bench_list != NULL) {
592  m->bench_list = NULL;
593  }
594 
595  if(m->interval_list != NULL) {
598  }
599 
600  m->n_p = -1;
601  m->completion = 0;
602  m->complete = 0;
603 }
604 
605 /*!
606  * plot a model which is in terms of 1 parameter
607  *
608  * @param plot_handle pointer to gnuplot handle
609  * @param model pointer to model to plot
610  * @param options pointer to options for plot
611  *
612  */
613 void
614 plot_model(gnuplot_ctrl *plot_handle, struct pmm_model *model,
615  struct pmm_view_options *options)
616 {
617  double *x;
618  double *y;
619  int n, c;
620  char *plot_title_buf;
621 
622  struct pmm_benchmark *b, *b_plot;
623 
624  if(options->plot_average == 1 ||
625  options->plot_max == 1)
626  {
628  }
629  else {
630  n = model->bench_list->size;
631  }
632 
633  y = malloc(n * sizeof *y);
634  if(y == NULL) {
635  ERRPRINTF("Error allocating memory y.\n");
636  exit(EXIT_FAILURE);
637  }
638 
639  x = malloc(n * sizeof *x);
640  if(x == NULL) {
641  ERRPRINTF("Error allocating memory to x.\n");
642  exit(EXIT_FAILURE);
643  }
644 
645  b = model->bench_list->first;
646 
647 
648  c = 0;
649  while(b != NULL && c < n) {
650 
651  if(options->plot_average == 1) {
652  b_plot = get_avg_bench_from_sorted_bench_list(b, b->p);
653 
654  if(b_plot == NULL) {
655  ERRPRINTF("Error getting average of benchmark:\n");
657  exit(EXIT_FAILURE);
658  }
659  }
660  else if(options->plot_max == 1) {
661  b_plot = NULL;
662  b_plot = find_max_bench_in_sorted_bench_list(b, b->p);
663 
664  if(b_plot == NULL) {
665  ERRPRINTF("Error getting max of benchmark:\n");
667  exit(EXIT_FAILURE);
668  }
669  }
670  else {
671  b_plot = b;
672  }
673 
674  x[c] = (double)b->p[0];
675  y[c] = b_plot->flops;
676 
677  printf("c:%d/%d x:%f y:%f\n", c, n, x[c], y[c]);
678 
679  c++;
680 
681  if(options->plot_average == 1)
682  {
683  free_benchmark(&b_plot);
685  }
686  else if(options->plot_max == 1) {
688  }
689  else {
690  b = b->next;
691  }
692 
693  }
694 
695 
696  if(b != NULL && c != n-1) {
697  printf("Error, unexpected number of benchmarks\n");
698  exit(EXIT_FAILURE);
699  }
700 
701  set_plot_labels_ranges(plot_handle, model, &plot_title_buf);
702 
703  if(options->plot_palette == 1) {
704  gnuplot_cmd(plot_handle, "set palette");
705  gnuplot_setstyle(plot_handle, "points palette");
706  }
707  else if(options->plot_style != NULL) {
708  gnuplot_setstyle(plot_handle, options->plot_style);
709  }
710 
711  gnuplot_plot_xy(plot_handle, x, y, n, plot_title_buf);
712 
713  if(options->plot_intervals == 1) {
714  draw_plot_intervals(plot_handle, model);
715  }
716 
717  free(plot_title_buf);
718  plot_title_buf = NULL;
719 
720  free(x);
721  x = NULL;
722 
723  free(y);
724  y = NULL;
725 }
726 
727 /*!
728  * plot an interpolated one dimensional slice of a 2 parameter model
729  *
730  * @param plot_handle pointer to gnuplot handle
731  * @param model pointer to model
732  * @param options pointer to options
733  *
734  */
735 void
736 plot_slice_interp_model(gnuplot_ctrl *plot_handle, struct pmm_model *model,
737  struct pmm_view_options *options)
738 {
739  int i, j;
740  double *x;
741  double *y;
742  int n;
743  char *plot_title_buf;
744  int ret;
745 
746  int pfound;
747  int p0; // the planes that we will plot (should those not speficied in
748  // the slice
749  //
750  int max, min;
751 
752 
753  struct pmm_octave_data *oct_data;
754  double *approx_speeds;
755  int **base_points;
756  int mode;
757 
758 
759 
760  // find the free parameter of the model (which the plot will be
761  // in terms of)
762  p0=-1;
763  for(i=0; i<model->n_p; i++) {
764  pfound = 0;
765  for(j=0; j<options->slice_arr_size; j++) {
766  if(i==options->slice_i_arr[j]) {
767  pfound = 1;
768  break;
769  }
770  }
771 
772  if(pfound == 0) {
773  if(p0 < 0) {
774  p0 = i;
775  }
776  else {
777  ERRPRINTF("Found too many free parameters.\n");
778  exit(EXIT_FAILURE);
779  }
780  }
781  }
782 
783  if(p0 < 0) {
784  ERRPRINTF("Not found enough free parameters.\n");
785  }
786 
787 
788  // set max and min of parameter we will interpolate over
789  min = model->pd_set->pd_array[p0].start;
790  max = model->pd_set->pd_array[p0].end;
791 
792  n = options->slice_interpolate;
793 
794  mode = PMM_ALL;
795  if(options->plot_average == 1) {
796  mode = PMM_AVG;
797  }
798  else if(options->plot_max == 1) {
799  mode = PMM_MAX;
800  }
801 
802  base_points = malloc(n * sizeof *base_points);
803  approx_speeds = malloc(n * sizeof *approx_speeds);
804  x = malloc(n * sizeof *x);
805 
806  if(x == NULL || base_points == NULL || approx_speeds == NULL) {
807  ERRPRINTF("Error allocating memory (n:%d).\n", n);
808  exit(EXIT_FAILURE);
809  }
810 
811  octave_init();
812 
813  // TODO fill with max, avg or all points in model
814  oct_data = fill_octave_input_matrices(model, mode);
815  if(oct_data == NULL) {
816  ERRPRINTF("Error preparing octave input data.\n");
817  exit(EXIT_FAILURE);
818  }
819 
820  if(octave_triangulate(oct_data) < 0) {
821  ERRPRINTF("Error calculating triangulation of data.\n");
822  exit(EXIT_FAILURE);
823  }
824 
825  // prep the interpolation array
826  for(i=0; i<n; i++) {
827  base_points[i] = malloc(model->n_p * sizeof(int));
828  for(j=0; j<options->slice_arr_size; j++) {
829  base_points[i][options->slice_i_arr[j]] = options->slice_val_arr[j];
830  }
831 
832  x[i] = (double)min + (double)i*((max-min)/(double)n);
833  base_points[i][p0] = x[i];
834  }
835 
836 
837  approx_speeds = octave_interp_array(oct_data, base_points, model->n_p, n);
838 
839  if(approx_speeds == NULL) {
840  ERRPRINTF("Error interpolating model.\n");
841  exit(EXIT_FAILURE);
842  }
843 
844  y = approx_speeds;
845 
846  if(model->parent_routine != NULL) {
847  ret = asprintf(&plot_title_buf, "%s model", model->parent_routine->name);
848  if(ret < 0) {
849  ERRPRINTF("Error setting plot title.\n");
850  }
851  }
852  else {
853  ret = asprintf(&plot_title_buf, "%s", basename(model->model_path));
854  if(ret < 0) {
855  ERRPRINTF("Error setting plot title.\n");
856  }
857  }
858 
859  if(options->plot_palette == 1) {
860  gnuplot_cmd(plot_handle, "set palette");
861  gnuplot_setstyle(plot_handle, "points palette");
862  }
863  else if(options->plot_style != NULL) {
864  gnuplot_setstyle(plot_handle, options->plot_style);
865  }
866 
867  gnuplot_plot_xy(plot_handle, x, y, n, plot_title_buf);
868 
869  free(plot_title_buf);
870  plot_title_buf = NULL;
871 
872  free(x);
873  x = NULL;
874 
875  free(approx_speeds);
876  y = NULL; approx_speeds = NULL;
877 
878  for(i=0; i<n; i++) {
879  free(base_points[i]);
880  base_points[i] = NULL;
881  }
882  free(base_points);
883  base_points = NULL;
884 
885 }
886 
887 
888 /*!
889  * plot a 2-d projection of a higher-d model
890  *
891  * @param plot_handle pointer to gnuplot control structure
892  * @param model pointer to model to plot
893  * @param options pointer to options structure
894  */
895 void
896 plot_slice_model(gnuplot_ctrl *plot_handle, struct pmm_model *model,
897  struct pmm_view_options *options)
898 {
899  int i, j, c;
900  double *x;
901  double *y;
902  int n;
903  char *plot_title_buf;
904  int ret;
905 
906  int pfound;
907  int p0; // the planes that we will plot (should those not speficied in
908  // the slice
909 
910  struct pmm_benchmark *b, *b_plot;
911 
912 
913  // find the free parameter of the model (which the plot will be
914  // in terms of)
915  p0=-1;
916  for(i=0; i<model->n_p; i++) {
917  pfound = 0;
918  for(j=0; j<options->slice_arr_size; j++) {
919  if(i==options->slice_i_arr[j]) {
920  pfound = 1;
921  break;
922  }
923  }
924 
925  if(pfound == 0) {
926  if(p0 < 0) {
927  p0 = i;
928  }
929  else {
930  ERRPRINTF("Found too many free parameters.\n");
931  exit(EXIT_FAILURE);
932  }
933  }
934  }
935 
936  if(p0 < 0) {
937  ERRPRINTF("Not found enough free parameters.\n");
938  }
939 
940  if(options->plot_average == 1 ||
941  options->plot_max == 1)
942  {
944  }
945  else {
946  n = model->bench_list->size;
947  }
948 
949  x = malloc(n * sizeof *x);
950  y = malloc(n * sizeof *y);
951  if(x == NULL || y == NULL) {
952  ERRPRINTF("Error allocating memory (n:%d).\n", n);
953  exit(EXIT_FAILURE);
954  }
955 
956  c=0;
957  b = model->bench_list->first;
958  while(b != NULL) {
959 
960  // if bench b is not in the slice defined by options, get the next b
961  while(b != NULL && bench_in_slice(options, b) == 0) {
962  if(options->plot_average == 1 ||
963  options->plot_max == 1)
964  {
966  }
967  else {
968  b = b->next;
969  }
970  }
971  if(b == NULL) {
972  break;
973  }
974 
975 
976  if(options->plot_average == 1) {
977  b_plot = get_avg_bench_from_sorted_bench_list(b, b->p);
978 
979  if(b_plot == NULL) {
980  ERRPRINTF("Error getting average of benchmark!\n");
982  exit(EXIT_FAILURE);
983  }
984  }
985  else if(options->plot_max == 1) {
986  b_plot = NULL;
987  b_plot = find_max_bench_in_sorted_bench_list(b, b->p);
988 
989  if(b_plot == NULL) {
990  ERRPRINTF("Error getting max of benchmark:\n");
992  exit(EXIT_FAILURE);
993  }
994  }
995  else {
996  b_plot = b;
997  }
998 
999  x[c] = (double)b->p[p0];
1000  y[c] = b_plot->flops;
1001 
1002  printf("c:%d/%d x:%f y:%f\n", c, n, x[c], y[c]);
1003 
1004  c++;
1005 
1006  if(options->plot_average == 1) {
1007  free_benchmark(&b_plot);
1008  b = get_next_different_bench(b);
1009  }
1010  else if(options->plot_max == 1) {
1011  b = get_next_different_bench(b);
1012  }
1013  else {
1014  b = b->next;
1015  }
1016  }
1017 
1018  if(c == 0) {
1019  ERRPRINTF("No benchmarks found along specified slice.\n");
1020  free(x);
1021  x = NULL;
1022 
1023  free(y);
1024  y = NULL;
1025 
1026  return;
1027  }
1028 
1029  if(model->parent_routine != NULL) {
1030  ret = asprintf(&plot_title_buf, "%s model", model->parent_routine->name);
1031  if(ret < 0) {
1032  ERRPRINTF("Error setting plot title.\n");
1033  }
1034  }
1035  else {
1036  ret = asprintf(&plot_title_buf, "%s", basename(model->model_path));
1037  if(ret < 0) {
1038  ERRPRINTF("Error setting plot title.\n");
1039  }
1040  }
1041 
1042  if(options->plot_palette == 1) {
1043  gnuplot_cmd(plot_handle, "set palette");
1044  gnuplot_setstyle(plot_handle, "points palette");
1045  }
1046  else if(options->plot_style != NULL) {
1047  gnuplot_setstyle(plot_handle, options->plot_style);
1048  }
1049 
1050  gnuplot_plot_xy(plot_handle, x, y, c, plot_title_buf);
1051 
1052  free(plot_title_buf);
1053  plot_title_buf = NULL;
1054 
1055  free(x);
1056  x = NULL;
1057 
1058  free(y);
1059  y = NULL;
1060 }
1061 
1062 /*!
1063  * plot a 3-d projection of a higher-d model
1064  *
1065  * @param plot_handle pointer to gnuplot control structure
1066  * @param model pointer to model to plot
1067  * @param options pointer to options structure
1068  */
1069 void
1070 splot_slice_model(gnuplot_ctrl *plot_handle, struct pmm_model *model,
1071  struct pmm_view_options *options)
1072 {
1073  int i, j, c;
1074  double *x;
1075  double *y;
1076  double *z;
1077  int n;
1078  char *plot_title_buf;
1079  int ret;
1080 
1081  int pfound;
1082  int p0, p1; // the planes that we will plot (should those not speficied in
1083  // the slice
1084 
1085  struct pmm_benchmark *b, *b_plot;
1086 
1087 
1088  p0=-1; p1=-1;
1089  for(i=0; i<model->n_p; i++) {
1090  pfound = 0;
1091  for(j=0; j<options->slice_arr_size; j++) {
1092  if(i==options->slice_i_arr[j]) {
1093  pfound = 1;
1094  break;
1095  }
1096  }
1097 
1098  if(pfound == 0) {
1099  if(p0 < 0) {
1100  p0 = i;
1101  }
1102  else if (p1 < 0) {
1103  p1 = i;
1104  }
1105  else {
1106  ERRPRINTF("Found too many free parameters.\n");
1107  exit(EXIT_FAILURE);
1108  }
1109  }
1110  }
1111 
1112  if(p0 < 0 || p1 < 0) {
1113  ERRPRINTF("Not found enough free parameters.\n");
1114  }
1115 
1116  if(options->plot_average == 1 ||
1117  options->plot_max == 1)
1118  {
1120 
1121  }
1122  else {
1123  n = model->bench_list->size;
1124  }
1125 
1126  x = malloc(n * sizeof *x);
1127  y = malloc(n * sizeof *y);
1128  z = malloc(n * sizeof *z);
1129  if(x == NULL || y == NULL || z == NULL) {
1130  ERRPRINTF("Error allocating memory.\n");
1131  exit(EXIT_FAILURE);
1132  }
1133 
1134  c=0;
1135  b = model->bench_list->first;
1136  while(b != NULL) {
1137 
1138  while(b != NULL && bench_in_slice(options, b) == 0) {
1139  if(options->plot_average == 1 ||
1140  options->plot_max == 1)
1141  {
1142  b = get_next_different_bench(b);
1143  }
1144  else {
1145  b = b->next;
1146  }
1147  }
1148  if(b == NULL) {
1149  break;
1150  }
1151 
1152 
1153  if(options->plot_average == 1) {
1154  b_plot = get_avg_bench_from_sorted_bench_list(b, b->p);
1155 
1156  if(b_plot == NULL) {
1157  ERRPRINTF("Error getting average of benchmark!\n");
1159  exit(EXIT_FAILURE);
1160  }
1161  }
1162  else if(options->plot_max == 1) {
1163  b_plot = NULL;
1164  b_plot = find_max_bench_in_sorted_bench_list(b, b->p);
1165 
1166  if(b_plot == NULL) {
1167  ERRPRINTF("Error getting max of benchmark:\n");
1169  exit(EXIT_FAILURE);
1170  }
1171  }
1172  else {
1173  b_plot = b;
1174  }
1175 
1176  x[c] = (double)b->p[p0];
1177  y[c] = (double)b->p[p1];
1178  z[c] = b_plot->flops;
1179 
1180  printf("c:%d/%d x:%f y:%f z:%f\n", c, n, x[c], y[c], z[c]);
1181 
1182  c++;
1183 
1184  if(options->plot_average == 1) {
1185  free_benchmark(&b_plot);
1186  b = get_next_different_bench(b);
1187  }
1188  else if(options->plot_max == 1) {
1189  b = get_next_different_bench(b);
1190  }
1191  else {
1192  b = b->next;
1193  }
1194  }
1195 
1196  if(c == 0) {
1197  ERRPRINTF("No benchmarks found along specified slice.\n");
1198  free(x);
1199  x = NULL;
1200 
1201  free(y);
1202  y = NULL;
1203 
1204  free(z);
1205  z = NULL;
1206  return;
1207  }
1208 
1209  if(model->parent_routine != NULL) {
1210  ret = asprintf(&plot_title_buf, "%s model", model->parent_routine->name);
1211  if(ret < 0) {
1212  ERRPRINTF("Error setting plot title.\n");
1213  }
1214  }
1215  else {
1216  ret = asprintf(&plot_title_buf, "%s", basename(model->model_path));
1217  if(ret < 0) {
1218  ERRPRINTF("Error setting plot title.\n");
1219  }
1220  }
1221 
1222  if(options->plot_palette == 1) {
1223  gnuplot_cmd(plot_handle, "set palette");
1224  gnuplot_setstyle(plot_handle, "points palette");
1225  }
1226  else if(options->plot_style != NULL) {
1227  gnuplot_setstyle(plot_handle, options->plot_style);
1228  }
1229 
1230  gnuplot_splot(plot_handle, x, y, z, c, plot_title_buf);
1231 
1232  free(plot_title_buf);
1233  plot_title_buf = NULL;
1234 
1235  free(x);
1236  x = NULL;
1237 
1238  free(y);
1239  y = NULL;
1240 
1241  free(z);
1242  z = NULL;
1243 
1244  return;
1245 }
1246 
1247 /*!
1248  * plot a 3-d model
1249  *
1250  * @param plot_handle pointer to gnuplot control structure
1251  * @param model pointer to model to plot
1252  * @param options pointer to options structure
1253  */
1254 void
1255 splot_model(gnuplot_ctrl *plot_handle, struct pmm_model *model,
1256  struct pmm_view_options *options)
1257 {
1258  int c;
1259  double *x;
1260  double *y;
1261  double *z;
1262  int n;
1263  char *plot_title_buf;
1264 
1265  struct pmm_benchmark *b, *b_plot;
1266 
1267  // decide how many points will be in plot
1268  if(options->plot_average == 1 ||
1269  options->plot_max == 1)
1270  {
1272  }
1273  else {
1274  n = model->bench_list->size;
1275  }
1276 
1277  // allocate
1278  x = malloc(n * sizeof *x);
1279  y = malloc(n * sizeof *y);
1280  z = malloc(n * sizeof *z);
1281  if(x == NULL || y == NULL || z == NULL) {
1282  ERRPRINTF("Error allocating memory.\n");
1283  exit(EXIT_FAILURE);
1284  }
1285 
1286  // read model into x,y,z
1287  c=0;
1288  b = model->bench_list->first;
1289  while(b != NULL) {
1290 
1291  // do we plot an average/max/raw benchmark
1292  if(options->plot_average == 1) {
1293  b_plot = get_avg_bench_from_sorted_bench_list(b, b->p);
1294 
1295  if(b_plot == NULL) {
1296  ERRPRINTF("Error getting average of benchmark!\n");
1298  exit(EXIT_FAILURE);
1299  }
1300  }
1301  else if(options->plot_max == 1) {
1302  b_plot = NULL;
1303  b_plot = find_max_bench_in_sorted_bench_list(b, b->p);
1304 
1305  if(b_plot == NULL) {
1306  ERRPRINTF("Error getting max of benchmark:\n");
1308  exit(EXIT_FAILURE);
1309  }
1310  }
1311  else {
1312  b_plot = b;
1313  }
1314 
1315  x[c] = (double)b->p[0];
1316  y[c] = (double)b->p[1];
1317  z[c] = b_plot->flops;
1318 
1319  printf("c:%d/%d x:%f y:%f z:%f\n", c, n, x[c], y[c], z[c]);
1320 
1321  c++;
1322 
1323  if(options->plot_average == 1) {
1324  free_benchmark(&b_plot);
1325  b = get_next_different_bench(b);
1326  }
1327  else if(options->plot_max == 1) {
1328  b = get_next_different_bench(b);
1329  }
1330  else {
1331  b = b->next;
1332  }
1333  }
1334 
1335  set_splot_labels_ranges(plot_handle, model, &plot_title_buf);
1336 
1337  if(options->plot_palette == 1) {
1338  gnuplot_cmd(plot_handle, "set palette");
1339  gnuplot_setstyle(plot_handle, "points palette");
1340  }
1341  else if(options->plot_style != NULL) {
1342  gnuplot_setstyle(plot_handle, options->plot_style);
1343  }
1344 
1345  //gnuplot_cmd(plot_handle, "set multiplot");
1346 
1347  // call the gnuplot plotting function
1348  gnuplot_splot(plot_handle, x, y, z, n, plot_title_buf);
1349 
1350  // intervals are not part of the plot but overlayed so must be done after
1351  if(options->plot_intervals == 1) {
1352 
1353  draw_splot_intervals(plot_handle, model);
1354  }
1355 
1356  free(plot_title_buf);
1357  plot_title_buf = NULL;
1358 
1359  free(x);
1360  x = NULL;
1361 
1362  free(y);
1363  y = NULL;
1364 
1365  free(z);
1366  z = NULL;
1367 }
1368 
1369 /*!
1370  * set labels, ranges and title for a 2-d plot
1371  *
1372  * @param plot_handle pointer to gnuplot structure
1373  * @param model pointer to model that is being plot
1374  * @param plot_title_buf pointer to character buffer that will contain title
1375  *
1376  * @return TODO fails with error but no return
1377  */
1378 void
1379 set_plot_labels_ranges(gnuplot_ctrl *plot_handle, struct pmm_model *model,
1380  char **plot_title_buf)
1381 {
1382  int ret;
1383 
1384  if(model->parent_routine != NULL) {
1385 
1386  gnuplot_set_xlabel(plot_handle,
1387  model->parent_routine->pd_set->pd_array[0].name);
1388 
1389  gnuplot_cmd(plot_handle, "set xrange[0:%d]",
1390  model->parent_routine->pd_set->pd_array[0].end >
1391  model->parent_routine->pd_set->pd_array[0].start ?
1392  model->parent_routine->pd_set->pd_array[0].end :
1393  model->parent_routine->pd_set->pd_array[0].start);
1394 
1395  ret = asprintf(plot_title_buf, "%s model", model->parent_routine->name);
1396  if(ret < 0) {
1397  ERRPRINTF("Error setting plot title.\n");
1398  }
1399 
1400  }
1401  else {
1402  ret = asprintf(plot_title_buf, "%s", basename(model->model_path));
1403  if(ret < 0) {
1404  ERRPRINTF("Error setting plot title.\n");
1405  }
1406  }
1407 
1408  gnuplot_cmd(plot_handle, "set yrange[-10:]");
1409  gnuplot_set_ylabel(plot_handle, "flops");
1410 }
1411 
1412 /*!
1413  * set labels, ranges and title for a 3-d plot
1414  *
1415  * @param plot_handle pointer to gnuplot structure
1416  * @param model pointer to model that is being plot
1417  * @param plot_title_buf pointer to character buffer that will contain title
1418  *
1419  * @return TODO fails with error but no return
1420  */
1421 void
1422 set_splot_labels_ranges(gnuplot_ctrl *plot_handle, struct pmm_model *model,
1423  char **plot_title_buf)
1424 {
1425  int ret;
1426 
1427  if(model->parent_routine != NULL) {
1428  gnuplot_set_xlabel(plot_handle,
1429  model->parent_routine->pd_set->pd_array[0].name);
1430  gnuplot_set_ylabel(plot_handle,
1431  model->parent_routine->pd_set->pd_array[1].name);
1432 
1433  gnuplot_cmd(plot_handle, "set xrange[0:%d]",
1434  model->parent_routine->pd_set->pd_array[0].end >
1435  model->parent_routine->pd_set->pd_array[0].start ?
1436  model->parent_routine->pd_set->pd_array[0].end :
1437  model->parent_routine->pd_set->pd_array[0].start);
1438 
1439  gnuplot_cmd(plot_handle, "set yrange[-10:%d]",
1440  model->parent_routine->pd_set->pd_array[1].end >
1441  model->parent_routine->pd_set->pd_array[1].start ?
1442  model->parent_routine->pd_set->pd_array[1].end :
1443  model->parent_routine->pd_set->pd_array[1].start);
1444 
1445  ret = asprintf(plot_title_buf, "%s model", model->parent_routine->name);
1446  if(ret < 0) {
1447  ERRPRINTF("Error setting plot title.\n");
1448  }
1449  }
1450  else {
1451  ret = asprintf(plot_title_buf, "%s", basename(model->model_path));
1452  if(ret < 0) {
1453  ERRPRINTF("Error setting plot title.\n");
1454  }
1455  }
1456 
1457  gnuplot_cmd(plot_handle, "set zrange[0:]");
1458  gnuplot_set_zlabel(plot_handle, "flops");
1459 }
1460 
1461 /*!
1462  * draw construction intervals on 2-d plots
1463  *
1464  * @param plot_handle pointer to gnuplot_ctrl structure
1465  * @param model pointer to model who's construction intervals are
1466  * to be plotted
1467  *
1468  * @return 0 on success (never fails TODO)
1469  */
1470 int
1471 draw_plot_intervals(gnuplot_ctrl *plot_handle, struct pmm_model *model)
1472 {
1473 
1474 
1475  struct pmm_interval *interval;
1476 
1477  // clear arrows and labels
1478  gnuplot_cmd(plot_handle, "unset label");
1479  gnuplot_cmd(plot_handle, "unset arrow");
1480 
1481  gnuplot_cmd(plot_handle, "set label \'point\' at screen 0.1,0.10 right");
1482  gnuplot_cmd(plot_handle, "set label \' \' at screen 0.2,0.10 point ps 1");
1483  gnuplot_cmd(plot_handle, "set label \'empty\' at screen 0.1,0.08 right");
1484  gnuplot_cmd(plot_handle, "set arrow from screen 0.2,0.08 to "
1485  "screen 0.3,0.08 nohead ls %d", IT_GBBP_EMPTY);
1486 
1487  gnuplot_cmd(plot_handle, "set label \'climb\' at screen 0.1,0.06 right");
1488  gnuplot_cmd(plot_handle, "set arrow from screen 0.2,0.06 to "
1489  "screen 0.3,0.06 nohead ls %d", IT_GBBP_CLIMB);
1490 
1491  gnuplot_cmd(plot_handle, "set label \'bisect\' at screen 0.1,0.04 right");
1492  gnuplot_cmd(plot_handle, "set arrow from screen 0.2,0.04 to "
1493  "screen 0.3,0.04 nohead ls %d", IT_GBBP_BISECT);
1494 
1495  gnuplot_cmd(plot_handle, "set label \'inflect\' at screen 0.1,0.02 right");
1496  gnuplot_cmd(plot_handle, "set arrow from screen 0.2,0.02 to "
1497  "screen 0.3,0.02 nohead ls %d", IT_GBBP_INFLECT);
1498 
1499  interval = model->interval_list->top;
1500  while(interval != NULL) {
1501 
1502  print_interval(PMM_DBG, interval);
1503  switch(interval->type) {
1504  case IT_POINT:
1505 
1506  gnuplot_cmd(plot_handle, "set label \' \' at %f,%f "
1507  "point ps 1",
1508  (double)interval->start[0],
1509  0);
1510  break;
1511 
1512  case IT_GBBP_EMPTY:
1513  case IT_GBBP_CLIMB:
1514  case IT_GBBP_BISECT:
1515  case IT_GBBP_INFLECT:
1516 
1517  gnuplot_cmd(plot_handle, "set arrow from %f,%f to "
1518  "%f,%f nohead ls %d",
1519  (double)interval->start[0],
1520  0.0,
1521  (double)interval->end[0],
1522  0.0,
1523  interval->type);
1524 
1525  break;
1526 
1527  default:
1528  break;
1529  }
1530 
1531  interval=interval->previous;
1532  }
1533  gnuplot_cmd(plot_handle, "replot");
1534 
1535  return 0; //success
1536 }
1537 
1538 
1539 /*!
1540  * draw construction intervals on 3-d plots
1541  *
1542  * @param plot_handle pointer to gnuplot_ctrl structure
1543  * @param model pointer to model who's construction intervals are
1544  * to be plotted
1545  *
1546  * @return 0 on success (never fails TODO)
1547  */
1548 int
1549 draw_splot_intervals(gnuplot_ctrl *plot_handle, struct pmm_model *model)
1550 {
1551 
1552 
1553  struct pmm_interval *interval;
1554 
1555  // clear arrows and labels
1556  gnuplot_cmd(plot_handle, "unset label");
1557  gnuplot_cmd(plot_handle, "unset arrow");
1558 
1559  gnuplot_cmd(plot_handle, "set label \'point\' at screen 0.1,0.10 right");
1560  gnuplot_cmd(plot_handle, "set label \' \' at screen 0.2,0.10 point ps 1");
1561  gnuplot_cmd(plot_handle, "set label \'empty\' at screen 0.1,0.08 right");
1562  gnuplot_cmd(plot_handle, "set arrow from screen 0.2,0.08 to "
1563  "screen 0.3,0.08 nohead ls %d", IT_GBBP_EMPTY);
1564 
1565  gnuplot_cmd(plot_handle, "set label \'climb\' at screen 0.1,0.06 right");
1566  gnuplot_cmd(plot_handle, "set arrow from screen 0.2,0.06 to "
1567  "screen 0.3,0.06 nohead ls %d", IT_GBBP_CLIMB);
1568 
1569  gnuplot_cmd(plot_handle, "set label \'bisect\' at screen 0.1,0.04 right");
1570  gnuplot_cmd(plot_handle, "set arrow from screen 0.2,0.04 to "
1571  "screen 0.3,0.04 nohead ls %d", IT_GBBP_BISECT);
1572 
1573  gnuplot_cmd(plot_handle, "set label \'inflect\' at screen 0.1,0.02 right");
1574  gnuplot_cmd(plot_handle, "set arrow from screen 0.2,0.02 to "
1575  "screen 0.3,0.02 nohead ls %d", IT_GBBP_INFLECT);
1576 
1577  interval = model->interval_list->top;
1578  while(interval != NULL) {
1579 
1580  print_interval(PMM_DBG, interval);
1581  switch(interval->type) {
1582  case IT_POINT:
1583 
1584  gnuplot_cmd(plot_handle, "set label \' \' at %f,%f,%f "
1585  "point ps 1",
1586  (double)interval->start[0],
1587  (double)interval->start[1],
1588  0);
1589  break;
1590 
1591  case IT_GBBP_EMPTY:
1592  case IT_GBBP_CLIMB:
1593  case IT_GBBP_BISECT:
1594  case IT_GBBP_INFLECT:
1595 
1596  gnuplot_cmd(plot_handle, "set arrow from %f,%f,%f to "
1597  "%f,%f,%f nohead ls %d",
1598  (double)interval->start[0],
1599  (double)interval->start[1],
1600  0.0,
1601  (double)interval->end[0],
1602  (double)interval->end[1],
1603  0.0,
1604  interval->type);
1605 
1606  break;
1607 
1608  default:
1609  break;
1610  }
1611 
1612  interval=interval->previous;
1613  }
1614  gnuplot_cmd(plot_handle, "replot");
1615 
1616  return 0; //success
1617 }
1618 /*!
1619  * check if a benchmark belongs to a slice defined in a pmm_view_options
1620  * structure
1621  *
1622  * @param options pointer to the options structure containing slice def.
1623  * @param b pointer to the benchmark
1624  *
1625  * @return 0 if benchmark does not belong, 1 if benchmark does belong
1626  */
1627 int
1628 bench_in_slice(struct pmm_view_options *options, struct pmm_benchmark *b)
1629 {
1630  int i;
1631 
1632  for(i=0; i<options->slice_arr_size; i++) {
1633 
1634  DBGPRINTF("i:%d slice_i_arr[i]:%d b-p[]:%d slice_val:%d\n",
1635  i, options->slice_i_arr[i], b->p[options->slice_i_arr[i]],
1636  options->slice_val_arr[i]);
1637 
1638  if(b->p[options->slice_i_arr[i]] == options->slice_val_arr[i]) {
1639 
1640  }
1641  else {
1642  return 0; //false
1643  }
1644  }
1645 
1646  return 1; //true
1647 }
1648