Beispiel #1
0
 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)]
Beispiel #2
0
 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)
Beispiel #3
0
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)
Beispiel #4
0
 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
Beispiel #5
0
 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)
Beispiel #6
0
 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)
Beispiel #7
0
    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
Beispiel #8
0
    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)