docstr: :param candidates_m: candidates lists
  :param U: min resource each candidate needs
  :return:
docstr_tok: [":","param","candidates_m",":","candidates","lists",":","param","U",":","min","resource","each","candidate","needs",":","return",":"]
code: def run_phase2(self, U: int, candidates_m: list):
      """
      :param candidates_m: candidates lists
      :param U: min resource each candidate needs
      :return:
      """
      # print(f" *********** begin BudgetAwareControllerSR with U={U}, K={len(candidates_m)} ***********")
      candidates = copy(candidates_m)
      total_epoch_each_rounds = len(candidates) * U
      min_budget_required = 0
      previous_epoch = None
      scored_cand = None
      while True:
          cur_cand_num = len(candidates)
          if cur_cand_num == 1:
              break
          total_score = []
          # number of each res given to each cand, pick lower bound
          epoch_per_model = int(total_epoch_each_rounds / cur_cand_num)
  
          if previous_epoch is None:
              previous_epoch = epoch_per_model
          elif previous_epoch == epoch_per_model:
              # which means the epoch don't increase, no need to re-evaluate each component
              num_keep = cur_cand_num - 1
              candidates = [ele[0] for ele in scored_cand[-num_keep:]]
              continue
  
          if epoch_per_model >= self.max_unit_per_model:
              epoch_per_model = self.max_unit_per_model
  
          # print(f"[successive_reject]: {cur_cand_num} model left, "
          #       f"and evaluate each model with {epoch_per_model} epoch")
          # evaluate each arch
          for cand in candidates:
              score = self._evaluator.p2_evaluate(cand, epoch_per_model)
              total_score.append((cand, score))
              min_budget_required += epoch_per_model
          # sort from min to max
          scored_cand = sorted(total_score, key=lambda x: x[1])
  
          if epoch_per_model == self.max_unit_per_model:
              # each model is fully evaluated, just return top 1
              candidates = [scored_cand[-1][0]]
          else:
              # only keep m-1, remove the worst one
              num_keep = cur_cand_num - 1
              candidates = [ele[0] for ele in scored_cand[-num_keep:]]
  
      return candidates[0], None, min_budget_required
  
imports: from copy import copy
  from src.common.constant import Config
label_desc: Use image node_id 4 for calling the BudgetAwareControllerSR obj's underlying member method code with example usage: obj.run_phase2(U, candidates_m) and returns: candidates,  None,  min_budget_required