Skip to content

Commit

Permalink
[FEATURE] Allow hints to generated from prior placements. (#86)
Browse files Browse the repository at this point in the history
* Add option in CMake to work across Gurobi versions.

* Communicate hints for the ChooseExpressions.

* Only allow hinting in the SolverModel if requested.

* Implement warm starts using prior placements.

* Update stubs for Python frontend.
  • Loading branch information
sukritkalra authored Jan 19, 2024
1 parent 87c3b03 commit c902a91
Show file tree
Hide file tree
Showing 9 changed files with 553 additions and 78 deletions.
14 changes: 12 additions & 2 deletions schedulers/tetrisched/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,18 @@ if (EXISTS "${GUROBI_DIR}")
LIST(APPEND SOLVER_BACKEND_LINK_DIRS
"${GUROBI_DIR}/lib/")
LIST(APPEND SOLVER_BACKEND_LINK_LIBRARIES
"gurobi_c++"
"gurobi100")
"gurobi_c++")
if (NOT DEFINED TETRISCHED_GUROBI_VER OR ${TETRISCHED_GUROBI_VER} EQUAL 10)
message("-- Using Gurobi version 10.0.0")
LIST(APPEND SOLVER_BACKEND_LINK_LIBRARIES
"gurobi100")
elseif (${TETRISCHED_GUROBI_VER} EQUAL 11)
message("-- Using Gurobi version 11.0.0")
LIST(APPEND SOLVER_BACKEND_LINK_LIBRARIES
"gurobi110")
else()
message(FATAL_ERROR "The linking for Gurobi Version ${TETRISCHED_GUROBI_VER} is not defined.")
endif()
else()
message("-- Not Adding GUROBI")
endif()
Expand Down
54 changes: 42 additions & 12 deletions schedulers/tetrisched/include/tetrisched/Expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,20 @@ struct ExpressionTimeBounds {
std::string toString() const;
};

/// An `ExpressionStatus` enumeration represents the status of an expression.
/// The status of an Expression is used to determine if the Expression was
/// satisfied before. If so, the Solver can be informed of the initial values
/// of the variables that were used to satisfy the Expression.
enum ExpressionStatus {
/// The Expression was not satisfied before.
EXPR_STATUS_UNSATISFIED = 0,
/// The Expression was satisfied before.
EXPR_STATUS_SATISFIED = 1,
/// The Expression has not been encountered before, and must be solved.
EXPR_STATUS_UNKNOWN = 2,
};
using ExpressionStatus = enum ExpressionStatus;

