Skip to content

Commit

Permalink
Add debugging to optimization passes and aggressively optimize.
Browse files Browse the repository at this point in the history
  • Loading branch information
sukritkalra committed Nov 9, 2023
1 parent ac4a42c commit 6606803
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 31 deletions.
30 changes: 20 additions & 10 deletions schedulers/tetrisched/include/tetrisched/OptimizationPasses.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,15 @@ class OptimizationPass {
/// Get the type of the optimization pass.
OptimizationPassType getType() const;

/// Run the pass on the given STRL expression.
/// Get the name of the optimization pass.
std::string getName() const;

/// Run the pass on the given STRL expression and the CapacityConstraintMap.
/// If an output log file is provided, the pass may choose to log useful
/// information to the file.
virtual void runPass(ExpressionPtr strlExpression,
CapacityConstraintMap& capacityConstraints) = 0;
CapacityConstraintMap& capacityConstraints,
std::optional<std::string> debugFile) = 0;

// Clean the pass after a run.
virtual void clean() = 0;
Expand All @@ -59,7 +65,8 @@ class CriticalPathOptimizationPass : public OptimizationPass {

/// Run the Critical Path optimization pass on the given STRL expression.
void runPass(ExpressionPtr strlExpression,
CapacityConstraintMap& capacityConstraints) override;
CapacityConstraintMap& capacityConstraints,
std::optional<std::string> debugFile) override;

