Skip to content
Merged
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
11 changes: 5 additions & 6 deletions docs/src/parallel.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

## Generally

HiGHS currently has limited opportunities for exploiting parallel
HiGHS has increasing opportunities for exploiting parallel
computing. When using a CPU, these are currently restricted to the
dual simplex solver for LP, the factorisation-based interior point solver,
dual simplex solver for LP, the factorisation-based interior point solver (HiPO),
and the MIP solver. Details of these and future plans are set out below.
HiGHS has an implementation of a first order method (PDLP) for solving LPs
that can exploit the availability of a [GPU](@ref gpu).
Expand All @@ -24,10 +24,9 @@ concurrent Highs instances must use the same value of `threads`.

By default, the HiGHS dual simplex solver runs in serial. However, it
has a variant allowing concurrent processing. This variant is used
when the [parallel](@ref option-parallel) option is set "on", by
specifying `--parallel` when running the [executable](@ref executable)
via the command line, or by setting it via a library call in an
application.
when the [parallel](@ref option-parallel) option is set to "on" and
[simplex\_strategy](@ref option-simplex-strategy) is set to
`kSimplexStrategyDualTasks` (2) or `kSimplexStrategyDualMulti` (3).

The concurrency used will be the value of
[simplex\_max\_concurrency](@ref option-simplex-max-concurrency). If
Expand Down
77 changes: 44 additions & 33 deletions highs/presolve/HPresolve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7472,10 +7472,10 @@ HPresolve::Result HPresolve::removeDependentEquations(
factor.setTimeLimit(time_limit);
// Determine rank deficiency of the equations
if (!silent)
highsLogUser(options->log_options, HighsLogType::kInfo,
"Dependent equations search running with time "
"limit of %.2fs\n",
time_limit);
highsLogDev(options->log_options, HighsLogType::kInfo,
" Dependent equations search running with time "
"limit of %.2fs\n",
time_limit);
double time_taken = -this->timer->read();
HighsInt build_return = factor.build();
time_taken += this->timer->read();
Expand All @@ -7494,21 +7494,23 @@ HPresolve::Result HPresolve::removeDependentEquations(
static_cast<int>(num_variables), static_cast<int>(model->num_col_),
static_cast<int>(num_nz), static_cast<int>(num_removed_row),
static_cast<int>(num_removed_nz), time_taken);
highsLogUser(options->log_options, HighsLogType::kInfo,
"Dependent equations search terminated after %.3gs due to "
"expected time exceeding limit\n",
time_taken);
highsLogUser(
options->log_options, HighsLogType::kInfo,
" Dependent equations search terminated after %.3gs due to "
"expected time exceeding limit\n",
time_taken);
}
return returnOk();
} else {
double pct_off_timeout =
1e2 * std::fabs(time_taken - time_limit) / time_limit;
if (!silent && pct_off_timeout < 1.0)
highsLogUser(options->log_options, HighsLogType::kWarning,
"Dependent equations search finished within %.2f%% of limit "
"of %.2fs: "
"risk of non-deterministic behaviour if solve is repeated\n",
pct_off_timeout, time_limit);
highsLogUser(
options->log_options, HighsLogType::kWarning,
" Dependent equations search finished within %.2f%% of limit "
"of %.2fs: "
"risk of non-deterministic behaviour if solve is repeated\n",
pct_off_timeout, time_limit);
}
// build_return as rank_deficiency must be valid
assert(build_return >= 0);
Expand All @@ -7525,26 +7527,35 @@ HPresolve::Result HPresolve::removeDependentEquations(
}
}
if (!silent) {
highsLogUser(
options->log_options, HighsLogType::kInfo,
"Search of %d equation%s with %d / %d variable%s and %d nonzero%s "
"removed %d dependent equation%s and %d nonzero%s "
"in %.2fs with bounds in (%.2fs, %.2fs) and limit = %.2fs",
// clang-format off
static_cast<int>(num_equations), highsIntToPlural(num_equations).c_str(),
static_cast<int>(num_variables),
static_cast<int>(model->num_col_), highsIntToPlural(num_variables).c_str(),
static_cast<int>(num_nz), highsIntToPlural(num_nz).c_str(),
static_cast<int>(num_removed_row), highsIntToPlural(num_removed_row).c_str(),
static_cast<int>(num_removed_nz), highsIntToPlural(num_removed_nz).c_str(),
// clang-format on
time_taken, factor.min_time_bound_, factor.max_time_bound_, time_limit);
if (num_fictitious_rows_skipped)
highsLogDev(options->log_options, HighsLogType::kInfo,
", avoiding %d fictitious row%s",
static_cast<int>(num_fictitious_rows_skipped),
highsIntToPlural(num_fictitious_rows_skipped).c_str());
highsLogUser(options->log_options, HighsLogType::kInfo, "\n");
std::stringstream ss;
ss.str(std::string());
ss << highsFormatToString("Dependent equations search");
if (options->log_dev_level > 0)
ss << highsFormatToString(
" with %d / %d variable%s and %d nonzero%s",
static_cast<int>(num_variables), static_cast<int>(model->num_col_),
highsIntToPlural(num_variables).c_str(), static_cast<int>(num_nz),
highsIntToPlural(num_nz).c_str());
ss << highsFormatToString(" removed %d equation%s and %d nonzero%s",
static_cast<int>(num_removed_row),
highsIntToPlural(num_removed_row).c_str(),
static_cast<int>(num_removed_nz),
highsIntToPlural(num_removed_nz).c_str());
if (options->log_dev_level > 0) {
ss << highsFormatToString(" in %.2fs with bounds in (%.2f, %.2f)s",
time_taken, factor.min_time_bound_,
factor.max_time_bound_);
if (num_fictitious_rows_skipped)
ss << highsFormatToString(
", avoiding %d fictitious row%s",
static_cast<int>(num_fictitious_rows_skipped),
highsIntToPlural(num_fictitious_rows_skipped).c_str());
highsLogDev(options->log_options, HighsLogType::kInfo, "%s\n",
ss.str().c_str());
} else {
highsLogUser(options->log_options, HighsLogType::kInfo, "%s\n",
ss.str().c_str());
}
}
return returnOk();
}
Expand Down
21 changes: 21 additions & 0 deletions highs/simplex/HEkk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,27 @@ HighsStatus HEkk::solve(const bool force_phase2) {
simplexStrategyToString(kSimplexStrategyDualMulti).c_str(),
int(info_.num_concurrency));
} else {
std::stringstream ss;
ss.str(std::string());
assert(simplex_strategy == kSimplexStrategyChoose ||
simplex_strategy == kSimplexStrategyDual);
ss << highsFormatToString(
"Choosing to use %s%s",
options_->parallel == kHighsOnString ? "serial " : "",
simplexStrategyToString(kSimplexStrategyDual).c_str());
if (options_->parallel == kHighsOnString) {
ss << highsFormatToString(" despite setting parallel = on\n");
ss << highsFormatToString(
"To force parallel dual simplex, set simplex_strategy to "
"kSimplexStrategyDualTasks = %d or (preferably) "
"kSimplexStrategyDualMulti = %d\n",
kSimplexStrategyDualTasks, kSimplexStrategyDualMulti);
}
highsLogUser(options_->log_options, HighsLogType::kInfo, "%s\n",
ss.str().c_str());

printf("HEkk::solve simplex strategy = %d; parallel = %s\n",
int(simplex_strategy), options_->parallel.c_str());
highsLogUser(options_->log_options, HighsLogType::kInfo, "Using %s\n",
simplexStrategyToString(kSimplexStrategyDual).c_str());
}
Expand Down
Loading