Skip to content

A New Simulated Annealing Schedule #1205

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jul 27, 2020
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
38 changes: 38 additions & 0 deletions doc/src/vpr/command_line_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,44 @@ If any of init_t, exit_t or alpha_t is specified, the user schedule, with a fixe

**Default:** ``0.0``

.. _dusty_sa_options:
Setting any of the following options selects `Dusty's annealing schedule <dusty_sa.rst>`_.

.. option:: --alpha_min <float>

The minimum (starting) update factor (alpha) used.
Ranges between 0 and alpha_max.

**Default:** ``0.2``

.. option:: --alpha_max <float>

The maximum (stopping) update factor (alpha) used after which simulated annealing will complete.
Ranges between alpha_min and 1.

**Default:** ``0.9``

.. option:: --alpha_decay <float>

The rate at which alpha will approach 1: alpha(n) = 1 - (1 - alpha(n-1)) * alpha_decay
Ranges between 0 and 1.

**Default:** ``0.7``

.. option:: --anneal_success_min <float>

The minimum success ratio after which the temperature will reset to maintain the target success ratio.
Ranges between 0 and anneal_success_target.

**Default:** ``0.1``

.. option:: --anneal_success_target <float>

The temperature after each reset is selected to keep this target success ratio.
Ranges between anneal_success_target and 1.

**Default:** ``0.25``

.. _timing_driven_placer_options:

Timing-Driven Placer Options
Expand Down
22 changes: 22 additions & 0 deletions doc/src/vpr/dusty_sa.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Dusty's Simulated Annealing Schedule
====================================

This simulated annealing schedule is designed to quickly characterize the search space and maintain a target success ratio (accepted moves.)

It starts at the minimum alpha (``--alpha_min``) to allow it to quickly find the target.

For each alpha, the temperature decays by a factor of alpha after each outer loop iteration.

The temperature before which the success ratio drops below the target (``--anneal_success_target``) is recorded; after hitting the minimum success ratio (``--anneal_success_min``), the temperature resets to a little before recorded temperature, and alpha parameter itself decays according to ``--alpha_decay``.

The effect of this is many fast, but slowing sweeps in temperature, focused where they can make the most effective progress. Unlike fixed and adaptive schedules that monotonically decrease temperature, this allows the global properties of the search space to affect the schedule.

In addition, move_lim (which controls the number of iterations in the inner loop) is scaled with the target success ratio over the current success ratio, which reduces the time to reach the target ratio.

The schedule terminates when the maximum alpha (``--alpha_max``) is reached. Termination is ensured by the narrowing range between the recorded upper temperature and the minimum success ratio, which will eventually cause alpha to reach its maximum.

This algorithm was inspired by Lester Ingber's adaptive simulated annealing algorithm [ASA93]_.

See ``update_state()`` in ``place.cpp`` for the algorithm details.

.. [ASA93] Ingber, Lester. "Adaptive simulated annealing (ASA)." Global optimization C-code, Caltech Alumni Association, Pasadena, CA (1993).
25 changes: 25 additions & 0 deletions vpr/src/base/SetupVPR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,31 @@ static void SetupAnnealSched(const t_options& Options,
VPR_FATAL_ERROR(VPR_ERROR_OTHER, "inner_num must be greater than 0.\n");
}

AnnealSched->alpha_min = Options.PlaceAlphaMin;
if (AnnealSched->alpha_min >= 1 || AnnealSched->alpha_min <= 0) {
VPR_FATAL_ERROR(VPR_ERROR_OTHER, "alpha_min must be between 0 and 1 exclusive.\n");
}

AnnealSched->alpha_max = Options.PlaceAlphaMax;
if (AnnealSched->alpha_max >= 1 || AnnealSched->alpha_max <= AnnealSched->alpha_min) {
VPR_FATAL_ERROR(VPR_ERROR_OTHER, "alpha_max must be between alpha_min and 1 exclusive.\n");
}

AnnealSched->alpha_decay = Options.PlaceAlphaDecay;
if (AnnealSched->alpha_decay >= 1 || AnnealSched->alpha_decay <= 0) {
VPR_FATAL_ERROR(VPR_ERROR_OTHER, "alpha_decay must be between 0 and 1 exclusive.\n");
}

AnnealSched->success_min = Options.PlaceSuccessMin;
if (AnnealSched->success_min >= 1 || AnnealSched->success_min <= 0) {
VPR_FATAL_ERROR(VPR_ERROR_OTHER, "success_min must be between 0 and 1 exclusive.\n");
}

AnnealSched->success_target = Options.PlaceSuccessTarget;
if (AnnealSched->success_target >= 1 || AnnealSched->success_target <= 0) {
VPR_FATAL_ERROR(VPR_ERROR_OTHER, "success_target must be between 0 and 1 exclusive.\n");
}

AnnealSched->type = Options.anneal_sched_type;
}

