def main(): global search_counter bitcode = sys.argv[1] search_conf_file = sys.argv[2] original_conf_file = sys.argv[3] # # delete log file if exists # try: os.remove("log.dd") except OSError: pass # # parsing config files # search_conf = json.loads(open(search_conf_file, 'r').read()) original_conf = json.loads(open(original_conf_file, 'r').read()) search_changes = search_conf["config"] change_set = [] type_set = [] # # record the change set # for search_change in search_changes: type_vector = search_change.values()[0]["type"] if isinstance(type_vector, list): type_set.append(type_vector) change_set.append(search_change.values()[0]) # # search for valid configuration # print "Searching for valid configuration using delta-debugging algorithm ..." # get original score utilities.to_highest_precision(change_set, type_set) utilities.run_config(search_conf, original_conf, bitcode, search_counter) original_score = utilities.get_dynamic_score(search_counter) * 1.05 search_counter = search_counter + 1 # keep searching while the type set is not searched throughout while not utilities.is_empty(type_set): search_config(change_set, type_set, search_conf, original_conf, bitcode, original_score) # get the score of modified program utilities.run_config(search_conf, original_conf, bitcode, search_counter) modified_score = utilities.get_dynamic_score(search_counter) search_counter = search_counter + 1 if modified_score <= original_score: print "Check valid_" + bitcode + ".json for the valid configuration file" # print valid configuration file and diff file utilities.print_config(search_conf, "dd2_valid_" + bitcode + ".json") utilities.print_diff(search_conf, original_conf, "dd2_diff_" + bitcode + ".json") else: print "No configuration is found!"
def random_local_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, div, original_score, count): initial_change_set = [] for i in range(len(change_set)): initial_change_set.append(change_set[i]["type"]) #print initial_change_set while (count > 0): lower = False while (not lower): if is_bottom(initial_change_set): return lower = randomly_to_2nd_highest_precision(change_set, type_set, switch_set, initial_change_set) count = count - 1 if run_config( search_config, original_config, bitcode, original_score ) == 1 and utilities.get_dynamic_score() <= original_score: initial_change_set = [] for i in range(len(change_set)): initial_change_set.append(change_set[i]["type"]) utilities.print_config(search_config, "final_config_from_random_search.json") fp = open('log.dd', 'a') fp.write(".......................................\n") fp.close()
def search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, original_score): # search from bottom up to_highest_precision(change_set, type_set, switch_set) to_2nd_highest_precision(change_set, type_set, switch_set) if run_config(search_config, original_config, bitcode, original_score ) != 1 or utilities.get_dynamic_score() > original_score: dd_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, 2, original_score) # remove types and switches that cannot be changed for i in xrange(0, len(change_set)): if len(type_set[i]) > 0 and community_obj.get_vars( change_set[i]["name"])[0]["type"] == type_set[i][-1]: del (type_set[i][:]) if len(switch_set[i]) > 0: del (switch_set[i][:]) # remove highest precision from each type vector for i in xrange(0, len(type_set)): type_vector = type_set[i] switch_vector = switch_set[i] if len(type_vector) > 0: type_vector.pop() if len(switch_vector) > 0: switch_vector.pop()
def main(): """ main function receives - argv[1] : bitcode file location - argv[2] : search file location - argv[3] : original config file location """ global BITCODE, SEARCH_CONF, ORIGINAL_CONF, ORIGINAL_SCORE BITCODE = sys.argv[1] SEARCH_CONF = json.loads(open(sys.argv[2], 'r').read()) ORIGINAL_CONF = json.loads(open(sys.argv[3], 'r').read()) # delete log file if exists try: os.remove("log.dd") except OSError: pass # use index to find corresponding type change_set = [] type_set = [] switch_set = [] # parse search configuration file for idx, item in enumerate(SEARCH_CONF["config"]): type_list = item.values()[0]["type"] if isinstance(type_list, list): type_set.append(type_list) change_set.append(item.values()[0]) # put function calls into switch_set if item.keys()[0] == "call": switch_set.append(item.values()[0]["switch"]) else: switch_set.append([]) # parse search grouping group_set = init_groups() print "groups: " print group_set print "\n" # get original score to_highest_precision(change_set, type_set, switch_set) run_config() ORIGINAL_SCORE = utilities.get_dynamic_score() # search for valid configuration using delta-debugging algorithm search_config(change_set, type_set, switch_set, group_set) # get the score of modified program if is_valid_config(): print "Check valid_" + BITCODE + ".json for the valid configuration file" # print valid configuration file and diff file utilities.print_config(SEARCH_CONF, "dd2_valid_" + BITCODE + ".json") utilities.print_diff(SEARCH_CONF, ORIGINAL_CONF, "dd2_diff_" + BITCODE + ".txt") else: print "No configuration is found!"
def is_valid_config(): """ Test if current configuration is valid """ global ORIGINAL_SCORE result = run_config() if result == 1: new_score = utilities.get_dynamic_score() if new_score <= ORIGINAL_SCORE: return True return False
def run_delta(delta_change, delta_type, change_set, type_set, search_config, original_config, bitcode, original_score, inx, queue): if len(delta_change) > 0: # always reset to lowest precision utilities.to_2nd_highest_precision(change_set, type_set) # apply change for variables in delta utilities.to_highest_precision(delta_change, delta_type) # run config result = utilities.run_config(search_config, original_config, bitcode, inx) score = utilities.get_dynamic_score(inx) if result == 1 and score < original_score: queue.put([inx, score])
def random_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, original_score, total_count): utilities.print_config(search_config, "final_config_from_random_search.json") count=total_count opt_score=original_score while(count>0): # search starts with a random initial config to_random_precision(change_set, type_set, switch_set) count=count-1 if run_config(search_config, original_config, bitcode, opt_score) == 1 and utilities.get_dynamic_score() <= opt_score: initial_score = utilities.get_dynamic_score() utilities.print_config(search_config, "final_config_from_random_search.json") fp = open('log.dd', 'a') fp.write("START local search <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n") fp.close() random_count=random.randint(0, count) if random_count>0: opt_score=random_local_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, 2, initial_score, random_count) count=count-random_count fp = open('log.dd', 'a') fp.write("END local search >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n") fp.close()
def search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, original_score): # search from bottom up to_2nd_highest_precision(change_set, type_set, switch_set) if run_config(search_config, original_config, bitcode) != 1 or utilities.get_dynamic_score() > original_score: dd_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, 2, original_score) # remove types and switches that cannot be changed for i in xrange(0, len(change_set)): if len(type_set[i]) > 0 and change_set[i]["type"] == type_set[i][-1]: del(type_set[i][:]) if len(switch_set[i]) > 0: del(switch_set[i][:]) # remove highest precision from each type vector for i in xrange(0, len(type_set)): type_vector = type_set[i] switch_vector = switch_set[i] if len(type_vector) > 0: type_vector.pop() if len(switch_vector) > 0: switch_vector.pop()
def search_config(change_set, type_set, search_config, original_config, bitcode, original_score): global search_counter # search from bottom up utilities.to_2nd_highest_precision(change_set, type_set) if utilities.run_config( search_config, original_config, bitcode, search_counter ) != 1 or utilities.get_dynamic_score(search_counter) > original_score: search_counter = search_counter + 1 dd_search_config(change_set, type_set, search_config, original_config, bitcode, original_score, 2) else: search_counter = search_counter + 1 # remove types that cannot be changed for i in xrange(0, len(change_set)): if len(type_set[i]) > 0 and change_set[i]["type"] == type_set[i][-1]: del (type_set[i][:]) # remove highest precision from each type vector for type_vector in type_set: if len(type_vector) > 0: type_vector.pop()
def main(): global search_counter bitcode = sys.argv[1] search_conf_file = sys.argv[2] original_conf_file = sys.argv[3] # # delete log file if exists # try: os.remove("log.dd") except OSError: pass # # parsing config files # search_conf = json.loads(open(search_conf_file, 'r').read()) original_conf = json.loads(open(original_conf_file, 'r').read()) search_changes = search_conf["config"] change_set = [] type_set = [] # # record the change set # for search_change in search_changes: type_vector = search_change.values()[0]["type"] if isinstance(type_vector, list): type_set.append(type_vector) change_set.append(search_change.values()[0]) # get original score utilities.to_highest_precision(change_set, type_set) utilities.run_config(search_conf, original_conf, bitcode, search_counter) original_score = utilities.get_dynamic_score(search_counter) * 1.05 search_counter = search_counter + 1 cpu_no = CPU_NO # multiprocessing.cpu_count() # # search for valid configuration # print "Searching for valid configuration using delta-debugging algorithm ..." # keep searching while the type set is not searched throughout while not utilities.is_empty(type_set): # # distribute change set # dis_no = ((len(change_set)-1)/cpu_no)+1 queue = Queue() workers = [] for i in xrange(cpu_no): workers.append(Process(target=search_config_dis, args=( change_set[i*dis_no:min((i+1)*dis_no, len(change_set))], type_set[i*dis_no:min((i+1)*dis_no, len(type_set))], search_conf, original_conf, bitcode, search_counter + i*dis_no*dis_no, i*dis_no, queue))) utilities.to_highest_precision(change_set, type_set) for w in workers: w.start() for w in workers: w.join() print len(type_set) while not queue.empty(): inx = queue.get() print inx del(type_set[inx][:]) j = 0 while j < len(type_set): if len(type_set[j]) == 0: type_set.pop(j) change_set.pop(j) else: j += 1 search_counter += cpu_no*dis_no*dis_no search_config(change_set, type_set, search_conf, original_conf, bitcode, original_score) # get the score of modified program utilities.run_config(search_conf, original_conf, bitcode, search_counter) modified_score = utilities.get_dynamic_score(search_counter) search_counter = search_counter + 1 if modified_score <= original_score: print "Check valid_" + bitcode + ".json for the valid configuration file" # print valid configuration file and diff file utilities.print_config(search_conf, "dd2_valid_" + bitcode + ".json") utilities.print_diff(search_conf, original_conf, "dd2_diff_" + bitcode + ".json") else: print "No configuration is found!"
def main(): bitcode = sys.argv[1] search_conf_file = sys.argv[2] original_conf_file = sys.argv[3] partition_conf_file = sys.argv[4] #partition_conf_file = "partition.json" # # delete log file if exists # try: os.remove("log.dd") except OSError: pass if __debug__: try: os.remove("ivy.log") except OSError: pass # # get original config and score # original_conf = json.loads(open(original_conf_file, 'r').read()) run_config(original_conf, original_conf, bitcode, 0) original_score = utilities.get_dynamic_score() if __debug__: fp = open('ivy.log', 'a') print >> fp, "---------" print >> fp, "original score" print >> fp, original_score fp.close() # # hierarchically type tuning # partition_tree = json.loads(open(partition_conf_file, 'r').read()) curr_conf = None curr_score = -1 level = len(partition_tree) - 1 while level >= 0: if __debug__: fp = open('ivy.log', 'a') print >> fp, "partition level and config" print >> fp, level, partition_tree[level] fp.close() search_conf = json.loads(open(search_conf_file, 'r').read()) change_items = search_conf['config'] # delete from the search space the configs that have been pruned if curr_conf != None: reach_bottom_label = 1 for i in range(len(curr_conf['config'])): curr_type = curr_conf['config'][i].values()[0]["type"] type_vector = change_items[i].values()[0]["type"] index = type_vector.index(curr_type) if index != 0: reach_bottom_label = 0 del type_vector[index + 1:] if change_items[i].keys()[0] == "call": del change_items[i].values()[0]["switch"][index + 1:] if reach_bottom_label == 1: break # create communities based on the current level of the partition tree global community_obj community_obj = com.community(partition_tree, change_items, level) if __debug__: fp = open('ivy.log', 'a') print >> fp, "community configs:" print >> fp, community_obj.confs fp.close() # # record the change set # search_changes = community_obj.confs change_set = [] type_set = [] switch_set = [] for i in range(len(search_changes)): type_vector = search_changes[i]["type"] if isinstance(type_vector, list): if len(type_vector) == 1: tmp_set = [] tmp_type_set = [] tmp_switch_set = [] tmp_set.append(search_changes[i]) tmp_type_set.append(type_vector) if "switch" in community_obj.get_vars( search_changes[i]["name"])[0].keys(): tmp_switch_set.append( community_obj.get_vars( search_changes[i]["name"])[0]["switch"]) else: tmp_switch_set.append([]) to_highest_precision(tmp_set, tmp_type_set, tmp_switch_set) else: type_set.append(type_vector) change_set.append(search_changes[i]) if (len(community_obj.get_vars(search_changes[i]["name"])) == 1) & ("switch" in community_obj.get_vars( search_changes[i]["name"])[0].keys()): switch_set.append( community_obj.get_vars( search_changes[i]["name"])[0]["switch"]) else: switch_set.append([]) # # search for valid configuration # print "Searching for valid configuration using delta-debugging algorithm ..." # get current score if curr_score == -1: curr_score = original_score ## 0.95 curr_conf = original_conf # keep searching while the type set is not searched throughout while not is_empty(type_set): search_config(change_set, type_set, switch_set, search_conf, original_conf, bitcode, original_score) # get the score of modified program run_config(search_conf, original_conf, bitcode, 0) modified_score = utilities.get_dynamic_score() if modified_score <= curr_score: curr_conf = search_conf curr_score = modified_score if __debug__: fp = open('ivy.log', 'a') print >> fp, "---------" print >> fp, "updating new score" print >> fp, curr_score fp.close() # print the intermediate level configuration utilities.print_config( curr_conf, "dd2_valid_level" + str(level) + "_" + bitcode + ".json") fleveline = open("log.dd", "a") fleveline.write( "----------------------------------------------------------------------\n" ) fleveline.close() # check the modified configuration ''' if is_bottom_type(change_set): if __debug__ : fp = open('ivy.log', 'a') print>>fp, "stop searching : reach bottom types" print>>fp, search_conf print>>fp, "change set:" print>>fp, change_set fp.close() break ''' level -= 1 # print tuning result if (curr_score <= original_score) & (curr_conf != None): #print valid configuration file and diff file diff = utilities.print_diff(curr_conf, original_conf, "dd2_diff_" + bitcode + ".json") if diff: utilities.print_config(curr_conf, "dd2_valid_" + bitcode + ".json") print "original_score: ", original_score print "modified_score: ", curr_score fp = open('time.txt', 'a') print >> fp, curr_score, "/", original_score fp.close() print "Check valid_" + bitcode + ".json for the valid configuration file" return print "No configuration is found!"
def main(): bitcode = sys.argv[1] search_conf_file = sys.argv[2] original_conf_file = sys.argv[3] if len(sys.argv)>4: total_count = int(sys.argv[4]) else: total_count = 1000 # # delete log file if exists # try: os.remove("log.dd") except OSError: pass # # get configs and the topological order # search_conf = json.loads(open(search_conf_file, 'r').read()) original_conf = json.loads(open(original_conf_file, 'r').read()) # # parsing config files # search_changes = search_conf["config"] change_set = [] type_set = [] switch_set = [] # # record the change set # for search_change in search_changes: type_vector = search_change.values()[0]["type"] if isinstance(type_vector, list): type_set.append(type_vector) change_set.append(search_change.values()[0]) if search_change.keys()[0] == "call": switch_set.append(search_change.values()[0]["switch"]) else: switch_set.append([]) # # search for valid configuration # print "Searching for valid configuration using delta-debugging algorithm ..." # get original score to_highest_precision(change_set, type_set, switch_set) run_config(search_conf, original_conf, bitcode, 0) original_score = utilities.get_dynamic_score() ## 0.95 # keep searching while the type set is not searched throughout if not is_empty(type_set): random_search_config(change_set, type_set, switch_set, search_conf, original_conf, bitcode, original_score, total_count) # get the score of modified program cmd="sed -i -e '1s/{/{\"config\": [/' -e 's/\"localVar/{\"localVar/' -e 's/\"call/{\"call/' -e 's/},/}},/' -e 's/\"name\(.*\),/\"name\\1/' final_config_from_random_search.json" os.system(cmd) os.system("tac <final_config_from_random_search.json | sed -e '2s/},/}/' -e '1s/}/]}/' | tac >tmp_final_config_from_random_search.json") os.system("mv tmp_final_config_from_random_search.json final_config_from_random_search.json") search_conf = json.loads(open("final_config_from_random_search.json", 'r').read()) run_config(search_conf, original_conf, bitcode, 0) modified_score = utilities.get_dynamic_score() if modified_score <= original_score: # print valid configuration file and diff file utilities.print_config(search_conf, "dd2_valid_" + bitcode + ".json") diff = utilities.print_diff(search_conf, original_conf, "dd2_diff_" + bitcode + ".json") if diff: print "original_score: ", original_score print "modified_score: ", modified_score fp = open('time.txt', 'a') print>>fp, modified_score, "/", original_score fp.close() print "Check valid_" + bitcode + ".json for the valid configuration file" return print "No configuration is found!"
def dd_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, div, original_score): # # partition change_set into deltas and delta inverses # delta_change_set = [] delta_type_set = [] delta_switch_set = [] delta_inv_change_set = [] delta_inv_type_set = [] delta_inv_switch_set = [] div_size = int(math.ceil(float(len(change_set)) / float(div))) for i in xrange(0, len(change_set), div_size): delta_change = [] delta_type = [] delta_switch = [] delta_inv_change = [] delta_inv_type = [] delta_inv_switch = [] for j in xrange(0, len(change_set)): if j >= i and j < i + div_size: delta_change.append(change_set[j]) delta_type.append(type_set[j]) delta_switch.append(switch_set[j]) else: delta_inv_change.append(change_set[j]) delta_inv_type.append(type_set[j]) delta_inv_switch.append(switch_set[j]) delta_change_set.append(delta_change) delta_type_set.append(delta_type) delta_switch_set.append(delta_switch) delta_inv_change_set.append(delta_inv_change) delta_inv_type_set.append(delta_inv_type) delta_inv_switch_set.append(delta_inv_switch) # # iterate through all delta and inverse delta set # record delta set that passes # pass_inx = -1 inv_is_better = False min_score = -1 if __debug__: fp = open('ivy.log', 'a') print >> fp, "change_set:" print >> fp, change_set fp.close() for i in xrange(0, len(delta_change_set)): delta_change = delta_change_set[i] delta_type = delta_type_set[i] delta_switch = delta_switch_set[i] if len(delta_change) > 0: if __debug__: fp = open('ivy.log', 'a') print >> fp, "entering delta running" print >> fp, "delta_change:" print >> fp, delta_change fp.close() # always reset to lowest precision to_2nd_highest_precision(change_set, type_set, switch_set) # apply change for variables in delta to_highest_precision(delta_change, delta_type, delta_switch) # record i if config passes if run_config( search_config, original_config, bitcode, original_score ) == 1 and utilities.get_dynamic_score() < original_score: score = utilities.get_dynamic_score() if score < min_score or min_score == -1: pass_inx = i inv_is_better = False min_score = score delta_inv_change = delta_inv_change_set[i] delta_inv_type = delta_inv_type_set[i] delta_inv_switch = delta_inv_switch_set[i] if len(delta_inv_change) > 0 and div > 2: if __debug__: fp = open('ivy.log', 'a') print >> fp, "entering delta inv running" print >> fp, "delta_inv_change:" print >> fp, delta_inv_change fp.close() # always reset to lowest precision to_2nd_highest_precision(change_set, type_set, switch_set) # apply change for variables in delta inverse to_highest_precision(delta_inv_change, delta_inv_type, delta_inv_switch) # record i if config passes if run_config( search_config, original_config, bitcode, original_score ) == 1 and utilities.get_dynamic_score() < original_score: score = utilities.get_dynamic_score() if score < min_score or min_score == -1: pass_inx = i inv_is_better = True min_score = score # # recursively search in pass delta or pass delta inverse # right now keep searching for the first pass delta or # pass delta inverse; later on we will integrate cost # model here # if pass_inx != -1: pass_change_set = delta_inv_change_set[ pass_inx] if inv_is_better else delta_change_set[pass_inx] pass_type_set = delta_inv_type_set[ pass_inx] if inv_is_better else delta_type_set[pass_inx] pass_switch_set = delta_inv_switch_set[ pass_inx] if inv_is_better else delta_switch_set[pass_inx] if len(pass_change_set) > 1: # always reset to lowest precision # search for can-be-lowered items among 'pass_change_set' to_2nd_highest_precision(change_set, type_set, switch_set) dd_search_config(pass_change_set, pass_type_set, pass_switch_set, search_config, original_config, bitcode, 2, original_score) else: # the 2nd highest precision works for all to_2nd_highest_precision(change_set, type_set, switch_set) to_highest_precision(pass_change_set, pass_type_set, pass_switch_set) return # # stop searching when division greater than change set size # if div >= len(change_set): to_highest_precision(change_set, type_set, switch_set) return else: dd_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, 2 * div, original_score) return
def dd_search_config(change_set, type_set, switch_set, group_set, div): # # partition change_set into deltas and delta inverses # delta_change_set = [] delta_type_set = [] delta_switch_set = [] delta_inv_change_set = [] delta_inv_type_set = [] delta_inv_switch_set = [] div_size = int(math.ceil(float(len(group_set)) / float(div))) # import pdb; pdb.set_trace() for i in xrange(0, len(group_set), div_size): delta_change = [] delta_type = [] delta_switch = [] delta_inv_change = [] delta_inv_type = [] delta_inv_switch = [] for j in xrange(0, len(group_set)): group = group_set[j] if j >= i and j < i + div_size: for change_idx in group: delta_change.append(change_set[change_idx]) delta_type.append(type_set[change_idx]) delta_switch.append(switch_set[change_idx]) else: for change_idx in group: delta_inv_change.append(change_set[change_idx]) delta_inv_type.append(type_set[change_idx]) delta_inv_switch.append(switch_set[change_idx]) delta_change_set.append(delta_change) delta_type_set.append(delta_type) delta_switch_set.append(delta_switch) delta_inv_change_set.append(delta_inv_change) delta_inv_type_set.append(delta_inv_type) delta_inv_switch_set.append(delta_inv_switch) # iterate through all delta and inverse delta set # record delta set that passes with min score pass_inx = -1 inv_is_better = False min_score = -1 # import pdb; pdb.set_trace() for i in range(len(delta_change_set)): delta_change = delta_change_set[i] delta_type = delta_type_set[i] delta_switch = delta_switch_set[i] if len(delta_change) > 0: # always reset to lowest precision to_2nd_highest_precision_by_group(change_set, type_set, switch_set, group_set) # apply change for variables in delta to_highest_precision(delta_change, delta_type, delta_switch) # record i if config passes if is_valid_config(): score = utilities.get_dynamic_score() if score < min_score or min_score == -1: pass_inx = i inv_is_better = False min_score = score delta_inv_change = delta_inv_change_set[i] delta_inv_type = delta_inv_type_set[i] delta_inv_switch = delta_inv_switch_set[i] if len(delta_inv_change) > 0 and div > 2: # always reset to lowest precision to_2nd_highest_precision_by_group(change_set, type_set, switch_set, group_set) # apply change for variables in delta inverse to_highest_precision(delta_inv_change, delta_inv_type, delta_inv_switch) # record i if config passes if is_valid_config(): score = utilities.get_dynamic_score() if score < min_score or min_score == -1: pass_inx = i inv_is_better = True min_score = score # import pdb; pdb.set_trace() # # recursively search in pass delta or pass delta inverse # right now keep searching for the first pass delta or # pass delta inverse; later on we will integrate cost # model here # if pass_inx != -1: pass_group_set = group_set[pass_inx * div_size:(pass_inx + 1) * div_size] if inv_is_better: pass_group_set = [ grp for grp in group_set if grp not in pass_group_set ] if len(pass_group_set) > 1: # always reset to lowest precision to_2nd_highest_precision_by_group(change_set, type_set, switch_set, group_set) dd_search_config(change_set, type_set, switch_set, pass_group_set, 2) else: to_2nd_highest_precision_by_group(change_set, type_set, switch_set, group_set) to_highest_precision_by_group(change_set, type_set, switch_set, pass_group_set) return # stop searching when cannot divide groups any more if div_size == 1: to_highest_precision_by_group(change_set, type_set, switch_set, group_set) else: dd_search_config(change_set, type_set, switch_set, group_set, 2 * div)
def main(): bitcode = sys.argv[1] search_conf_file = sys.argv[2] original_conf_file = sys.argv[3] # # delete log file if exists # try: os.remove("log.dd") except OSError: pass # # parsing config files # search_conf = json.loads(open(search_conf_file, 'r').read()) original_conf = json.loads(open(original_conf_file, 'r').read()) search_changes = search_conf["config"] change_set = [] type_set = [] switch_set = [] # # record the change set # for search_change in search_changes: type_vector = search_change.values()[0]["type"] if isinstance(type_vector, list): type_set.append(type_vector) change_set.append(search_change.values()[0]) if search_change.keys()[0] == "call": switch_set.append(search_change.values()[0]["switch"]) else: switch_set.append([]) print switch_set # # search for valid configuration # print "Searching for valid configuration using delta-debugging algorithm ..." # get original score to_highest_precision(change_set, type_set, switch_set) run_config(search_conf, original_conf, bitcode) original_score = utilities.get_dynamic_score() ## 0.95 # keep searching while the type set is not searched throughout while not is_empty(type_set): search_config(change_set, type_set, switch_set, search_conf, original_conf, bitcode, original_score) # get the score of modified program run_config(search_conf, original_conf, bitcode) modified_score = utilities.get_dynamic_score() if modified_score <= original_score: print "Check valid_" + bitcode + ".json for the valid configuration file" # print valid configuration file and diff file utilities.print_config(search_conf, "dd2_valid_" + bitcode + ".json") utilities.print_diff(search_conf, original_conf, "dd2_diff_" + bitcode + ".json") else: print "No configuration is found!"
def dd_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, div, original_score): # # partition change_set into deltas and delta inverses # delta_change_set = [] delta_type_set = [] delta_switch_set = [] delta_inv_change_set = [] delta_inv_type_set = [] delta_inv_switch_set = [] div_size = int(math.ceil(float(len(change_set)) / float(div))) for i in xrange(0, len(change_set), div_size): delta_change = [] delta_type = [] delta_switch = [] delta_inv_change = [] delta_inv_type = [] delta_inv_switch = [] for j in xrange(0, len(change_set)): if j >= i and j < i + div_size: delta_change.append(change_set[j]) delta_type.append(type_set[j]) delta_switch.append(switch_set[j]) else: delta_inv_change.append(change_set[j]) delta_inv_type.append(type_set[j]) delta_inv_switch.append(switch_set[j]) delta_change_set.append(delta_change) delta_type_set.append(delta_type) delta_switch_set.append(delta_switch) delta_inv_change_set.append(delta_inv_change) delta_inv_type_set.append(delta_inv_type) delta_inv_switch_set.append(delta_inv_switch) # # iterate through all delta and inverse delta set # record delta set that passes # pass_inx = -1 inv_is_better = False min_score = -1 for i in xrange(0, len(delta_change_set)): delta_change = delta_change_set[i] delta_type = delta_type_set[i] delta_switch = delta_switch_set[i] if len(delta_change) > 0: # always reset to lowest precision to_2nd_highest_precision(change_set, type_set, switch_set) # apply change for variables in delta to_highest_precision(delta_change, delta_type, switch_set) # record i if config passes if run_config( search_config, original_config, bitcode ) == 1 and utilities.get_dynamic_score() < original_score: score = utilities.get_dynamic_score() if score < min_score or min_score == -1: pass_inx = i inv_is_better = False min_score = score delta_inv_change = delta_inv_change_set[i] delta_inv_type = delta_inv_type_set[i] delta_inv_switch = delta_inv_switch_set[i] if len(delta_inv_change) > 0 and div > 2: # always reset to lowest precision to_2nd_highest_precision(change_set, type_set, switch_set) # apply change for variables in delta inverse to_highest_precision(delta_inv_change, delta_inv_type, delta_inv_switch) # record i if config passes if run_config( search_config, original_config, bitcode ) == 1 and utilities.get_dynamic_score() < original_score: score = utilities.get_dynamic_score() if score < min_score or min_score == -1: pass_inx = i inv_is_better = True min_score = score # # recursively search in pass delta or pass delta inverse # right now keep searching for the first pass delta or # pass delta inverse; later on we will integrate cost # model here # if pass_inx != -1: pass_change_set = delta_inv_change_set[ pass_inx] if inv_is_better else delta_change_set[pass_inx] pass_type_set = delta_inv_type_set[ pass_inx] if inv_is_better else delta_type_set[pass_inx] pass_switch_set = delta_inv_switch_set[ pass_inx] if inv_is_better else delta_switch_set[pass_inx] # log the configuration if it is faster than original_score # to_2nd_highest_precision(change_set, type_set) # to_highest_precision(pass_change_set, pass_type_set) # run_config(search_config, original_config, bitcode) # modified_score = utilities.get_dynamic_score() # if modified_score <= original_score: # utilities.log_fast_config("fast_configs.cov", search_counter-1, modified_score) if len(pass_change_set) > 1: # always reset to lowest precision to_2nd_highest_precision(change_set, type_set, switch_set) dd_search_config(pass_change_set, pass_type_set, pass_switch_set, search_config, original_config, bitcode, 2, original_score) else: to_2nd_highest_precision(change_set, type_set, switch_set) to_highest_precision(pass_change_set, pass_type_set, pass_switch_set) return # # stop searching when division greater than change set size # if div >= len(change_set): to_highest_precision(change_set, type_set, switch_set) # log the configuration if it is faster than original_score # run_config(search_config, original_config, bitcode) # modified_score = utilities.get_dynamic_score() # if modified_score <= original_score: # utilities.log_fast_config("fast_configs.cov", search_counter-1, modified_score) return else: dd_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, 2 * div, original_score) return
def dd_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, div, original_score): # # partition change_set into deltas and delta inverses # delta_change_set = [] delta_type_set = [] delta_switch_set = [] delta_inv_change_set = [] delta_inv_type_set = [] delta_inv_switch_set = [] div_size = int(math.ceil(float(len(change_set))/float(div))) for i in xrange(0, len(change_set), div_size): delta_change = [] delta_type = [] delta_switch = [] delta_inv_change = [] delta_inv_type = [] delta_inv_switch = [] for j in xrange(0, len(change_set)): if j >= i and j < i+div_size: delta_change.append(change_set[j]) delta_type.append(type_set[j]) delta_switch.append(switch_set[j]) else: delta_inv_change.append(change_set[j]) delta_inv_type.append(type_set[j]) delta_inv_switch.append(switch_set[j]) delta_change_set.append(delta_change) delta_type_set.append(delta_type) delta_switch_set.append(delta_switch) delta_inv_change_set.append(delta_inv_change) delta_inv_type_set.append(delta_inv_type) delta_inv_switch_set.append(delta_inv_switch) # # iterate through all delta and inverse delta set # record delta set that passes # pass_inx = -1 inv_is_better = False min_score = -1 for i in xrange(0, len(delta_change_set)): delta_change = delta_change_set[i] delta_type = delta_type_set[i] delta_switch = delta_switch_set[i] if len(delta_change) > 0: # always reset to lowest precision to_2nd_highest_precision(change_set, type_set, switch_set) # apply change for variables in delta to_highest_precision(delta_change, delta_type, switch_set) # record i if config passes if run_config(search_config, original_config, bitcode) == 1 and utilities.get_dynamic_score() < original_score: score = utilities.get_dynamic_score() if score < min_score or min_score == -1: pass_inx = i inv_is_better = False min_score = score delta_inv_change = delta_inv_change_set[i] delta_inv_type = delta_inv_type_set[i] delta_inv_switch = delta_inv_switch_set[i] if len(delta_inv_change) > 0 and div > 2: # always reset to lowest precision to_2nd_highest_precision(change_set, type_set, switch_set) # apply change for variables in delta inverse to_highest_precision(delta_inv_change, delta_inv_type, delta_inv_switch) # record i if config passes if run_config(search_config, original_config, bitcode) == 1 and utilities.get_dynamic_score() < original_score: score = utilities.get_dynamic_score() if score < min_score or min_score == -1: pass_inx = i inv_is_better = True min_score = score # # recursively search in pass delta or pass delta inverse # right now keep searching for the first pass delta or # pass delta inverse; later on we will integrate cost # model here # if pass_inx != -1: pass_change_set = delta_inv_change_set[pass_inx] if inv_is_better else delta_change_set[pass_inx] pass_type_set = delta_inv_type_set[pass_inx] if inv_is_better else delta_type_set[pass_inx] pass_switch_set = delta_inv_switch_set[pass_inx] if inv_is_better else delta_switch_set[pass_inx] # log the configuration if it is faster than original_score # to_2nd_highest_precision(change_set, type_set) # to_highest_precision(pass_change_set, pass_type_set) # run_config(search_config, original_config, bitcode) # modified_score = utilities.get_dynamic_score() # if modified_score <= original_score: # utilities.log_fast_config("fast_configs.cov", search_counter-1, modified_score) if len(pass_change_set) > 1: # always reset to lowest precision to_2nd_highest_precision(change_set, type_set, switch_set) dd_search_config(pass_change_set, pass_type_set, pass_switch_set, search_config, original_config, bitcode, 2, original_score) else: to_2nd_highest_precision(change_set, type_set, switch_set) to_highest_precision(pass_change_set, pass_type_set, pass_switch_set) return # # stop searching when division greater than change set size # if div >= len(change_set): to_highest_precision(change_set, type_set, switch_set) # log the configuration if it is faster than original_score # run_config(search_config, original_config, bitcode) # modified_score = utilities.get_dynamic_score() # if modified_score <= original_score: # utilities.log_fast_config("fast_configs.cov", search_counter-1, modified_score) return else: dd_search_config(change_set, type_set, switch_set, search_config, original_config, bitcode, 2*div, original_score) return
def search_config(change_set, type_set, search_config, original_config, bitcode, original_score): global search_counter # search from bottom up utilities.to_2nd_highest_precision(change_set, type_set) if utilities.run_config(search_config, original_config, bitcode, search_counter) != 1 or utilities.get_dynamic_score(search_counter) > original_score: search_counter = search_counter + 1 dd_search_config(change_set, type_set, search_config, original_config, bitcode, original_score, 2) else: search_counter = search_counter + 1 # remove types that cannot be changed for i in xrange(0, len(change_set)): if len(type_set[i]) > 0 and change_set[i]["type"] == type_set[i][-1]: del(type_set[i][:]) # remove highest precision from each type vector for type_vector in type_set: if len(type_vector) > 0: type_vector.pop()