/// Clean the pass data structures.
void clean() override;
Expand All @@ -71,14 +78,14 @@ class CriticalPathOptimizationPass : public OptimizationPass {
class CapacityConstraintMapPurgingOptimizationPass : public OptimizationPass {
private:
/// A HashMap of the Expression ID to the cliques in the Expression tree.
std::unordered_map<std::string, std::unordered_set<std::string>> cliques;
std::unordered_map<ExpressionPtr, std::unordered_set<ExpressionPtr>> cliques;

/// Computes the cliques from a bottom-up traversal of the STRL.
void computeCliques(ExpressionPtr expression);

/// Deactivates the CapacityConstraints that are trivially satisfied.
void deactivateCapacityConstraints(
CapacityConstraintMap& capacityConstraints);
void deactivateCapacityConstraints(CapacityConstraintMap& capacityConstraints,
std::optional<std::string> debugFile);

public:
/// Instantiate the CapacityConstraintMapPurgingOptimizationPass.
Expand All @@ -87,27 +94,30 @@ class CapacityConstraintMapPurgingOptimizationPass : public OptimizationPass {
/// Run the CapacityConstraintMapPurgingOptimizationPass on the given STRL
/// expression.
void runPass(ExpressionPtr strlExpression,
CapacityConstraintMap& capacityConstraints) override;
CapacityConstraintMap& capacityConstraints,
std::optional<std::string> debugFile) override;

/// Clean the pass data structures.
void clean() override;
};

class OptimizationPassRunner {
private:
/// If True, the optimization passes may output logs.
bool debug;
/// A list of optimization passes to run.
std::vector<OptimizationPassPtr> registeredPasses;

public:
/// Initialize the OptimizationPassRunner.
OptimizationPassRunner();
OptimizationPassRunner(bool debug = false);

/// Run the pre-translation optimization passes on the given STRL expression.
void runPreTranslationPasses(ExpressionPtr strlExpression,
void runPreTranslationPasses(Time currentTime, ExpressionPtr strlExpression,
CapacityConstraintMap& capacityConstraints);

/// Run the post-translation optimization passes on the given STRL expression.
void runPostTranslationPasses(ExpressionPtr strlExpression,
void runPostTranslationPasses(Time currentTime, ExpressionPtr strlExpression,
CapacityConstraintMap& capacityConstraints);
};
} // namespace tetrisched
Expand Down
90 changes: 73 additions & 17 deletions schedulers/tetrisched/src/OptimizationPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ OptimizationPass::OptimizationPass(std::string name, OptimizationPassType type)

OptimizationPassType OptimizationPass::getType() const { return type; }

std::string OptimizationPass::getName() const { return name; }

/* Methods for CriticalPathOptimizationPass */
CriticalPathOptimizationPass::CriticalPathOptimizationPass()
: OptimizationPass("CriticalPathOptimizationPass",
Expand Down Expand Up @@ -350,7 +352,8 @@ void CriticalPathOptimizationPass::purgeNodes(ExpressionPtr expression) {
}

void CriticalPathOptimizationPass::runPass(
ExpressionPtr strlExpression, CapacityConstraintMap& capacityConstraints) {
ExpressionPtr strlExpression, CapacityConstraintMap& capacityConstraints,
std::optional<std::string> debugFile) {
/* Phase 1: We first do a bottom-up traversal of the tree to compute
a tight bound for each node in the STRL tree. */
computeTimeBounds(strlExpression);
Expand Down Expand Up @@ -412,15 +415,15 @@ void CapacityConstraintMapPurgingOptimizationPass::computeCliques(
TETRISCHED_DEBUG("Creating a clique for Expression "
<< currentExpression->getId() << " ("
<< currentExpression->getName() << ")")
std::unordered_set<std::string> clique;
std::unordered_set<ExpressionPtr> clique;
for (auto& child : currentExpression->getChildren()) {
clique.insert(child->getId());
clique.insert(child);
TETRISCHED_DEBUG("Inserting " << child->getId() << " ("
<< child->getName()
<< ") to the clique for "
<< currentExpression->getId())
}
cliques[currentExpression->getId()] = clique;
cliques[currentExpression] = clique;
}
}

Expand All @@ -435,11 +438,15 @@ void CapacityConstraintMapPurgingOptimizationPass::computeCliques(
}

void CapacityConstraintMapPurgingOptimizationPass::
deactivateCapacityConstraints(CapacityConstraintMap& capacityConstraints) {
deactivateCapacityConstraints(CapacityConstraintMap& capacityConstraints,
std::optional<std::string> debugFile) {
std::ofstream debugFileStream;
if (debugFile.has_value()) {
debugFileStream.open(debugFile.value());
}
// Construct a vector of the size of the number of cliques.
// This vector will keep track of if the clique was used in a constraint, and
// if so, its maximum usage.
// std::vector<std::pair<bool, uint32_t>> cliqueUsage(cliques.size());
TETRISCHED_DEBUG("Running deactivation of constraints from a map of size "
<< capacityConstraints.size())
size_t deactivatedConstraints = 0;
Expand All @@ -448,8 +455,7 @@ void CapacityConstraintMapPurgingOptimizationPass::
for (auto& [key, capacityConstraint] :
capacityConstraints.capacityConstraints) {
// Reset the clique usage vector.
// cliqueUsage.assign(cliqueUsage.size(), std::make_pair(false, 0));
std::unordered_map<std::string, uint32_t> expressionUsageMap;
std::unordered_map<ExpressionPtr, uint32_t> expressionUsageMap;

// Iterate over all the Expressions that contribute to a usage in
// this CapacityConstraint, and turn on their clique usage.
Expand All @@ -460,9 +466,9 @@ void CapacityConstraintMapPurgingOptimizationPass::
") of type " + expression->getTypeString() +
" has more than one parent. This is not supported.");
}
auto expressionKey = expression->getParents()[0]->getId();
auto expressionKey = expression->getParents()[0];
if (cliques.find(expressionKey) == cliques.end()) {
expressionKey = expression->getId();
expressionKey = expression;
}

// We make note of the maximum usage that this clique can
Expand All @@ -486,6 +492,35 @@ void CapacityConstraintMapPurgingOptimizationPass::
}
}

// All the MAX cliques have been identified, if they are immediately
// ordered by a < expression, then we can keep bubbling up the checks
// until they reach a min.
std::unordered_set<ExpressionPtr> keysToDelete;
do {
// Clear up the keys to delete.
keysToDelete.clear();

// Bubble up cliques.
for (auto& [clique, usage] : expressionUsageMap) {
for (auto& parent : clique->getParents()) {
if (parent->getType() == ExpressionType::EXPR_LESSTHAN) {
keysToDelete.insert(clique);
if (expressionUsageMap.find(parent) == expressionUsageMap.end()) {
expressionUsageMap[parent] = usage;
} else {
expressionUsageMap[parent] =
std::max(expressionUsageMap[parent], usage);
}
}
}
}

// Delete redundant keys.
for (auto& key : keysToDelete) {
expressionUsageMap.erase(key);
}
} while (keysToDelete.size() > 0);

// If the clique usage is <= RHS, then we can deactivate this constraint.
uint32_t totalUsage = 0;
for (auto& [clique, usage] : expressionUsageMap) {
Expand All @@ -506,14 +541,23 @@ void CapacityConstraintMapPurgingOptimizationPass::
<< capacityConstraint->getQuantity()
<< " and its maximum resource usage is " << totalUsage)
}

if (debugFile.has_value()) {
debugFileStream << capacityConstraint->getName() << ": " << totalUsage
<< ", " << capacityConstraint->getQuantity() << std::endl;
}
}
TETRISCHED_DEBUG("Deactivated " << deactivatedConstraints << " out of "
<< capacityConstraints.size()
<< " constraints.")
std::cout << "Deactivated " << deactivatedConstraints << " out of "
<< capacityConstraints.size()
<< " constraints." << std::endl;
}