Expand Down
9 changes: 9 additions & 0 deletions vpr/src/base/ShowSetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ static void ShowAnnealSched(const t_annealing_sched& AnnealSched) {
case USER_SCHED:
VTR_LOG("USER_SCHED\n");
break;
case DUSTY_SCHED:
VTR_LOG("DUSTY_SCHED\n");
break;
default:
VTR_LOG_ERROR("Unknown annealing schedule\n");
}
Expand All @@ -165,6 +168,12 @@ static void ShowAnnealSched(const t_annealing_sched& AnnealSched) {
VTR_LOG("AnnealSched.init_t: %f\n", AnnealSched.init_t);
VTR_LOG("AnnealSched.alpha_t: %f\n", AnnealSched.alpha_t);
VTR_LOG("AnnealSched.exit_t: %f\n", AnnealSched.exit_t);
} else if (DUSTY_SCHED == AnnealSched.type) {
VTR_LOG("AnnealSched.alpha_min: %f\n", AnnealSched.alpha_min);
VTR_LOG("AnnealSched.alpha_max: %f\n", AnnealSched.alpha_max);
VTR_LOG("AnnealSched.alpha_decay: %f\n", AnnealSched.alpha_decay);
VTR_LOG("AnnealSched.success_min: %f\n", AnnealSched.success_min);
VTR_LOG("AnnealSched.success_target: %f\n", AnnealSched.success_target);
}
}

Expand Down
46 changes: 41 additions & 5 deletions vpr/src/base/read_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1566,6 +1566,36 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
.default_value("0.8")
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument(args.PlaceAlphaMin, "--alpha_min")
.help(
"For placement using Dusty's annealing schedule. Minimum (starting) value of alpha.")
.default_value("0.2")
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument(args.PlaceAlphaMax, "--alpha_max")
.help(
"For placement using Dusty's annealing schedule. Maximum (stopping) value of alpha.")
.default_value("0.9")
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument(args.PlaceAlphaDecay, "--alpha_decay")
.help(
"For placement using Dusty's annealing schedule. The value that alpha is scaled by after reset.")
.default_value("0.7")
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument(args.PlaceSuccessMin, "--anneal_success_min")
.help(
"For placement using Dusty's annealing schedule. Minimum success ratio when annealing before resetting the temperature to maintain the target success ratio.")
.default_value("0.1")
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument(args.PlaceSuccessTarget, "--anneal_success_target")
.help(
"For placement using Dusty's annealing schedule. Target success ratio when annealing.")
.default_value("0.25")
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument(args.pad_loc_file, "--fix_pins")
.help(
"Fixes I/O pad locations during placement. Valid options:\n"
Expand Down Expand Up @@ -2192,13 +2222,19 @@ void set_conditional_defaults(t_options& args) {
args.quench_recompute_divider.set(args.inner_loop_recompute_divider, Provenance::INFERRED);
}

//Are we using the automatic, or user-specified annealing schedule?
if (args.PlaceInitT.provenance() == Provenance::SPECIFIED
|| args.PlaceExitT.provenance() == Provenance::SPECIFIED
|| args.PlaceAlphaT.provenance() == Provenance::SPECIFIED) {
//Which schedule?
if (args.PlaceAlphaMin.provenance() == Provenance::SPECIFIED // Any of these flags select Dusty's schedule
|| args.PlaceAlphaMax.provenance() == Provenance::SPECIFIED
|| args.PlaceAlphaDecay.provenance() == Provenance::SPECIFIED
|| args.PlaceSuccessMin.provenance() == Provenance::SPECIFIED
|| args.PlaceSuccessTarget.provenance() == Provenance::SPECIFIED) {
args.anneal_sched_type.set(DUSTY_SCHED, Provenance::INFERRED);
} else if (args.PlaceInitT.provenance() == Provenance::SPECIFIED // Any of these flags select a manual schedule
|| args.PlaceExitT.provenance() == Provenance::SPECIFIED
|| args.PlaceAlphaT.provenance() == Provenance::SPECIFIED) {
args.anneal_sched_type.set(USER_SCHED, Provenance::INFERRED);
} else {
args.anneal_sched_type.set(AUTO_SCHED, Provenance::INFERRED);
args.anneal_sched_type.set(AUTO_SCHED, Provenance::INFERRED); // Otherwise use the automatic schedule
}

//Are the pad locations specified?
Expand Down
5 changes: 5 additions & 0 deletions vpr/src/base/read_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ struct t_options {
argparse::ArgValue<float> PlaceInitT;
argparse::ArgValue<float> PlaceExitT;
argparse::ArgValue<float> PlaceAlphaT;
argparse::ArgValue<float> PlaceAlphaMin;
argparse::ArgValue<float> PlaceAlphaMax;
argparse::ArgValue<float> PlaceAlphaDecay;
argparse::ArgValue<float> PlaceSuccessMin;
argparse::ArgValue<float> PlaceSuccessTarget;
argparse::ArgValue<sched_type> anneal_sched_type;
argparse::ArgValue<e_place_algorithm> PlaceAlgorithm;
argparse::ArgValue<e_pad_loc_type> pad_loc_type;
Expand Down
13 changes: 13 additions & 0 deletions vpr/src/base/vpr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ enum class e_timing_update_type {
/* Timing data structures end */
enum sched_type {
AUTO_SCHED,
DUSTY_SCHED,
USER_SCHED
};
/* Annealing schedule */
Expand Down Expand Up @@ -806,6 +807,18 @@ struct t_annealing_sched {
float init_t;
float alpha_t;
float exit_t;

/* Parameters for DUSTY_SCHED *
* The alpha ranges from alpha_min to alpha_max, decaying each *
* iteration by `alpha_decay`. *
* `restart_filter` is the low-pass coefficient (EWMA) for updating *
* the new starting temperature for each alpha. *
* Give up after `wait` alphas. */
float alpha_min;
float alpha_max;
float alpha_decay;
float success_min;
float success_target;
};

/* Various options for the placer. *
Expand Down
Loading