bool Clustering::perform_single_move(const SingleMove& move) { if (move.c1 == move.c2) return false; // update stats Stats delta1 = node_stats[move.i]; delta1.self += 2.0 * move.weight_i_c1; Stats delta2 = node_stats[move.i]; delta2.self += 2.0 * move.weight_i_c2; clus_stats[move.c1] -= delta1; clus_stats[move.c2] += delta2; clus_stats.total -= delta1; clus_stats.total += delta2; // update loss sum_local_loss = move.sum_local_after; loss = move.loss_after; // update cluster assignment if(node_clus[move.i] != move.c1) throw std::logic_error("node_clus[move.i] != move.c2"); node_clus[move.i] = move.c2; // update update_clus_size(move.c1, -1); update_clus_size(move.c2, +1); // recheck invariants if (params.check_invariants) verify_invariants(); if (params.verbosity >= 6) { params.debug_out << " moved " << move.i << " from " << move.c1; if (!node_partition.empty()) params.debug_out << " in " << node_partition[move.c1]; params.debug_out << " to " << move.c2; if (!node_partition.empty()) params.debug_out << " in " << node_partition[move.c2]; params.debug_out << " loss " << setprecision(12) << move.loss_after << " in " << num_clusters() << " clusters" << endl; } return true; }
// // wrapper_type: 0 for kernel functions, 1 for entry point epwrapper_ functions // Returns the current driver call stack after entering the driver // // gen_enter_driver is called after the associated kernel function executes // gen_enter_driver is called before the associated driver function executes. // // Interesting functions: 0 if not interesting, 1 if interesting. // Note that both driver functions and kernel functions can be interesting // We can distinguish that based on wrapper_type // int gen_enter_driver (const char *fn, int line, enum symdrive_WRAPPER_TYPE wrapper_type, int retval_valid, unsigned long retval, const char *interesting_fn, void (*gen_register_all_param)(void)) { // Moved from generated code. // Call interrupt handlers if we're entering the driver from // a call into the kernel. static char first_time_in_driver = 1; if (first_time_in_driver == 1) { gen_register_all_param(); first_time_in_driver = 0; } if (wrapper_type == STUBWRAPPER) { // Pause/Resume accumulation if needed //s2e_disable_trackperf(__LINE__, SYMDRIVE_PAUSE_IRQ); call_interrupt_handlers(fn, line); execute_completions(fn, line); //s2e_enable_trackperf(__LINE__, SYMDRIVE_CONTINUE_IRQ); } acquire_global_lock(); // Entering driver: if (driver_call_stack == 0) { //if (cleanup_path == 0 && strcmp (fn, "cleanup_module") == 0) { // TODO HACK // cleanup_path = 1; //} //if (cleanup_path == 0) { // s2e_disable_all_apic_interrupts(); //} verify_retval(fn, line, wrapper_type, ENTRANCE, retval_valid, retval); // Reset success path on first entry into driver s2e_success_path (line, fn, 0); } verify_invariants(fn, line, 1, wrapper_type); // Track performance / basic blocks //if (strcmp (fn, g_sym_trackperf_fn) == 0) { // // start accumulation // s2e_enable_trackperf(__LINE__, SYMDRIVE_START_AUTO); //} // Entering driver/kernel function: s2e_enter_function(line, fn, wrapper_type); handle_interesting_function(fn, line, wrapper_type, retval_valid, retval, interesting_fn, ENTRANCE); handle_max_coverage(fn, line, retval_valid, retval, wrapper_type, ENTRANCE); release_global_lock(); // Not used as far as I know: return driver_call_stack; }
// go over nodes in a random order, and try to move to neighboring cluster bool Clustering::optimize_single_moves_pass() { if (params.check_invariants) verify_invariants(); bool changes = false; std::random_shuffle(node_perm.begin(), node_perm.end()); for (vector<int>::const_iterator i_it = node_perm.begin() ; i_it != node_perm.end() ; ++i_it) { //OCTAVE_QUIT; if (optimize_single_move_for_node(*i_it)) changes = true; } if (changes) { // it is important to recalculate the loss, otherwise we accumulate numerical errors recalc_internal_data(); } return changes; }
// // This function is called in the postfn_ generated function // int gen_exit_driver (const char *fn, int line, enum symdrive_WRAPPER_TYPE wrapper_type, int retval_valid, unsigned long retval, const char *interesting_fn, void (*gen_register_all_param)(void)) { //static int alternate_sym = 0; acquire_global_lock(); // Exiting driver/kernel function: s2e_exit_function(line, fn, wrapper_type); // Track performance / basic blocks // Do this before calling verify_retval // Do this before max coverage. //if (strcmp (fn, g_sym_trackperf_fn) == 0) { // s2e_disable_trackperf(__LINE__, SYMDRIVE_STOP_AUTO); //} // Starting the full-coverage mode handle_max_coverage(fn, line, retval_valid, retval, wrapper_type, EXIT); handle_interesting_function(fn, line, wrapper_type, retval_valid, retval, interesting_fn, EXIT); // If the retval is valid and not symbolic then prioritize or deprioritize. // If it is symbolic, then do nothing on the assumption that it's a hardware // value -- we should not be prioritizing hardware values. if (retval_valid) { if (s2e_is_symbolic_symdrive(line, retval) == 0) { s2e_prioritize(line); if (g_symdrive_annotations == 0) { // Proceed normally } else { // Convert retval to success uprintk ("Prioritization: allowing our path per annotation\n", fn, line, s2e_get_example_uint (retval)); g_symdrive_annotations = 0; retval = 0; } if (!IS_ERR_VALUE(retval)) { s2e_success_path(line, fn, 1); uprintk ("Prioritizing line %d, example val %lu\n", line, s2e_get_example_uint(retval)); } else { uprintk ("Deprioritizing line %d, example val %lu\n", line, s2e_get_example_uint(retval)); s2e_success_path(line, fn, -1); s2e_deprioritize(line); } } else { uprintk ("Line %d: symbolic retval, example %lu.\n", line, s2e_get_example_uint(retval)); } } // Exiting driver: verify_invariants(fn, line, -1, wrapper_type); if (driver_call_stack == 0) { verify_retval(fn, line, wrapper_type, EXIT, retval_valid, retval); reset_new_objects (fn); //if (cleanup_path == 0) { // s2e_enable_all_apic_interrupts(); //} } release_global_lock(); // Moved from generated code. // Call interrupt handlers if we're returning to the kernel. if (wrapper_type == PREPOSTFN && driver_call_stack == 0) { //s2e_disable_trackperf(__LINE__, SYMDRIVE_PAUSE_IRQ); // Pause accumulation call_interrupt_handlers(fn, line); execute_completions(fn, line); //s2e_enable_trackperf(__LINE__, SYMDRIVE_CONTINUE_IRQ); // Resume accumulation } // Not used as far as I know: return driver_call_stack; }