diff --git a/cpp/src/branch_and_bound/branch_and_bound.cpp b/cpp/src/branch_and_bound/branch_and_bound.cpp index 774202c054..8943567619 100644 --- a/cpp/src/branch_and_bound/branch_and_bound.cpp +++ b/cpp/src/branch_and_bound/branch_and_bound.cpp @@ -3721,6 +3721,12 @@ mip_status_t branch_and_bound_t::solve(mip_solution_t& solut omp_get_num_threads() >= CUOPT_MIP_CLIQUE_CUTS_REQUIRED_THREAD_COUNT && !settings_.deterministic) { signal_extend_cliques_.store(false, std::memory_order_release); + mip::clique_config_t clique_config; + clique_table_ = + std::make_shared>(2 * original_problem_.num_cols, + clique_config.min_clique_size, + clique_config.max_clique_size_for_extension); + auto* initial_clique_table = clique_table_.get(); typename mip_solver_settings_t::tolerances_t tolerances_for_clique{}; tolerances_for_clique.presolve_absolute_tolerance = settings_.primal_tol; tolerances_for_clique.absolute_tolerance = settings_.primal_tol; @@ -3730,12 +3736,12 @@ mip_status_t branch_and_bound_t::solve(mip_solution_t& solut tolerances_for_clique.relative_mip_gap = settings_.relative_mip_gap_tol; #pragma omp task priority(CUOPT_DEFAULT_TASK_PRIORITY) depend(out : *clique_signal) \ - firstprivate(tolerances_for_clique) + firstprivate(tolerances_for_clique, initial_clique_table) { user_problem_t problem_copy = original_problem_; timer_t timer(std::numeric_limits::infinity()); mip::find_initial_cliques( - problem_copy, tolerances_for_clique, clique_table_, timer, clique_signal); + problem_copy, tolerances_for_clique, *initial_clique_table, timer, clique_signal); } } diff --git a/cpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cu b/cpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cu index a8e6997572..850637c2e6 100644 --- a/cpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cu +++ b/cpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cu @@ -670,7 +670,7 @@ void print_clique_table(const clique_table_t& clique_table) template void find_initial_cliques(user_problem_t& problem, typename mip_solver_settings_t::tolerances_t tolerances, - std::shared_ptr>& clique_table_out, + clique_table_t& clique_table, cuopt::timer_t& timer, omp_atomic_t* signal_extend) { @@ -701,48 +701,40 @@ void find_initial_cliques(user_problem_t& problem, t_sort = stage_timer.elapsed_time(); #endif clique_config_t clique_config; - auto clique_table = - std::make_shared>(2 * problem.num_cols, - clique_config.min_clique_size, - clique_config.max_clique_size_for_extension); - clique_table->tolerances = tolerances; + clique_table.tolerances = tolerances; double time_limit_for_additional_cliques = timer.remaining_time() / 2; cuopt::timer_t additional_cliques_timer(time_limit_for_additional_cliques); double find_work_estimate = 0.0; // Always build base cliques in full; signal_extend only gates the extension phase. for (const auto& knapsack_constraint : knapsack_constraints) { if (timer.check_time_limit()) { break; } - find_cliques_from_constraint(knapsack_constraint, *clique_table, additional_cliques_timer); + find_cliques_from_constraint(knapsack_constraint, clique_table, additional_cliques_timer); find_work_estimate += knapsack_constraint.entries.size(); } #ifdef DEBUG_CLIQUE_TABLE t_find = stage_timer.elapsed_time(); #endif CUOPT_LOG_DEBUG("Number of cliques: %d, additional cliques: %d, find_work=%.0f", - clique_table->first.size(), - clique_table->addtl_cliques.size(), + clique_table.first.size(), + clique_table.addtl_cliques.size(), find_work_estimate); - remove_small_cliques(*clique_table, timer); + remove_small_cliques(clique_table, timer); #ifdef DEBUG_CLIQUE_TABLE t_small = stage_timer.elapsed_time(); #endif - fill_var_clique_maps(*clique_table); + fill_var_clique_maps(clique_table); #ifdef DEBUG_CLIQUE_TABLE t_maps = stage_timer.elapsed_time(); #endif - // Publish the base table so cut generation can start using it; the extension - // phase below keeps mutating *clique_table, so the consumer must signal this - // task to stop and join it (taskwait) before reading the table. - clique_table_out = clique_table; double extend_work = 0.0; i_t n_extended_cliques = extend_cliques(knapsack_constraints, - *clique_table, + clique_table, timer, &extend_work, clique_config.min_extend_work, clique_config.max_extend_work, signal_extend); - if (n_extended_cliques > 0) { fill_var_clique_maps(*clique_table); } + if (n_extended_cliques > 0) { fill_var_clique_maps(clique_table); } #ifdef DEBUG_CLIQUE_TABLE t_extend = stage_timer.elapsed_time(); CUOPT_LOG_DEBUG( @@ -765,7 +757,7 @@ void find_initial_cliques(user_problem_t& problem, template void find_initial_cliques( \ user_problem_t & problem, \ typename mip_solver_settings_t::tolerances_t tolerances, \ - std::shared_ptr> & clique_table_out, \ + clique_table_t & clique_table, \ cuopt::timer_t & timer, \ omp_atomic_t * signal_extend); \ template void build_clique_table( \ diff --git a/cpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cuh b/cpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cuh index fe6db31c26..f1c1082aaf 100644 --- a/cpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cuh +++ b/cpp/src/mip_heuristics/presolve/conflict_graph/clique_table.cuh @@ -201,16 +201,14 @@ struct clique_table_t { typename mip_solver_settings_t::tolerances_t tolerances; }; -// Builds the conflict-graph clique table for `problem`. The base cliques are -// published to `clique_table_out` before the (optional, signal-gated) extension -// phase begins, so cut generation can pick up the table while extension keeps -// running concurrently. Consumers MUST set `*signal_extend` and join the -// producing task before reading the table (see prepare_fractional_sub_conflict_graph), since -// the extension phase keeps mutating the same object after it is published. +// Builds the conflict-graph clique table for `problem`. Consumers MUST set +// `*signal_extend` and join the producing task before reading the table (see +// prepare_fractional_sub_conflict_graph), since the extension phase keeps +// mutating the table after its base cliques are built. template void find_initial_cliques(simplex::user_problem_t& problem, typename mip_solver_settings_t::tolerances_t tolerances, - std::shared_ptr>& clique_table_out, + clique_table_t& clique_table, cuopt::timer_t& timer, omp_atomic_t* signal_extend = nullptr);