def METHOD_NAME(self, n_trial, measure_option, early_stopping=None, callbacks=(), si_prefix="G"):
    """Begin tuning
    Parameters
    ----------
    n_trial: int
        Maximum number of configs to try (measure on real hardware)
    measure_option: dict
        The options for how to measure generated code.
        You should use the return value ot autotvm.measure_option for this argument.
    early_stopping: int, optional
        Early stop the tuning when not finding better configs in this number of trials
    callbacks: List of callable
        A list of callback functions. The signature of callback function is
        (Tuner, List of MeasureInput, List of MeasureResult)
        with no return value. These callback functions will be called on
        every measurement pair. See autotvm/tuner/callback.py for some examples.
    si_prefix: str
        One of tvm.autotvm.utils.SI_PREFIXES. The SI prefix to use when reporting FLOPS.
    """
    measure_batch = create_measure_batch(self.task, measure_option)
    n_parallel = getattr(measure_batch, "n_parallel", 1)
    early_stopping = early_stopping or 1e9
    self.n_trial = n_trial
    self.early_stopping = early_stopping
    # Validate si_prefix arg
    format_si_prefix(0, si_prefix)
    old_level = logger.level
    GLOBAL_SCOPE.in_tuning = True
    i = error_ct = 0
    errors = []
    while i < n_trial:
        if not self.has_next():
            break
        configs = self.next_batch(min(n_parallel, n_trial - i))
        inputs = [MeasureInput(self.task.target, self.task, config) for config in configs]
        results = measure_batch(inputs)
        # keep best config
        for k, (inp, res) in enumerate(zip(inputs, results)):
            config = inp.config
            if res.error_no == 0:
                flops = inp.task.flop / np.mean(res.costs)
                error_ct = 0
                result_msg = res
            else:
                flops = 0
                error_ct += 1
                tb, error = res.costs
                if isinstance(error, str):
                    errors.append(tb + "\n" + error)
                else:
                    errors.append(tb + "\n" + str(error))
                result_msg = errors[-1]
            if flops > self.best_flops:
                self.best_flops = flops
                self.best_config = config
                self.best_measure_pair = (inp, res)
                self.best_iter = i + k
            logger.debug(
                "No: %d\t%sFLOPS: %.2f/%.2f\tresult: %s\t%s",
                i + k + 1,
                si_prefix,
                format_si_prefix(flops, si_prefix),
                format_si_prefix(self.best_flops, si_prefix),
                result_msg,
                config,
            )
        i += len(results)
        self.ttl = min(early_stopping + self.best_iter, n_trial) - i
        self.update(inputs, results)
        for callback in callbacks:
            callback(self, inputs, results)
        if i >= self.best_iter + early_stopping:
            logger.debug("Early stopped. Best iter: %d.", self.best_iter)
            break
        if error_ct > self.error_ct_threshold:
            logging.basicConfig()
            logger.warning("Too many errors happen in the tuning. Switching to debug mode.")
            logger.setLevel(logging.DEBUG)
        else:
            logger.setLevel(old_level)
    if error_ct == i:
        _, f = tempfile.mkstemp(prefix="tvm_tuning_errors_", suffix=".log", text=True)
        with open(f, "w") as file:
            file.write("\n".join(errors))
        logging.warning(
            "Could not find any valid schedule for task %s. "
            "A file containing the errors has been written to %s.",
            self.task,
            f,
        )
    GLOBAL_SCOPE.in_tuning = False
    del measure_batch