def find_maximum_power_budget(layout): # No search because the user specified a fixed power budget? if (utils.argv.power_budget): [temperature, power_distribution] = optimize_power_distribution( layout, utils.argv.power_budget, utils.argv.powerdistopt, utils.argv.power_distribution_optimization_num_trials, utils.argv.power_distribution_optimization_num_iterations) [power_distribution, temperature ] = make_power_distribution_feasible(layout, power_distribution, temperature) return [power_distribution, temperature] # No search because the maximum power possible is already below temperature? utils.info(1, "Checking if the maximum power is cool enough") temperature = Layout.compute_layout_temperature( layout, [layout.get_chip().get_power_levels()[-1]] * layout.get_num_chips()) if (temperature <= utils.argv.max_allowed_temperature): #utils.info(2, "We can set all chips to the max power level!") return [[layout.get_chip().get_power_levels()[-1]] * layout.get_num_chips(), temperature] # No search because the minimum power possible is already above temperature? utils.info(1, "Checking if the minimum power is already too hot") temperature = Layout.compute_layout_temperature( layout, [layout.get_chip().get_power_levels()[0]] * layout.get_num_chips()) if (temperature > utils.argv.max_allowed_temperature): sys.stderr.write( "Even setting all chips to minimum power gives a temperature of " + str(temperature) + ", which is above the maximum allowed temperature of " + str(utils.argv.max_allowed_temperature) + "\n") return None # DISCRETE? if is_power_optimization_method_discrete(utils.argv.powerdistopt): [power_distribution, temperature] = find_maximum_power_budget_discrete(layout) return [power_distribution, temperature] else: # OR CONTINUOUS? [power_distribution, temperature] = find_maximum_power_budget_continuous(layout) [power_distribution, temperature ] = make_power_distribution_feasible(layout, power_distribution, temperature) return [power_distribution, temperature]
def find_maximum_power_budget_discrete_random(layout): power_levels = layout.get_chip().get_power_levels() distribution = layout.get_chip().get_power_levels( )[0] * layout.get_num_chips() best_distribution = None best_distribution_temperature = None for trial in xrange(0, utils.argv.power_distribution_optimization_num_trials): utils.info(2, "Trial #" + str(trial)) distribution = [] for i in xrange(0, layout.get_num_chips()): distribution.append(utils.pick_random_element(power_levels)) temperature = Layout.compute_layout_temperature(layout, distribution) if (temperature <= utils.argv.max_allowed_temperature): if (best_distribution == None) or (sum(best_distribution) < sum(distribution)): best_distribution = distribution best_distribution_temperature = temperature utils.info( 2, "Better Random Trial: Total=" + str(sum(best_distribution)) + "; Distribution=" + str(best_distribution) + "; Temperature= " + str(temperature)) return [best_distribution, best_distribution_temperature]
def minimize_temperature_random_continuous(layout, total_power_budget, num_iterations): # Generate a valid random start random_start = generate_random_power_distribution(layout, total_power_budget) utils.info(1, "\t\tRandom start: " + str(random_start)) # Compute the temperature temperature = Layout.compute_layout_temperature(layout, random_start) return [temperature, random_start]
def minimize_temperature_uniform(layout, total_power_budget, num_iterations): # Generate a uniform power distribution uniform_distribution = layout.get_num_chips() * [ total_power_budget / layout.get_num_chips() ] # Compute the temperature temperature = Layout.compute_layout_temperature(layout, uniform_distribution) return [temperature, uniform_distribution]
def minimize_temperature_neighbor(layout, total_power_budget, num_iterations): # Generate a valid random start random_start = generate_random_power_distribution(layout, total_power_budget) best_distribution = random_start best_temperature = Layout.compute_layout_temperature(layout, random_start) utils.info( 2, "\tGenerated a random start: " + str(best_distribution) + " (temperature = " + str(best_temperature) + ")") epsilon = 1 for iteration in xrange(0, num_iterations): some_improvement = False for pair in list( itertools.product(xrange(0, layout.get_num_chips()), xrange(0, layout.get_num_chips()))): if (pair[0] == pair[1]): continue candidate = list(best_distribution) candidate[pair[0]] += epsilon candidate[pair[1]] -= epsilon if (max(candidate) > max(layout.get_chip().get_power_levels()) ) or (min(best_distribution) < min( layout.get_chip().get_power_levels())): continue temperature = Layout.compute_layout_temperature(layout, candidate) if (temperature < best_temperature): utils.info( 2, "\tNeighbor " + str(candidate) + " has temperature " + str(temperature)) best_temperature = temperature best_distribution = candidate some_improvement = true break # We do a greedy search, which goes toward any improvement if (not some_improvement): break return [best_temperature, best_distribution]
def find_maximum_power_budget_discrete_greedy_random(layout): power_levels = layout.get_chip().get_power_levels() best_best_distribution = None best_best_distribution_temperature = None for trial in xrange(0, utils.argv.power_distribution_optimization_num_trials): utils.info(2, "Trial #" + str(trial)) # Initialize the best distribution (that we're looking for) best_distribution_index = [0] * layout.get_num_chips() best_distribution = [power_levels[x] for x in best_distribution_index] while (True): # pick one non-max chip while (True): picked = utils.pick_random_element( range(0, layout.get_num_chips())) if (best_distribution_index[picked] == len(power_levels) - 1): continue else: break # increase the power of that chip, tentatively candidate_index = list(best_distribution_index) candidate_index[picked] += 1 # Compute the temperature candidate = [power_levels[x] for x in candidate_index] temperature = Layout.compute_layout_temperature(layout, candidate) sys.stderr.write("Looking at: " + str(candidate) + " - Temperature = " + str(temperature) + "\n") # If too hot, nevermind and give up (don't evey try another) if (temperature > utils.argv.max_allowed_temperature): break # Otherwise, great best_distribution_index = list(candidate_index) best_distribution = list(candidate) best_distribution_temperature = temperature if (best_best_distribution == None) or (sum(best_distribution) > sum(best_best_distribution)): best_best_distribution = list(best_distribution) best_best_distribution_temperature = best_distribution_temperature return [best_distribution, best_distribution_temperature]
def make_power_distribution_feasible(layout, power_distribution, initial_temperature): new_temperature = initial_temperature utils.info( 1, "Continuous solution: Total= " + str(sum(power_distribution)) + "; Distribution= " + str(power_distribution)) power_levels = layout.get_chip().get_power_levels() lower_bound = [] for x in power_distribution: for i in xrange(len(power_levels) - 1, -1, -1): if (power_levels[i] <= x): lower_bound.append(i) break utils.info( 1, "Conservative feasible power distribution: " + str([power_levels[i] for i in lower_bound])) # exhaustively increase while possible (TODO: do a better heuristic? unclear) while (True): was_able_to_increase = False for i in xrange(0, len(lower_bound)): tentative_new_bound = lower_bound[:] if (tentative_new_bound[i] < len(power_levels) - 1): tentative_new_bound[i] += 1 # Evaluate the temperate tentative_power_distribution = [ power_levels[x] for x in tentative_new_bound ] temperature = Layout.compute_layout_temperature( layout, tentative_power_distribution) if (temperature <= utils.argv.max_allowed_temperature): lower_bound = tentative_new_bound[:] new_temperature = temperature was_able_to_increase = True utils.info( 1, "Improved feasible power distribution: " + str([power_levels[i] for i in lower_bound])) break if (not was_able_to_increase): break return ([power_levels[x] for x in lower_bound], new_temperature)
def find_maximum_power_budget_discrete_exhaustive(layout): power_levels = layout.get_chip().get_power_levels() best_distribution = None best_distribution_temperature = None for distribution in itertools.permutations(power_levels, layout.get_num_chips()): temperature = Layout.compute_layout_temperature(layout, distribution) if (temperature <= utils.argv.max_allowed_temperature): if (best_distribution == None) or (sum(best_distribution) < sum(distribution)): best_distribution = distribution best_distribution_temperature = temperature utils.info( 2, "Better distribution: Total=" + str(sum(best_distribution)) + "; Distribution=" + str(best_distribution) + "; Temperature= " + str(best_distribution_temperature)) return [best_distribution, best_distribution_temperature]
def find_maximum_power_budget_discrete_uniform(layout): power_levels = layout.get_chip().get_power_levels() best_power_level = None guess_temperature = None lower_bound = 0 #TODO:top level find max power budget checks max and min, set lower boutnd =1? and upper boutnd len(power_levels)-1-1 upper_bound = len( power_levels) - 2 ###TODO: check that - 2 works, changed from - 1 guess_index = -1 while (lower_bound != upper_bound): #print "l=", lower_bound, "u=", upper_bound if (guess_index == (upper_bound + lower_bound) / 2): break guess_index = (upper_bound + lower_bound) / 2 #print "Trying guess ", guess_index temperature = Layout.compute_layout_temperature( layout, [power_levels[guess_index]] * layout.get_num_chips()) #print "temperature = ", temperature if (temperature > utils.argv.max_allowed_temperature): upper_bound = guess_index else: guess_temperature = temperature lower_bound = guess_index #print "PICKED index ", guess_index best_power_level = power_levels[guess_index] # for level in power_levels: #temperature = Layout.compute_layout_temperature(layout, [level] * layout.get_num_chips()) #utils.info(2, "With power level " + str(level) + " for all chips: temperature = " + str(temperature)); #if (temperature<=utils.argv.max_allowed_temperature): #best_power_level = level #best_distribution_temperature = temperature #else: #break return [[best_power_level] * layout.get_num_chips(), guess_temperature]
def find_maximum_power_budget_discrete_greedy_not_so_random(layout): power_levels = layout.get_chip().get_power_levels() best_best_distribution = None best_best_distribution_temperature = None for trial in xrange(0, utils.argv.power_distribution_optimization_num_trials): utils.info(2, "Trial #" + str(trial)) # Initialize the best distribution (that we're looking for) best_distribution_index = [0] * layout.get_num_chips() best_distribution = [power_levels[x] for x in best_distribution_index] best_temperature = Layout.compute_layout_temperature( layout, best_distribution) while (True): # Evaluate all possible increases pay_off = [] utils.info(2, "Looking at all neighbors...") for i in xrange(0, layout.get_num_chips()): # If we're already at the max, set the payoff to a <0 value if (best_distribution_index[i] == len(power_levels) - 1): pay_off.append(-1.0) continue # Otherwise compute the payoff candidate_index = list(best_distribution_index) candidate_index[i] += 1 power_increase = power_levels[ candidate_index[i]] - power_levels[candidate_index[i] - 1] candidate = [power_levels[x] for x in candidate_index] temperature = Layout.compute_layout_temperature( layout, candidate) if (temperature > utils.argv.max_allowed_temperature): pay_off.append(-1.0) else: temperature_increase = temperature - best_temperature pay_off.append(power_increase / temperature_increase) # If all negative, we're done if (max(pay_off) < 0.0): break # Pick the best payoff utils.info(2, "Neighbor payoffs: " + str(pay_off)) picked = pay_off.index(max(pay_off)) utils.info(2, "Picking neighbor #" + str(picked)) # Otherwise, great best_distribution_index[picked] += 1 best_distribution = [power_levels[x] for x in candidate_index] best_distribution_temperature = Layout.compute_layout_temperature( layout, best_distribution) utils.info( 2, "New temperature = " + str(best_distribution_temperature)) if (best_best_distribution == None) or ( sum(best_distribution) > sum(best_best_distribution)): best_best_distribution = list(best_distribution) best_best_distribution_temperature = best_distribution_temperature return [best_distribution, best_distribution_temperature]
def basinhopping_objective_layout_temperature(x, layout): return Layout.compute_layout_temperature(layout, x)