def __init__(self, users, args): Estimator.__init__(self, users, args) self.fanout = self.args.hie_fanout self.n = self.users.n - self.users.m self.num_levels = int(math.log(self.n, self.fanout)) self.epsilon = self.args.range_epsilon / self.num_levels self.granularities = [self.fanout**h for h in range(self.num_levels)]
def __bayesian_trial(**kwargs): """ The 'black box function' implemented in the Bayesian Optimization method :param kwargs: An API for the Bayesian Optimization package used :return: Score of the Bayesian trial """ param_dict = OrderedDict(locals()['kwargs']) # Make into discrete params discrete_params = __make_discrete_param(param_dict) # Get the operations for this discrete param architecture, operations = self.architecture, self.param_op_map[ discrete_params] estimator = Estimator(architecture, operations) energy, area, cycle = estimator.estimate( ["energy", "area", "cycle"], analysis=False) return score_firmware(energy, area, cycle)
def run(q: Queue): try: from Camera.Camera import Camera from estimator.estimator import Estimator camera = Camera() estimator = Estimator() q.put(CMD.READY) while True: frame = camera.get_frame() r, i = estimator.get_result(frame) cmd = q.get() if cmd == CMD.GETPOSE: q.put({'results': r, 'img_show': i}) elif cmd == CMD.QUIT: break camera.stop() except Exception as e: q.put(CMD.CAMERR)
def __linear_search(self): e_time = time.time() # Conduct a linear search for k, v in self.param_op_map.items(): estimator = Estimator(architecture=self.architecture, operations=v) estimation = estimator.estimate(["energy", "area", "cycle"], False) energy, area, cycle = estimation self.param_cost_map[k] = (score_firmware(energy, area, cycle), estimation) top_solution = max(((*v, k) for k, v in self.param_cost_map.items())) linear_score = abs(top_solution[0]) linear_eac, linear_p = top_solution[1], top_solution[2] linear_sol = { self.fw_param_labels[i]: linear_p[i] for i in range(len(linear_p)) } # print(len(self.param_cost_map), "combinations estimated") # print("Exhaustive Linear Search Time: ", time.time() - e_time) return linear_sol, linear_score, linear_eac
def __init__(self, users, args): Estimator.__init__(self, users, args) self.percentile_estimator = PercentileEstimatorFactory.create_estimator( 'sw_mse', users, args) self.range_estimator = RangeEstimatorFactory.create_estimator( 'hm', users, args)
def __init__(self, users, args): Estimator.__init__(self, users, args) self.percentile_estimator = PercentileEstimatorFactory.create_estimator('nm_mse', users, args) self.range_estimator = RangeEstimatorFactory.create_estimator('guess_hierarchy', users, args)
def __bayesian_optimization_search(self): """ Employ Bayesian Optimization algorithm to search for optimal firmware solutions :return: tuple of len == 3: (solution_arguments, score, (energy, area, cycle)) """ def __bayesian_trial(**kwargs): """ The 'black box function' implemented in the Bayesian Optimization method :param kwargs: An API for the Bayesian Optimization package used :return: Score of the Bayesian trial """ param_dict = OrderedDict(locals()['kwargs']) # Make into discrete params discrete_params = __make_discrete_param(param_dict) # Get the operations for this discrete param architecture, operations = self.architecture, self.param_op_map[ discrete_params] estimator = Estimator(architecture, operations) energy, area, cycle = estimator.estimate( ["energy", "area", "cycle"], analysis=False) return score_firmware(energy, area, cycle) def __make_discrete_param(continuous_param_set: OrderedDict): """ Round a continuous parameter set suggested by the Bayesian Model into a discrete parameter set that is valid. Uses Euclidean distance algorithm :param continuous_param_set: The set of continuous params, size N :return: The parameter set made discrete, as an OrderedDict(). This will be put into **kwargs of Black Box Function """ continuous_param_ordered = [ continuous_param_set[i] for i in self.fw_param_labels ] continuous_param = np.array(tuple(continuous_param_ordered)) euclid_distance = lambda x, y: np.sqrt(((x - y)**2).sum(axis=0)) distances = sorted( [[euclid_distance(np.array(p), continuous_param), p] for p in self.param_op_map]) return distances[0][1] b_start = time.time() # Conduct Bayesian optimization over the firmware possibilities # Set the parameter boundaries param_bounds = OrderedDict() fw_param_point_set = self.param_op_map.keys() for i in range(len(self.fw_param_labels)): dimension_i = [p[i] for p in fw_param_point_set] # Heuristic: generally large tiles are more efficient print() max_i, min_i = max(dimension_i) * 1.25, min(dimension_i) * 0.9 param_bounds[self.fw_param_labels[i]] = (min_i, max_i) # Now apply the Bayesian model seed_num = math.ceil(len(self.param_op_map) * 0.01) bayes_model = BayesianOptimization(f=__bayesian_trial, pbounds=param_bounds, random_state=10, verbose=True) bayes_model.maximize(seed_num * 3, seed_num, kappa=1) bayes_score = abs(bayes_model.max['target']) bayes_p = __make_discrete_param(bayes_model.max['params']) bayes_sol = { self.fw_param_labels[i]: bayes_p[i] for i in range(len(bayes_p)) } e = Estimator(self.architecture, self.param_op_map[bayes_p]) self.best_ops = self.param_op_map[bayes_p] bayes_eac = e.estimate(['energy', 'area', 'cycle'], analysis=False) # print("Bayes Firmware Estimate:", bayes_sol, "Score of:", bayes_score) # print("Bayesian Time:", time.time() - b_start) return bayes_sol, bayes_score, bayes_eac
def search_combinations(self, top_solutions_num=3, hw_algorithm="bayes", fw_algorithm="bayes", verbose=False): """ Key algorithm to (1) search for different hardware-firmware combinations, (2) rank all these HW-FW combinations, and (3) output detailed component analysis for the top N architectures :param hw_algorithm: Algorithm used to search for hardware. Currently supports Bayesian Optimization ('bayes'), which is default, and linear-exhaustive search ('linear') :param top_solutions_num: Number of top solutions to be analyzed in detail :param fw_algorithm: Algorithm used to search for firmware. Currently supports Bayesian Optimization ('bayes'), which is default, and linear-exhaustive search ('linear') :param verbose: Whether the output log should include details of all the different hardware-firmware combinations searched :return: None. Will output search results in test_run folder, keeping track of search log details etc. """ start_time = time.time() self.algorithm_map[hw_algorithm](top_solutions_num, fw_algorithm, verbose) end_time = time.time() # Summarize the search, create output directory run_id = time.time_ns() out_dir = f"project_io/test_run/run_{run_id}" os.mkdir(out_dir) self.logger.add_line("=" * 50) self.logger.add_line( f"Total: {self.combinations_searched} combinations searched") self.logger.add_line("=" * 50) self.logger.add_line(f"Top solutions found:") for solution_i in range(top_solutions_num): solution = self.top_solutions[solution_i] self.logger.add_line(f"#{solution_i + 1}\t\t{'*' * 20}") self.logger.add_line(f"\t\tScore: {solution[0]}") self.logger.add_line( f"\t\tEnergy (pJ), Area (um^2), Cycle: {solution[2]}") self.logger.add_line(f"\t\tHardware: {solution[3].config_label}") self.logger.add_line(f"\t\tFirmware: {solution[1]}") self.logger.add_line( f"Execution time: {end_time - start_time} seconds") self.logger.write_out(os.path.join(out_dir, "search_log.txt")) # Retrieve the optimal architecture + operations, and analyze in detail. (Pie charts) # Do this by running Estimator again with analysis = True for i in range(top_solutions_num): solution_folder = os.path.join(out_dir, f"rank{i + 1}") os.mkdir(os.path.join(out_dir, f"rank{i + 1}")) analysis_arch = self.top_solutions[i][3] # Reset the firmware mapper to the winning architecture model self.firmware_mapper.architecture = analysis_arch self.firmware_mapper.run_operationalizer( ) # To get the param_op map firmware_config = self.top_solutions[i][1] # print(firmware_config, self.firmware_mapper.fw_param_labels) param_op = tuple(firmware_config[x] for x in self.firmware_mapper.fw_param_labels) analysis_op = self.firmware_mapper.param_op_map[param_op] analysis_estimator = Estimator(analysis_arch, analysis_op) analysis_estimator.estimate(["energy", "area", "cycle"], analysis=True, out_dir=solution_folder)