diff --git a/llvm/projects/hpvm-tensor-rt/opentuner/autotuner/algo_tuner.py b/llvm/projects/hpvm-tensor-rt/opentuner/autotuner/algo_tuner.py new file mode 100644 index 0000000000000000000000000000000000000000..784625de26bac8d08b59a69bd4ccf1a060de11fc --- /dev/null +++ b/llvm/projects/hpvm-tensor-rt/opentuner/autotuner/algo_tuner.py @@ -0,0 +1,295 @@ +#!/usr/bin/env python +# +# Algorithmic Approximation Tuning +# Purpose: Tunes for Perforation, Sampling, Numerical Precision (FP16) + + +import adddeps + +import argparse +import opentuner +from opentuner import ConfigurationManipulator +from opentuner import MeasurementInterface +from opentuner import Result +from opentuner import EnumParameter +from opentuner.search.objective import ThresholdAccuracyMinimizeTime +from opentuner.measurement.inputmanager import FixedInputManager +import shutil +import os +import sys +import subprocess +import threading +import psutil + +from measure_confidence2 import dump_promise_confidence_files3 +from measure_confidence2 import getConfidence, getMinAccuracy +from select_top_results import select_top_results +from time import sleep +from pareto_curve import findParetoConfigs + + + + +class TunerData: + def __init__(self): + self.binary_path = "" + self.output_dir = "" + self.num_layers = 0 + self.knobs_list = [] + self.knobs_speedup = {} + self.accuracy_threshold = 0 + self.test_id = 0 + self.layer_costs = [] + self.tuning_flags = [] + self.autotuner_runs = 0 + + + +tunerData = TunerData() + + +def readCostFile(file_path): + + layer_costs = [] + f = open(file_path) + for x in f: + cost = float(x.strip()) + layer_costs.append(cost) + + print ("len(layer_costs) = ", layer_costs) + f.close() + + return layer_costs + + + +def getAccuracy(file_name): + + file = open(file_name, "r") + acc_str = file.read() + file.close() + accuracy = float(acc_str) + + try: + accuracy = float(acc_str) + except: + return 20 + + print (accuracy) + return accuracy + + + +def createFlagsFile(file_name, cfg): + + f = open(file_name, "w+") + cmd_config = "" + for flag in tunerData.tuning_flags: + flag_value = cfg[flag] + cmd_config += str(flag_value) + "\n" + + f.write(cmd_config) + f.close() + + + +def readLayerKnobs(file_path): + + f = open(file_path, "r") + knobs_list = [] + for x in f: + knobs = [] + vals = x.split(",") + for val in vals: + knobs.append(int(val)) + + knobs_list.append(knobs) + + print ("knobs_list = ", knobs_list) + + return knobs_list + + + +def readKnobConfig(file_path): + + knobs_speedup = {} + f = open(file_path, "r") + for x in f: + toks = x.split("\t") + ID = int(toks[0].split(",")[1]) + + speedup = float(toks[2]) + knobs_speedup[ID] = speedup + + print ("knobs_speedup = ", knobs_speedup) + + return knobs_speedup + + + + +def getConfigCost(cfg): + + total_cost = 0.0 + for it in range(tunerData.num_layers): + flag = tunerData.tuning_flags[it] + flag_value = cfg[flag] + op_cost = tunerData.layer_costs[it] + speedup = tunerData.knobs_speedup[flag_value] + + total_cost += (op_cost * 1.0 / speedup * 1.0) + it += 1 + + return total_cost + + + + +class ClangFlagsTuner(MeasurementInterface): + + def __init__(self, args): + objective = ThresholdAccuracyMinimizeTime(tunerData.accuracy_threshold) + input_manager = FixedInputManager(size=tunerData.num_layers) + self.configs_list = [] + + super(ClangFlagsTuner, self).__init__( + args, program_name=args.binary, + program_version=self.file_hash(args.binary), + input_manager=input_manager, objective=objective) + + + + + def manipulator(self): + """ + Define the search space by creating a + ConfigurationManipulator + """ + manipulator = ConfigurationManipulator() + + for i in range(tunerData.num_layers): + tunerData.tuning_flags.append("flag" + str(i)) + + + #for flag in tunerData.tuning_flags: + for ind in range(tunerData.num_layers): + flag = tunerData.tuning_flags[ind] + manipulator.add_parameter( + EnumParameter(flag, tunerData.knobs_list[ind])) + + print ("ind = ", ind, " len = ", len(tunerData.knobs_list)) + print (tunerData.knobs_list[ind]) + ind += 1 + + return manipulator + + + + def run(self, desired_result, input, limit): + + """ + Run a given configuration then + return performance + """ + global test_id + + cfg = desired_result.configuration.data + + # NOTE: creates the file with flags read by the runtime + createFlagsFile("promise_flags", cfg) + + run_cmd = tunerData.binary_path + print "\nbinary_path = ", run_cmd + + + total_runs = 1 # NOTE: Single run sufficient in Algorithmic Approx Tuner + FNULL = open(os.devnull, 'wb') + p = subprocess.Popen([run_cmd, str(total_runs)], stdout = FNULL) + p.wait() + + + accuracy = getAccuracy("final_accuracy") + + # getConfigCost returns the cost associated with the selected configuration + total_comps = getConfigCost(cfg) + + + Result = opentuner.resultsdb.models.Result() + Result.time = total_comps + #Result.accuracy = accuracy + min_accuracy = getMinAccuracy("run_accuracies.txt") + print ("min_accuracy = ", min_accuracy) + Result.accuracy = min_accuracy + + if min_accuracy > tunerData.accuracy_threshold: + config_tuple = (total_comps, accuracy, cfg) + self.configs_list.append(config_tuple) + shutil.copy('promise_flags', tunerData.output_dir + '/' + tunerData.binary_path + '_' + str(tunerData.test_id)) + + f_acc = open(tunerData.output_dir + '/' + tunerData.binary_path + '_' + str(tunerData.test_id) + "_accuracy", "w") + f_acc.write(str(accuracy)) + f_acc.close() + + + tunerData.test_id += 1 + + return Result + + + def save_final_config(self, configuration): + + print "Done with Autotuning Run \n" + sleep(2) + + print "Final configuration", configuration.data + + return + + + + +if __name__ == '__main__': + + argparser = argparse.ArgumentParser(parents=opentuner.argparsers()) + argparser.add_argument('--binary', help='path to target binary') + argparser.add_argument('--num-layers', type=int, help='num of flags to tune') + argparser.add_argument('--accuracy', type=float, help='accuracy threshold') + argparser.add_argument('--result-dir', help='result directory') + argparser.add_argument('--cost-file', help='layer description') + argparser.add_argument('--knobs-config', help='knob settings and ID mapping') + argparser.add_argument('--layer-knobs', help='per-layer Knobs') + + + args = argparser.parse_args() + + tunerData.binary_path = str(args.binary) + tunerData.num_layers = int(args.num_layers) + tunerData.accuracy_threshold = float(args.accuracy) + + + # NOTE: Reading the cost file (with No of ops) to better guide the Autotuner + cost_file_path = args.cost_file + tunerData.layer_costs = readCostFile(cost_file_path) + + + tunerData.knobs_list = readLayerKnobs(args.layer_knobs) + tunerData.knobs_speedup = readKnobConfig(args.knobs_config) + + result_dir = args.result_dir + if result_dir == "": + print("Provide --result-dir ") + + tunerData.output_dir = result_dir + "/high_confidence/" + if not os.path.exists(result_dir): + os.mkdir(result_dir) + + if not os.path.exists(tunerData.output_dir): + print("Creating output directory = ", tunerData.output_dir) + os.mkdir(tunerData.output_dir) + + + + ClangFlagsTuner.main(argparser.parse_args()) + +