void CapacityConstraintMapPurgingOptimizationPass::runPass(
ExpressionPtr strlExpression, CapacityConstraintMap& capacityConstraints) {
ExpressionPtr strlExpression, CapacityConstraintMap& capacityConstraints,
std::optional<std::string> debugFile) {
/* Phase 1: We compute the cliques from the Expressions in the DAG. */
auto cliqueStartTime = std::chrono::high_resolution_clock::now();
computeCliques(strlExpression);
Expand All @@ -527,7 +571,7 @@ void CapacityConstraintMapPurgingOptimizationPass::runPass(
/* Phase 2: We go over each of the CapacityConstraint in the map, and
deactivate the constraint that is trivially satisfied. */
auto deactivationStartTime = std::chrono::high_resolution_clock::now();
deactivateCapacityConstraints(capacityConstraints);
deactivateCapacityConstraints(capacityConstraints, debugFile);
auto deactivationEndTime = std::chrono::high_resolution_clock::now();
auto deactivationDuration =
std::chrono::duration_cast<std::chrono::microseconds>(
Expand All @@ -540,7 +584,7 @@ void CapacityConstraintMapPurgingOptimizationPass::runPass(
void CapacityConstraintMapPurgingOptimizationPass::clean() { cliques.clear(); }

/* Methods for OptimizationPassRunner */
OptimizationPassRunner::OptimizationPassRunner() {
OptimizationPassRunner::OptimizationPassRunner(bool debug) : debug(debug) {
// Register the Critical Path optimization pass.
registeredPasses.push_back(std::make_shared<CriticalPathOptimizationPass>());
// Register the CapacityConstraintMapPurging optimization pass.
Expand All @@ -549,22 +593,34 @@ OptimizationPassRunner::OptimizationPassRunner() {
}

void OptimizationPassRunner::runPreTranslationPasses(
ExpressionPtr strlExpression, CapacityConstraintMap& capacityConstraints) {
Time currentTime, ExpressionPtr strlExpression,
CapacityConstraintMap& capacityConstraints) {
// Run the registered optimization passes on the given STRL expression.
for (auto& pass : registeredPasses) {
if (pass->getType() == OptimizationPassType::PRE_TRANSLATION_PASS) {
pass->runPass(strlExpression, capacityConstraints);
auto debugFile =
debug
? std::optional<std::string>(pass->getName() + "_" +
std::to_string(currentTime) + ".log")
: std::nullopt;
pass->runPass(strlExpression, capacityConstraints, debugFile);
pass->clean();
}
}
}

void OptimizationPassRunner::runPostTranslationPasses(
ExpressionPtr strlExpression, CapacityConstraintMap& capacityConstraints) {
Time currentTime, ExpressionPtr strlExpression,
CapacityConstraintMap& capacityConstraints) {
// Run the registered optimization passes on the given STRL expression.
for (auto& pass : registeredPasses) {
if (pass->getType() == OptimizationPassType::POST_TRANSLATION_PASS) {
pass->runPass(strlExpression, capacityConstraints);
auto debugFile =
debug
? std::optional<std::string>(pass->getName() + "_" +
std::to_string(currentTime) + ".log")
: std::nullopt;
pass->runPass(strlExpression, capacityConstraints, debugFile);
pass->clean();
}
}
Expand Down
6 changes: 3 additions & 3 deletions schedulers/tetrisched/src/Scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Scheduler::Scheduler(Time discretization, SolverBackendType solverBackend)
"The solver backend type is not supported.");
}
solverModel = solver->getModel();
optimizationPasses = OptimizationPassRunner();
optimizationPasses = OptimizationPassRunner(true);
}

void Scheduler::registerSTRL(ExpressionPtr expression,
Expand All @@ -56,7 +56,7 @@ void Scheduler::registerSTRL(ExpressionPtr expression,
// Run the Pre-Translation OptimizationPasses on this expression.
if (optimize) {
auto optimizerStartTime = std::chrono::high_resolution_clock::now();
optimizationPasses.runPreTranslationPasses(expression,
optimizationPasses.runPreTranslationPasses(currentTime, expression,
capacityConstraintMap);
auto optimizerEndTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
Expand All @@ -73,7 +73,7 @@ void Scheduler::registerSTRL(ExpressionPtr expression,
// Run the Post-Translation OptimizationPasses on this expression.
if (optimize) {
auto optimizerStartTime = std::chrono::high_resolution_clock::now();
optimizationPasses.runPostTranslationPasses(expression,
optimizationPasses.runPostTranslationPasses(currentTime, expression,
capacityConstraintMap);
auto optimizerEndTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
Expand Down
2 changes: 1 addition & 1 deletion schedulers/tetrisched/test/test_optimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ TEST(OptimizationTest, TestBasicCriticalPathOptimizationPass) {
lessThanExpression->exportToDot("PreOptimizationPass.dot");

tetrisched::CapacityConstraintMap capacityConstraintMap(1);
optimizationPass.runPass(lessThanExpression, capacityConstraintMap);
optimizationPass.runPass(lessThanExpression, capacityConstraintMap, std::nullopt);
lessThanExpression->exportToDot("PostOptimizationPass.dot");
}

0 comments on commit 6606803

Please sign in to comment.