/* module_analysis */ int module_analysis(void) { OUTPUT(("%s", _YELLOW("Analysing measurements"))); if (PERFEXPERT_SUCCESS != output_analysis()) { OUTPUT(("%s", _ERROR("printing analysis report"))); return PERFEXPERT_ERROR; } return PERFEXPERT_SUCCESS; }
/* module_compile */ int module_compile(void) { OUTPUT(("%s [%s]", _YELLOW("Compiling"), globals.program)); if (PERFEXPERT_SUCCESS != run_clean()) { return PERFEXPERT_ERROR; } if (PERFEXPERT_SUCCESS != run_make()) { return PERFEXPERT_ERROR; } return PERFEXPERT_SUCCESS; }
/* module_measurements */ int module_measurements(void) { OUTPUT(("%s", _YELLOW("Setting performance events"))); my_module_globals.hpctoolkit = (perfexpert_module_hpctoolkit_t *) perfexpert_module_available("hpctoolkit"); if (PERFEXPERT_SUCCESS != my_module_globals.hpctoolkit->set_event( "PAPI_TOT_CYC")) { OUTPUT(("%s", _ERROR("unable to generate add PAPI_TOT_CYC"))); return PERFEXPERT_ERROR; } return PERFEXPERT_SUCCESS; }
/* parse_cli_params */ int parse_module_args(int argc, char *argv[]) { int i = 0; /* If some environment variable is defined, use it! */ if (PERFEXPERT_SUCCESS != parse_env_vars()) { OUTPUT(("%s", _ERROR("parsing environment variables"))); return PERFEXPERT_ERROR; } /* Parse arguments */ argp_parse(&argp, argc, argv, 0, 0, NULL); /* Sanity check: threshold is mandatory, check limits */ if (((0 >= my_module_globals.threshold) || (1 < my_module_globals.threshold))) { OUTPUT(("%s", _ERROR("invalid threshold"))); return PERFEXPERT_ERROR; } OUTPUT_VERBOSE((7, "%s", _BLUE("Summary of options"))); OUTPUT_VERBOSE((7, " Threshold: %f", my_module_globals.threshold)); OUTPUT_VERBOSE((7, " Verbose level: %d", my_module_globals.verbose)); /* Not using OUTPUT_VERBOSE because I want only one line */ if (8 <= my_module_globals.verbose) { i = 0; printf("%s %s", PROGRAM_PREFIX, _YELLOW("options:")); for (i = 0; i < argc; i++) { printf(" [%s]", argv[i]); } printf("\n"); fflush(stdout); } return PERFEXPERT_SUCCESS; }
/* lcpi_compute */ int lcpi_compute(profile_t *profile) { lcpi_t *hotspot_lcpi = NULL, *lcpi = NULL; procedure_t *hotspot = NULL; double *values = NULL; char **names = NULL; int count = 0; OUTPUT_VERBOSE((4, " %s", _CYAN("Calculating LCPI metrics"))); /* For each hotspot in this profile... */ hotspot = (procedure_t *)perfexpert_list_get_first(&(profile->hotspots)); while ((perfexpert_list_item_t *)hotspot != &(profile->hotspots.sentinel)) { OUTPUT_VERBOSE((8, " [%d] %s", hotspot->id, _YELLOW(hotspot->name))); /* For each LCPI definition */ for (lcpi = globals.lcpi_by_name; lcpi != NULL; lcpi = lcpi->hh_str.next) { /* Copy LCPI definitions into this hotspot LCPI hash */ PERFEXPERT_ALLOC(lcpi_t, hotspot_lcpi, sizeof(lcpi_t)); strcpy(hotspot_lcpi->name_md5, lcpi->name_md5); hotspot_lcpi->name = lcpi->name; hotspot_lcpi->value = lcpi->value; hotspot_lcpi->expression = lcpi->expression; /* Get the list of variables and their values */ evaluator_get_variables(hotspot_lcpi->expression, &names, &count); if (0 < count) { int i = 0; PERFEXPERT_ALLOC(double, values, (sizeof(double*) * count)); for (i = 0; i < count; i++) { metric_t *metric = NULL; char key_md5[33]; strcpy(key_md5, perfexpert_md5_string(names[i])); perfexpert_hash_find_str(hotspot->metrics_by_name, (char *)&key_md5, metric); if (NULL == metric) { perfexpert_hash_find_str(globals.machine_by_name, (char *)&key_md5, metric); if (NULL == metric) { values[i] = 0.0; } else { values[i] = metric->value; } } else { values[i] = metric->value; } } /* Evaluate the LCPI expression */ hotspot_lcpi->value = evaluator_evaluate( hotspot_lcpi->expression, count, names, values); PERFEXPERT_DEALLOC(values); } /* Add the LCPI to the hotspot's list of LCPIs */ perfexpert_hash_add_str(hotspot->lcpi_by_name, name_md5, hotspot_lcpi); OUTPUT_VERBOSE((10, " %s=[%g]", hotspot_lcpi->name, hotspot_lcpi->value)); } /* Move on */ hotspot = (procedure_t *)perfexpert_list_get_next(hotspot); }
/* parse_cli_params */ int parse_cli_params(int argc, char *argv[]) { int parameter = 0; /* Temporary variable to hold parameter */ int option_index = 0; /* getopt_long() stores the option index here */ /* If some environment variable is defined, use it! */ if (PERFEXPERT_SUCCESS != parse_env_vars()) { OUTPUT(("%s", _ERROR("Error: parsing environment variables"))); return PERFEXPERT_ERROR; } while (1) { /* get parameter */ parameter = getopt_long(argc, argv, "achi:l:m:M:o:O:t:T:v:w:", long_options, &option_index); /* Detect the end of the options */ if (-1 == parameter) { break; } switch (parameter) { /* Aggregated metrics */ case 'a': globals.aggregate = PERFEXPERT_TRUE; OUTPUT_VERBOSE((1, "option 'a' set")); break; /* Activate colorful mode */ case 'c': globals.colorful = PERFEXPERT_TRUE; OUTPUT_VERBOSE((1, "option 'c' set")); break; /* Show help */ case 'h': OUTPUT_VERBOSE((1, "option 'h' set")); show_help(); return PERFEXPERT_ERROR; /* Input file */ case 'i': globals.inputfile = optarg; OUTPUT_VERBOSE((1, "option 'i' set [%s]", globals.inputfile)); break; /* LCPI file */ case 'l': globals.lcpifile = optarg; OUTPUT_VERBOSE((1, "option 'l' set [%s]", globals.lcpifile)); break; /* Measurement tool */ case 'm': globals.tool = optarg; OUTPUT_VERBOSE((1, "option 'm' set [%s]", globals.tool)); break; /* Machine file */ case 'M': globals.machinefile = optarg; OUTPUT_VERBOSE((1, "option 'M' set [%s]", globals.machinefile)); break; /* Output file */ case 'o': globals.outputfile = optarg; OUTPUT_VERBOSE((1, "option 'o' set [%s]", globals.outputfile)); break; /* Sorting order */ case 'O': globals.order = optarg; OUTPUT_VERBOSE((1, "option 'O' set [%s]", globals.order)); break; /* Threshold */ case 't': globals.threshold = atof(optarg); OUTPUT_VERBOSE((1, "option 't' set [%f]", globals.threshold)); break; /* Thread ID */ case 'T': globals.thread = atoi(optarg); OUTPUT_VERBOSE((1, "option 'T' set [%d]", globals.thread)); break; /* Verbose */ case 'v': globals.verbose = atoi(optarg); OUTPUT_VERBOSE((1, "option 'v' set [%d]", globals.verbose)); break; /* Workdir */ case 'w': globals.workdir = optarg; OUTPUT_VERBOSE((1, "option 'w' set [%s]", globals.workdir)); break; /* Unknown option */ case '?': default: show_help(); return PERFEXPERT_ERROR; } } /* Print summary */ OUTPUT_VERBOSE((7, "%s", _BLUE("Summary of options"))); OUTPUT_VERBOSE((7, " Aggregate? %s", globals.aggregate ? "yes" : "no")); OUTPUT_VERBOSE((7, " Colorful verbose? %s", globals.colorful ? "yes" : "no")); OUTPUT_VERBOSE((7, " Input file: %s", globals.inputfile)); OUTPUT_VERBOSE((7, " LCPI file: %s", globals.lcpifile)); OUTPUT_VERBOSE((7, " Measurement tool: %s", globals.tool)); OUTPUT_VERBOSE((7, " Machine file: %s", globals.machinefile)); OUTPUT_VERBOSE((7, " Output file: %s", globals.outputfile)); OUTPUT_VERBOSE((7, " Sorting order: %s", globals.order)); OUTPUT_VERBOSE((7, " Threshold: %f", globals.threshold)); OUTPUT_VERBOSE((7, " Thread ID: %d", globals.thread)); OUTPUT_VERBOSE((7, " Verbose level: %d", globals.verbose)); OUTPUT_VERBOSE((7, " Output metrcis: %s", globals.outputmetrics)); OUTPUT_VERBOSE((7, " Workdir: %s", globals.workdir)); /* Not using OUTPUT_VERBOSE because I want only one line */ if (8 <= globals.verbose) { int i; printf("%s %s", PROGRAM_PREFIX, _YELLOW("command line:")); for (i = 0; i < argc; i++) { printf(" %s", argv[i]); } printf("\n"); } /* Sanity check: verbose level should be between 1-10 */ if ((0 > globals.verbose) || (10 < globals.verbose)) { OUTPUT(("%s", _ERROR("Error: invalid verbose level"))); show_help(); return PERFEXPERT_ERROR; } /* Sanity check: threshold is mandatory */ if ((0 >= globals.threshold) || (1 < globals.threshold)) { OUTPUT(("%s", _ERROR("Error: undefined or invalid threshold"))); show_help(); return PERFEXPERT_ERROR; } /* Sanity check: inputfile is mandatory */ if (NULL == globals.inputfile) { OUTPUT(("%s", _ERROR("Error: undefined input file"))); show_help(); return PERFEXPERT_ERROR; } /* Sanity check: thread ID must be <= 0, but -1 means NO_THREADS */ if (-1 > globals.thread) { OUTPUT(("%s", _ERROR("Error: invalid thread ID"))); show_help(); return PERFEXPERT_ERROR; } return PERFEXPERT_SUCCESS; }
/* parse_cli_params */ int parse_module_args(int argc, char *argv[]) { int i = 0; /* Set default values */ arg_options = (arg_options_t) { .prefix = NULL, .before = NULL, .after = NULL, .mainsrc = NULL, }; if (((0 >= my_module_globals.threshold) || (1 < my_module_globals.threshold))) { OUTPUT(("%s", _ERROR("invalid threshold"))); return PERFEXPERT_ERROR; } /* If some environment variable is defined, use it! */ if (PERFEXPERT_SUCCESS != parse_env_vars()) { OUTPUT(("%s", _ERROR("parsing environment variables"))); return PERFEXPERT_ERROR; } /* Parse arguments */ argp_parse(&argp, argc, argv, 0, 0, NULL); /* Expand AFTERs, BEFOREs, and PREFIXs arguments */ // TODO: right now we only use the before, after and // prefix from globals. We should also consider values coming // throught args_options.* (that have been set in the previous // instruction if (NULL != arg_options.after) { perfexpert_string_split(perfexpert_string_remove_spaces( arg_options.after), my_module_globals.after, ' '); } if (NULL != arg_options.before) { perfexpert_string_split(perfexpert_string_remove_spaces( arg_options.before), my_module_globals.before, ' '); } if (NULL != arg_options.prefix) { perfexpert_string_split(perfexpert_string_remove_spaces( arg_options.prefix), my_module_globals.prefix, ' '); } if (NULL != arg_options.mainsrc) { my_module_globals.mainsrc = arg_options.mainsrc; } OUTPUT_VERBOSE((7, "%s", _BLUE("Summary of options"))); if (7 <= globals.verbose) { printf("%s Threshold: %f", PROGRAM_PREFIX, my_module_globals.threshold); printf("\n%s Prefix: ", PROGRAM_PREFIX); if (NULL == my_module_globals.prefix[0]) { printf(" (null)"); } else { i = 0; while (NULL != my_module_globals.prefix[i]) { printf(" [%s]", (char *)my_module_globals.prefix[i]); i++; } } printf("\n%s Before each run: ", PROGRAM_PREFIX); if (NULL == my_module_globals.before[0]) { printf(" (null)"); } else { i = 0; while (NULL != my_module_globals.before[i]) { printf(" [%s]", (char *)my_module_globals.before[i]); i++; } } printf("\n%s After each run: ", PROGRAM_PREFIX); if (NULL == my_module_globals.after[0]) { printf(" (null)"); } else { i = 0; while (NULL != my_module_globals.after[i]) { printf(" [%s]", (char *)my_module_globals.after[i]); i++; } } printf("\n%s Main src file: ", PROGRAM_PREFIX); if (NULL == my_module_globals.mainsrc) { printf(" (null)"); } else { printf(" [%s]", (char *)my_module_globals.mainsrc); } printf("\n"); fflush(stdout); } /* Not using OUTPUT_VERBOSE because I want only one line */ if (8 <= globals.verbose) { i = 0; printf("%s %s", PROGRAM_PREFIX, _YELLOW("options:")); for (i = 0; i < argc; i++) { printf(" [%s]", argv[i]); } printf("\n"); fflush(stdout); } return PERFEXPERT_SUCCESS; }
// This function takes the output of running VTune and creates a report CSV file // The results of running VTune are in results_folder // The output of this function is in parse_file // The command it executes is like: // amplxe-cl -R hw-events -r results_folder -group-by=function -format=csv -report-output=parse_file -csv-delimiter=',' // amplxe-cl -report hw-events -group-by=function -group-by=module -group-by=source-file -group-by=source-line -group-by=thread -r results_folder -format=csv -report-output=parse-file -csv-delimiter=',' int create_report(char* results_folder, const char* parse_file) { struct timespec time_start, time_end, time_diff; char *argv[MAX_ARGUMENTS_COUNT]; int argc = 0, i, rc; char buffer[MAX_BUFFER_SIZE]; test_t test; argv[argc] = VTUNE_CL_BIN; argc++; argv[argc] = VTUNE_ACT_REPORT; argc++; argv[argc] = VTUNE_RPT_HW; argc++; argv[argc] = "-group-by=function"; argc++; argv[argc] = "-group-by=module"; argc++; argv[argc] = "-group-by=source-file"; argc++; argv[argc] = "-group-by=source-line"; argc++; if (globals.output_mode == HYBRID_OUTPUT) { argv[argc] = "-group-by=thread"; argc++; } argv[argc] = "-r"; argc++; argv[argc] = my_module_globals.res_folder; argc++; argv[argc] = "-format=csv"; argc++; strcpy(buffer, "-report-output="); strcat(buffer, parse_file); argv[argc] = buffer; argc++; argv[argc] = "-csv-delimiter=','"; argc++; argv[argc] = NULL; /* Not using OUTPUT_VERBOSEbecause I want only one line */ if (8 <= globals.verbose) { printf("%s %s", PROGRAM_PREFIX, _YELLOW("command line:")); for (i = 0; i < argc; i++) { printf(" %s", argv[i]); } printf("\n"); } /* The super-ninja test sctructure */ PERFEXPERT_ALLOC(char, test.output, (strlen(globals.moduledir) + 14)); sprintf(test.output, "%s/vtune.output", globals.moduledir); test.input = my_module_globals.inputfile; test.info = globals.program; clock_gettime(CLOCK_MONOTONIC, &time_start); /* fork_and_wait_and_pray */ rc = perfexpert_fork_and_wait(&test, (char **)argv); /* Evaluate results if required to */ if (PERFEXPERT_FALSE == my_module_globals.ignore_return_code) { switch (rc) { case PERFEXPERT_FAILURE: case PERFEXPERT_ERROR: OUTPUT(("%s (return code: %d) Usually, this means that an error" " happened during the program execution. To see the program" "'s output, check the content of this file: [%s]. If you " "want to PerfExpert ignore the return code next time you " "run this program, set the 'return-code' option for the " "Vtune module. See 'perfexpert -H vtune' for details.", _ERROR("the target program returned non-zero"), rc, test.output)); return PERFEXPERT_ERROR; case PERFEXPERT_SUCCESS: OUTPUT_VERBOSE((7, "[ %s ]", _BOLDGREEN("OK"))); break; default: break; } } /* Calculate and display runtime */ clock_gettime(CLOCK_MONOTONIC, &time_end); perfexpert_time_diff(&time_diff, &time_start, &time_end); OUTPUT((" [1/1] %lld.%.9ld seconds (includes measurement overhead)", (long long)time_diff.tv_sec, time_diff.tv_nsec)); PERFEXPERT_DEALLOC(test.output); /* Run the AFTER program */ if (NULL != my_module_globals.after[0]) { PERFEXPERT_ALLOC(char, test.output, (strlen(globals.moduledir) + 20)); sprintf(test.output, "%s/after.output", globals.moduledir); test.input = NULL; test.info = my_module_globals.after[0]; if (0 != perfexpert_fork_and_wait(&test, (char **)my_module_globals.after)) { OUTPUT(("%s", _RED("'after' command return non-zero"))); } PERFEXPERT_DEALLOC(test.output); }
/* parse_cli_params */ int parse_module_args(int argc, char *argv[]) { int i = 0; /* Set default values */ arg_options = (arg_options_t) { .prefix = NULL, .before = NULL, .after = NULL, .knc_prefix = NULL, .knc_before = NULL, .knc_after = NULL }; /* If some environment variable is defined, use it! */ if (PERFEXPERT_SUCCESS != parse_env_vars()) { OUTPUT(("%s", _ERROR("parsing environment variables"))); return PERFEXPERT_ERROR; } /* Parse arguments */ argp_parse(&argp, argc, argv, 0, 0, NULL); /* Expand AFTERs, BEFOREs, and PREFIXs arguments */ if (NULL != arg_options.after) { perfexpert_string_split(perfexpert_string_remove_spaces( arg_options.after), my_module_globals.after, ' '); } if (NULL != arg_options.before) { perfexpert_string_split(perfexpert_string_remove_spaces( arg_options.before), my_module_globals.before, ' '); } if (NULL != arg_options.prefix) { perfexpert_string_split(perfexpert_string_remove_spaces( arg_options.prefix), my_module_globals.prefix, ' '); } if (NULL != arg_options.knc_after) { perfexpert_string_split(perfexpert_string_remove_spaces( arg_options.knc_after), my_module_globals.knc_after, ' '); } if (NULL != arg_options.knc_before) { perfexpert_string_split(perfexpert_string_remove_spaces( arg_options.knc_before), my_module_globals.knc_before, ' '); } if (NULL != arg_options.knc_prefix) { perfexpert_string_split(perfexpert_string_remove_spaces( arg_options.knc_prefix), my_module_globals.knc_prefix, ' '); } /* Sanity check: MIC options without MIC */ if ((NULL != my_module_globals.knc_prefix[0]) && (NULL == my_module_globals.knc)) { OUTPUT(("%s option -P selected but no MIC card was specified, ignoring", _BOLDRED("WARNING:"))); } /* Sanity check: MIC options without MIC */ if ((NULL != my_module_globals.knc_before[0]) && (NULL == my_module_globals.knc)) { OUTPUT(("%s option -B selected but no MIC card was specified, ignoring", _BOLDRED("WARNING:"))); } /* Sanity check: MIC options without MIC */ if ((NULL != my_module_globals.knc_after[0]) && (NULL == my_module_globals.knc)) { OUTPUT(("%s option -A selected but no MIC card was specified, ignoring", _BOLDRED("WARNING:"))); } OUTPUT_VERBOSE((7, "%s", _BLUE("Summary of options"))); OUTPUT_VERBOSE((7, " Program input file: %s", my_module_globals.inputfile)); if (7 <= globals.verbose) { printf("%s Prefix: ", PROGRAM_PREFIX); if (NULL == my_module_globals.prefix[0]) { printf(" (null)"); } else { i = 0; while (NULL != my_module_globals.prefix[i]) { printf(" [%s]", (char *)my_module_globals.prefix[i]); i++; } } printf("\n%s Before each run: ", PROGRAM_PREFIX); if (NULL == my_module_globals.before[0]) { printf(" (null)"); } else { i = 0; while (NULL != my_module_globals.before[i]) { printf(" [%s]", (char *)my_module_globals.before[i]); i++; } } printf("\n%s After each run: ", PROGRAM_PREFIX); if (NULL == my_module_globals.after[0]) { printf(" (null)"); } else { i = 0; while (NULL != my_module_globals.after[i]) { printf(" [%s]", (char *)my_module_globals.after[i]); i++; } } printf("\n"); fflush(stdout); } #if HAVE_KNC_SUPPORT OUTPUT_VERBOSE((7, " MIC card: %s", my_module_globals.knc)); if (7 <= globals.verbose) { printf("%s MIC prefix: ", PROGRAM_PREFIX); if (NULL == my_module_globals.knc_prefix[0]) { printf(" (null)"); } else { i = 0; while (NULL != my_module_globals.knc_prefix[i]) { printf(" [%s]", (char *)my_module_globals.knc_prefix[i]); i++; } } printf("\n%s MIC before each run:", PROGRAM_PREFIX); if (NULL == my_module_globals.knc_before[0]) { printf(" (null)"); } else { i = 0; while (NULL != my_module_globals.knc_before[i]) { printf(" [%s]", (char *)my_module_globals.knc_before[i]); i++; } } printf("\n%s MIC after each run: ", PROGRAM_PREFIX); if (NULL == my_module_globals.knc_after[0]) { printf(" (null)"); } else { i = 0; while (NULL != my_module_globals.knc_after[i]) { printf(" [%s]", (char *)my_module_globals.knc_after[i]); i++; } } printf("\n"); fflush(stdout); } #endif /* Not using OUTPUT_VERBOSE because I want only one line */ if (8 <= globals.verbose) { i = 0; printf("%s %s", PROGRAM_PREFIX, _YELLOW("options:")); for (i = 0; i < argc; i++) { printf(" [%s]", argv[i]); } printf("\n"); fflush(stdout); } return PERFEXPERT_SUCCESS; }
/* Set default values */ if (NULL == globals.machinefile) { PERFEXPERT_ALLOC(char, globals.machinefile, (strlen(PERFEXPERT_ETCDIR) + strlen(MACHINE_FILE) + 2)); sprintf(globals.machinefile, "%s/%s", PERFEXPERT_ETCDIR, MACHINE_FILE); } if (NULL == globals.lcpifile) { PERFEXPERT_ALLOC(char, globals.lcpifile, (strlen(PERFEXPERT_ETCDIR) + strlen(LCPI_FILE) + 2)); sprintf(globals.lcpifile, "%s/%s", PERFEXPERT_ETCDIR, LCPI_FILE); } /* Print to a file or STDOUT? */ if (NULL != globals.outputfile) { OUTPUT_VERBOSE((7, " %s (%s)", _YELLOW("printing recommendations to file"), globals.outputfile)); if (NULL == (globals.outputfile_FP = fopen(globals.outputfile, "w+"))) { OUTPUT(("%s (%s)", _ERROR("Error: unable to open output file"), globals.outputfile)); return PERFEXPERT_ERROR; } } else { OUTPUT_VERBOSE((7, " printing recommendations to STDOUT")); } /* Parse LCPI metrics */ if (PERFEXPERT_SUCCESS != lcpi_parse_file(globals.lcpifile)) { OUTPUT(("%s (%s)", _ERROR("Error: LCPI file is not valid"), globals.lcpifile)); return PERFEXPERT_ERROR; }