Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 32 additions & 27 deletions cpp/src/branch_and_bound/branch_and_bound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1754,7 +1754,7 @@ void branch_and_bound_t<i_t, f_t>::run_scheduler()
active_workers_per_strategy_[strategy]++;
launched_any_task = true;

#pragma omp task affinity(worker)
#pragma omp task affinity(worker) default(none) firstprivate(worker)
plunge_with(worker);

} else {
Expand All @@ -1775,7 +1775,7 @@ void branch_and_bound_t<i_t, f_t>::run_scheduler()
active_workers_per_strategy_[strategy]++;
launched_any_task = true;

#pragma omp task affinity(worker)
#pragma omp task affinity(worker) default(none) firstprivate(worker)
dive_with(worker);
}
}
Expand All @@ -1800,6 +1800,8 @@ void branch_and_bound_t<i_t, f_t>::run_scheduler()
template <typename i_t, typename f_t>
void branch_and_bound_t<i_t, f_t>::single_threaded_solve()
{
raft::common::nvtx::range scope("BB::single_threaded_solve");

branch_and_bound_worker_t<i_t, f_t> worker(0, original_lp_, Arow_, var_types_, settings_);

f_t lower_bound = get_lower_bound();
Expand Down Expand Up @@ -1875,19 +1877,23 @@ lp_status_t branch_and_bound_t<i_t, f_t>::solve_root_relaxation(

// Root node path
lp_status_t root_status;
std::future<lp_status_t> root_status_future;
root_status_future = std::async(std::launch::async,
&solve_linear_program_with_advanced_basis<i_t, f_t>,
std::ref(original_lp_),
exploration_stats_.start_time,
std::ref(lp_settings),
std::ref(root_relax_soln),
std::ref(basis_update),
std::ref(basic_list),
std::ref(nonbasic_list),
std::ref(root_vstatus),
std::ref(edge_norms),
nullptr);

// Note that we need to explicitly declared `root_status` as a shared variable here since
// it is local to the thread that are executing the enclosing task.
#pragma omp task default(shared) depend(out : root_status)
{
root_status = solve_linear_program_with_advanced_basis(original_lp_,
exploration_stats_.start_time,
lp_settings,
root_relax_soln_,
basis_update,
basic_list,
nonbasic_list,
root_vstatus_,
edge_norms_,
nullptr);
}

// Wait for the root relaxation solution to be sent by the diversity manager or dual simplex
// to finish
while (!root_crossover_solution_set_.load(std::memory_order_acquire) &&
Expand Down Expand Up @@ -1930,7 +1936,7 @@ lp_status_t branch_and_bound_t<i_t, f_t>::solve_root_relaxation(
// Check if crossover was stopped by dual simplex
if (crossover_status == crossover_status_t::OPTIMAL) {
set_root_concurrent_halt(1); // Stop dual simplex
root_status = root_status_future.get(); // Wait for dual simplex to finish
#pragma omp taskwait depend(in : root_status) // Wait for dual simplex to finish
set_root_concurrent_halt(0); // Clear the concurrent halt flag
// Override the root relaxation solution with the crossover solution
root_relax_soln = root_crossover_soln_;
Expand Down Expand Up @@ -1981,14 +1987,14 @@ lp_status_t branch_and_bound_t<i_t, f_t>::solve_root_relaxation(
solver_name = method_to_string(root_relax_solved_by);

} else {
root_status = root_status_future.get();
#pragma omp taskwait depend(in : root_status) // Wait for the dual simplex to finish
user_objective = root_relax_soln_.user_objective;
iter = root_relax_soln_.iterations;
root_relax_solved_by = DualSimplex;
solver_name = "Dual Simplex";
}
} else {
root_status = root_status_future.get();
#pragma omp taskwait depend(in : root_status) // Wait for the dual simplex to finish
user_objective = root_relax_soln_.user_objective;
iter = root_relax_soln_.iterations;
root_relax_solved_by = DualSimplex;
Expand Down Expand Up @@ -2614,17 +2620,16 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut
"| Gap | Time |\n");
}

if (settings_.deterministic) {
run_deterministic_coordinator(Arow_);
} else if (settings_.num_threads > 1) {
#pragma omp parallel num_threads(settings_.num_threads)
{
#pragma omp master
#pragma omp taskgroup
{
if (settings_.deterministic) {
run_deterministic_coordinator(Arow_);
} else if (settings_.num_threads > 1) {
run_scheduler();
} else {
single_threaded_solve();
}
} else {
single_threaded_solve();
}
} // Implicit barrier for all tasks created within the group (RINS, B&B workers)

is_running_ = false;

Expand Down
143 changes: 70 additions & 73 deletions cpp/src/branch_and_bound/pseudo_costs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,14 +756,15 @@ static void batch_pdlp_strong_branching_task(
ws_settings.inside_mip = true;
if (effective_batch_pdlp == 1) { ws_settings.concurrent_halt = &concurrent_halt; }

auto start_time = std::chrono::high_resolution_clock::now();
auto pdlp_start_time = std::chrono::high_resolution_clock::now();

auto ws_solution = solve_lp(&pc.pdlp_warm_cache.batch_pdlp_handle, mps_model, ws_settings);

if (verbose) {
auto end_time = std::chrono::high_resolution_clock::now();
auto pdlp_end_time = std::chrono::high_resolution_clock::now();
auto duration =
std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
std::chrono::duration_cast<std::chrono::milliseconds>(pdlp_end_time - pdlp_start_time)
.count();
settings.log.printf(
"Original problem solved in %d milliseconds"
" and iterations: %d\n",
Expand Down Expand Up @@ -999,7 +1000,7 @@ void strong_branching(const lp_problem_t<i_t, f_t>& original_lp,
basis_update_mpf_t<i_t, f_t>& basis_factors,
pseudo_costs_t<i_t, f_t>& pc)
{
constexpr bool verbose = false;
raft::common::nvtx::range scope("BB::strong_branching");

pc.resize(original_lp.num_cols);
pc.strong_branch_down.assign(fractional.size(), 0);
Expand Down Expand Up @@ -1052,75 +1053,74 @@ void strong_branching(const lp_problem_t<i_t, f_t>& original_lp,
basis_factors,
pc);
} else {
#pragma omp parallel num_threads(settings.num_threads)
{
#pragma omp single nowait
{
if (effective_batch_pdlp != 0) {
#pragma omp task
batch_pdlp_strong_branching_task(settings,
effective_batch_pdlp,
start_time,
concurrent_halt,
original_lp,
new_slacks,
root_solution.x,
fractional,
root_obj,
pc,
sb_view,
pdlp_obj_down,
pdlp_obj_up);
}
if (effective_batch_pdlp != 0) {
#pragma omp task default(shared)
batch_pdlp_strong_branching_task(settings,
effective_batch_pdlp,
start_time,
concurrent_halt,
original_lp,
new_slacks,
root_solution.x,
fractional,
root_obj,
pc,
sb_view,
pdlp_obj_down,
pdlp_obj_up);
}

if (effective_batch_pdlp != 2) {
i_t n = std::min<i_t>(4 * settings.num_threads, fractional.size());
if (effective_batch_pdlp != 2) {
i_t n = std::min<i_t>(4 * settings.num_threads, fractional.size());
// Here we are creating more tasks than the number of threads
// such that they can be scheduled dynamically to the threads.
#pragma omp taskloop num_tasks(n)
for (i_t k = 0; k < n; k++) {
i_t start = std::floor(k * fractional.size() / n);
i_t end = std::floor((k + 1) * fractional.size() / n);

constexpr bool verbose = false;
if (verbose) {
settings.log.printf("Thread id %d task id %d start %d end %d. size %d\n",
omp_get_thread_num(),
k,
start,
end,
end - start);
}

strong_branch_helper(start,
end,
start_time,
original_lp,
settings,
var_types,
fractional,
root_solution.x,
root_vstatus,
edge_norms,
root_obj,
upper_bound,
simplex_iteration_limit,
pc,
dual_simplex_obj_down,
dual_simplex_obj_up,
dual_simplex_status_down,
dual_simplex_status_up,
sb_view);
}
// DS done: signal PDLP to stop (time-limit or all work done) and wait
if (effective_batch_pdlp == 1) { concurrent_halt.store(1); }
#pragma omp taskloop num_tasks(n) default(shared)
for (i_t k = 0; k < n; k++) {
i_t start = std::floor(k * fractional.size() / n);
i_t end = std::floor((k + 1) * fractional.size() / n);

constexpr bool verbose = false;
if (verbose) {
settings.log.printf("Thread id %d task id %d start %d end %d. size %d\n",
omp_get_thread_num(),
k,
start,
end,
end - start);
}

strong_branch_helper(start,
end,
start_time,
original_lp,
settings,
var_types,
fractional,
root_solution.x,
root_vstatus,
edge_norms,
root_obj,
upper_bound,
simplex_iteration_limit,
pc,
dual_simplex_obj_down,
dual_simplex_obj_up,
dual_simplex_status_down,
dual_simplex_status_up,
sb_view);
}
// DS done: signal PDLP to stop (time-limit or all work done) and wait
if (effective_batch_pdlp == 1) { concurrent_halt.store(1); }
}

if (effective_batch_pdlp != 0) {
#pragma omp taskwait // Wait for the batch PDLP task to finish
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

settings.log.printf("Strong branching completed in %.2fs\n", toc(strong_branching_start_time));

constexpr bool verbose = false;
if (verbose) {
// Collect Dual Simplex statistics
i_t dual_simplex_optimal = 0, dual_simplex_infeasible = 0, dual_simplex_iter_limit = 0;
Expand Down Expand Up @@ -1283,6 +1283,8 @@ i_t pseudo_costs_t<i_t, f_t>::variable_selection(const std::vector<i_t>& fractio
const std::vector<f_t>& solution,
logger_t& log)
{
raft::common::nvtx::range scope("BB::pseudocost_branching");

i_t branch_var = fractional[0];
f_t max_score = -1;
i_t num_initialized_down;
Expand Down Expand Up @@ -1329,6 +1331,8 @@ i_t pseudo_costs_t<i_t, f_t>::reliable_variable_selection(
const std::vector<i_t>& new_slacks,
const lp_problem_t<i_t, f_t>& original_lp)
{
raft::common::nvtx::range scope("BB::reliability_branching");

constexpr f_t eps = 1e-6;
f_t start_time = bnb_stats.start_time;
i_t branch_var = fractional[0];
Expand Down Expand Up @@ -1563,7 +1567,7 @@ i_t pseudo_costs_t<i_t, f_t>::reliable_variable_selection(
log.printf("Time limit reached\n");
if (use_pdlp) {
concurrent_halt.store(1);
#pragma omp taskwait
#pragma omp taskwait // Wait for the batch PDLP task to finish
}
return branch_var;
}
Expand All @@ -1576,14 +1580,7 @@ i_t pseudo_costs_t<i_t, f_t>::reliable_variable_selection(
f_t dual_simplex_start_time = tic();

if (rb_mode != 2) {
#pragma omp taskloop if (num_tasks > 1) priority(task_priority) num_tasks(num_tasks) \
shared(score_mutex, \
sb_view, \
dual_simplex_obj_down, \
dual_simplex_obj_up, \
dual_simplex_status_down, \
dual_simplex_status_up, \
unreliable_list)
#pragma omp taskloop if (num_tasks > 1) priority(task_priority) num_tasks(num_tasks) default(shared)
for (i_t i = 0; i < num_candidates; ++i) {
auto [score, j] = unreliable_list[i];

Expand Down Expand Up @@ -1709,7 +1706,7 @@ i_t pseudo_costs_t<i_t, f_t>::reliable_variable_selection(
//}

if (use_pdlp) {
#pragma omp taskwait
#pragma omp taskwait // Wait for the batch PDLP task to finish

i_t pdlp_applied = 0;
i_t pdlp_optimal = 0;
Expand Down
3 changes: 0 additions & 3 deletions cpp/src/mip_heuristics/diversity/diversity_manager.cu
Original file line number Diff line number Diff line change
Expand Up @@ -603,18 +603,15 @@ solution_t<i_t, f_t> diversity_manager_t<i_t, f_t>::run_solver()

generate_solution(timer.remaining_time(), false);
if (timer.check_time_limit()) {
rins.stop_rins();
population.add_external_solutions_to_population();
return population.best_feasible();
}
if (check_b_b_preemption()) {
rins.stop_rins();
population.add_external_solutions_to_population();
return population.best_feasible();
}

run_fp_alone();
rins.stop_rins();
population.add_external_solutions_to_population();
return population.best_feasible();
};
Expand Down
Loading
Loading