/// A Base Class for all expressions in the STRL language.
class Expression : public std::enable_shared_from_this<Expression> {
protected:
Expand All @@ -205,6 +219,8 @@ class Expression : public std::enable_shared_from_this<Expression> {
SolutionResultPtr solution;
/// The time bounds for this Expression.
ExpressionTimeBounds timeBounds;
/// The status of this Expression.
ExpressionStatus status;
/// A mutex representing a lock on the parsing and population of results
/// from this Expression.
std::mutex expressionMutex;
Expand All @@ -214,7 +230,8 @@ class Expression : public std::enable_shared_from_this<Expression> {

public:
/// Construct the Expression class of the given type.
Expression(std::string name, ExpressionType type);
Expression(std::string name, ExpressionType type,
ExpressionStatus status = ExpressionStatus::EXPR_STATUS_UNKNOWN);

/// Prevent copies of the Expression class.
Expression(const Expression&) = delete;
Expand Down Expand Up @@ -271,6 +288,9 @@ class Expression : public std::enable_shared_from_this<Expression> {
/// Note that only certain Expressions may choose to use this information.
void setTimeBounds(ExpressionTimeBounds timeBounds);

/// Retrieves the status of the Expression.
ExpressionStatus getStatus() const;

/// Populates the solution of the subtree rooted at this Expression and
/// returns the Solution for this Expression. It assumes that the
/// SolverModelPtr has been populated with values for unknown variables and
Expand Down Expand Up @@ -299,6 +319,9 @@ class Expression : public std::enable_shared_from_this<Expression> {
std::optional<ParseResultPtr> getParsedResult() const;
};

/// A `PriorPlacement` represents the usage of Partitions for a given placement.
using PriorPlacement = std::vector<std::pair<PartitionPtr, uint32_t>>;

/// A `ChooseExpression` represents a choice of a required number of machines
/// from the set of resource partitions for the given duration starting at the
/// provided start_time.
Expand All @@ -322,14 +345,22 @@ class ChooseExpression : public Expression {
/// The variables that represent the choice of each Partition for this
/// Expression.
std::unordered_map<uint32_t, VariablePtr> partitionVariables;
/// The prior placements for this ChooseExpression if they exist.
std::optional<PriorPlacement> priorPlacements;

public:
ChooseExpression(std::string taskName, std::string strategyName,
Partitions resourcePartitions, uint32_t numRequiredMachines,
Time startTime, Time duration, TETRISCHED_ILP_TYPE utility);
ChooseExpression(std::string taskName, Partitions resourcePartitions,
uint32_t numRequiredMachines, Time startTime, Time duration,
TETRISCHED_ILP_TYPE utility);
ChooseExpression(
std::string taskName, std::string strategyName,
Partitions resourcePartitions, uint32_t numRequiredMachines,
Time startTime, Time duration, TETRISCHED_ILP_TYPE utility,
ExpressionStatus status = ExpressionStatus::EXPR_STATUS_UNKNOWN,
std::optional<PriorPlacement> priorPlacements = std::nullopt);
ChooseExpression(
std::string taskName, Partitions resourcePartitions,
uint32_t numRequiredMachines, Time startTime, Time duration,
TETRISCHED_ILP_TYPE utility,
ExpressionStatus status = ExpressionStatus::EXPR_STATUS_UNKNOWN,
std::optional<PriorPlacement> priorPlacements = std::nullopt);
void addChild(ExpressionPtr child) override;
ParseResultPtr parse(SolverModelPtr solverModel,
Partitions availablePartitions,
Expand Down Expand Up @@ -430,7 +461,7 @@ class MalleableChooseExpression : public Expression {
class AllocationExpression : public Expression {
private:
/// The allocation from each Partition that is part of this Placement.
std::vector<std::pair<PartitionPtr, uint32_t>> allocatedResources;
PriorPlacement allocatedResources;
/// The start time of the allocation represented by this Expression.
Time startTime;
/// The duration of the allocation represented by this Expression.
Expand All @@ -439,10 +470,9 @@ class AllocationExpression : public Expression {
Time endTime;

public:
AllocationExpression(
std::string taskName,
std::vector<std::pair<PartitionPtr, uint32_t>> partitionAssignments,
Time startTime, Time duration);
AllocationExpression(std::string taskName,
PriorPlacement partitionAssignments, Time startTime,
Time duration);
void addChild(ExpressionPtr child) override;
ParseResultPtr parse(SolverModelPtr solverModel,
Partitions availablePartitions,
Expand Down
3 changes: 3 additions & 0 deletions schedulers/tetrisched/include/tetrisched/SolverModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ class VariableT {
/// search.
void hint(T hintValue);

/// Retrieves the hinted value for the variable, if available.
std::optional<T> getHint() const;

/// Retrieve a string representation of this VariableT.
std::string toString() const;

Expand Down
9 changes: 9 additions & 0 deletions schedulers/tetrisched/include/tetrisched/Types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@
// values for this macro is supposed to be int32_t or double.
#define TETRISCHED_ILP_TYPE double


// Macro for hinting the variables.
// We have two strategies for hinting the variables.
// 1. We can hint the variables from a solution value cache saved from the previous
// iteration. This is the default behavior.
// 2. We can infer hints from which leaves have been previously satisfied. To turn
// this behavior on, set the following macro to true.
#define TETRISCHED_INFER_HINTS_FROM_LEAVES false

namespace tetrisched {
/// Defines the exceptions that the methods can throw.
namespace exceptions {
Expand Down
119 changes: 75 additions & 44 deletions schedulers/tetrisched/python/Expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ void defineSTRLExpressions(py::module_& tetrisched_m) {
.value("EXPR_WINDOWED_CHOOSE",
tetrisched::ExpressionType::EXPR_WINDOWED_CHOOSE);

// Define the ExpressionStatus enum.
py::enum_<tetrisched::ExpressionStatus>(tetrisched_m, "ExpressionStatus")
.value("EXPR_STATUS_UNKNOWN",
tetrisched::ExpressionStatus::EXPR_STATUS_UNKNOWN)
.value("EXPR_STATUS_SATISFIED",
tetrisched::ExpressionStatus::EXPR_STATUS_SATISFIED)
.value("EXPR_STATUS_UNSATISFIED",
tetrisched::ExpressionStatus::EXPR_STATUS_UNSATISFIED);

// Define the Placement object.
py::class_<tetrisched::Placement, tetrisched::PlacementPtr>(tetrisched_m,
"Placement")
Expand Down Expand Up @@ -119,50 +128,72 @@ void defineSTRLExpressions(py::module_& tetrisched_m) {
py::class_<tetrisched::ChooseExpression, tetrisched::Expression,
std::shared_ptr<tetrisched::ChooseExpression>>(tetrisched_m,
"ChooseExpression")
.def(py::init([](std::string taskName, std::string strategyName,
tetrisched::Partitions partitions,
uint32_t numRequiredMachines, tetrisched::Time startTime,
tetrisched::Time duration, TETRISCHED_ILP_TYPE utility) {
return std::make_shared<tetrisched::ChooseExpression>(
taskName, strategyName, partitions, numRequiredMachines,
startTime, duration, utility);
}),
"Initializes a ChooseExpression for the given task to be placed on "
"`numRequiredMachines` from the given partition at the given "
"startTime, running for the given duration.\n"
"\nArgs:\n"
" taskName (str): The name of the task to be placed.\n"
" strategyName (str): The name of the strategy of the Choose.\n"
" partitions (Partitions): The Partitions to be placed on.\n"
" numRequiredMachines (int): The number of machines required "
"for the task.\n"
" startTime (int): The start time of the task.\n"
" duration (int): The duration of the task.\n"
" utility (TETRISCHED_ILP_TYPE): The utility of the task.",
py::arg("taskName"), py::arg("strategyName"), py::arg("partitions"),
py::arg("numRequiredMachines"), py::arg("startTime"),
py::arg("duration"), py::arg("utility"))
.def(py::init([](std::string taskName, tetrisched::Partitions partitions,
uint32_t numRequiredMachines, tetrisched::Time startTime,
tetrisched::Time duration, TETRISCHED_ILP_TYPE utility) {
return std::make_shared<tetrisched::ChooseExpression>(
taskName, partitions, numRequiredMachines, startTime, duration,
utility);
}),
"Initializes a ChooseExpression for the given task to be placed on "
"`numRequiredMachines` from the given partition at the given "
"startTime, running for the given duration.\n"
"\nArgs:\n"
" taskName (str): The name of the task to be placed.\n"
" partitions (Partitions): The Partitions to be placed on.\n"
" numRequiredMachines (int): The number of machines required "
"for the task.\n"
" startTime (int): The start time of the task.\n"
" duration (int): The duration of the task.\n"
" utility (TETRISCHED_ILP_TYPE): The utility of the task.",
py::arg("taskName"), py::arg("partitions"),
py::arg("numRequiredMachines"), py::arg("startTime"),
py::arg("duration"), py::arg("utility"));
.def(
py::init(
[](std::string taskName, std::string strategyName,
tetrisched::Partitions partitions,
uint32_t numRequiredMachines, tetrisched::Time startTime,
tetrisched::Time duration, TETRISCHED_ILP_TYPE utility,
tetrisched::ExpressionStatus status =
tetrisched::ExpressionStatus::EXPR_STATUS_UNKNOWN,
std::optional<tetrisched::PriorPlacement> priorPlacements =
std::nullopt) {
return std::make_shared<tetrisched::ChooseExpression>(
taskName, strategyName, partitions, numRequiredMachines,
startTime, duration, utility, status, priorPlacements);
}),
"Initializes a ChooseExpression for the given task to be placed on \n"
"`numRequiredMachines` from the given partition at the given \n"
"startTime, running for the given duration.\n"
"\nArgs:\n"
" taskName (str): The name of the task to be placed.\n"
" strategyName (str): The name of the strategy of the Choose.\n"
" partitions (Partitions): The Partitions to be placed on.\n"
" numRequiredMachines (int): The number of machines required \n"
" for the task.\n"
" startTime (int): The start time of the task.\n"
" duration (int): The duration of the task.\n"
" utility (TETRISCHED_ILP_TYPE): The utility of the task.\n "
" status (ExpressionStatus): The status of the expression in a \n"
" previous cycle, if available.\n"
" priorPlacements (PriorPlacement): The prior placements of the \n"
" expression in a previous cycle, if available.\n",
py::arg("taskName"), py::arg("strategyName"), py::arg("partitions"),
py::arg("numRequiredMachines"), py::arg("startTime"),
py::arg("duration"), py::arg("utility"), py::arg("status"),
py::arg("priorPlacements"))
.def(
py::init(
[](std::string taskName, tetrisched::Partitions partitions,
uint32_t numRequiredMachines, tetrisched::Time startTime,
tetrisched::Time duration, TETRISCHED_ILP_TYPE utility,
tetrisched::ExpressionStatus status =
tetrisched::ExpressionStatus::EXPR_STATUS_UNKNOWN,
std::optional<tetrisched::PriorPlacement> priorPlacements =
std::nullopt) {
return std::make_shared<tetrisched::ChooseExpression>(
taskName, partitions, numRequiredMachines, startTime,
duration, utility, status, priorPlacements);
}),
"Initializes a ChooseExpression for the given task to be placed on \n"
"`numRequiredMachines` from the given partition at the given \n"
"startTime, running for the given duration.\n"
"\nArgs:\n"
" taskName (str): The name of the task to be placed.\n"
" partitions (Partitions): The Partitions to be placed on.\n"
" numRequiredMachines (int): The number of machines required \n"
" for the task.\n"
" startTime (int): The start time of the task.\n"
" duration (int): The duration of the task.\n"
" utility (TETRISCHED_ILP_TYPE): The utility of the task.\n"
" status (ExpressionStatus): The status of the expression in a \n"
" previous cycle, if available.\n"
" priorPlacements (PriorPlacement): The prior placements of the \n"
" expression in a previous cycle, if available.\n",
py::arg("taskName"), py::arg("partitions"),
py::arg("numRequiredMachines"), py::arg("startTime"),
py::arg("duration"), py::arg("utility"), py::arg("status"),
py::arg("priorPlacements"));

// Define the WindowedChooseExpression.
py::class_<tetrisched::WindowedChooseExpression, tetrisched::Expression,
Expand Down
Loading

0 comments on commit c902a91

Please sign in to comment.