diff --git a/src/scheduler/cpp/data.cpp b/src/scheduler/cpp/data.cpp index ce012e6..68faa8b 100644 --- a/src/scheduler/cpp/data.cpp +++ b/src/scheduler/cpp/data.cpp @@ -6,14 +6,13 @@ #include #include "data.h" -std::unordered_map> parse_configurations_file( +app_configs_t parse_configurations_file( std::string configurations_file) { std::ifstream infile(configurations_file); std::string app_id; int num_frozen, fps; double cost, metric; - std::unordered_map> - possible_configurations = {}; + app_configs_t possible_configurations = {}; while (infile >> app_id >> num_frozen >> fps >> cost >> metric) { std::vector units; ScheduleUnit unit = ScheduleUnit(app_id, num_frozen, fps, cost, metric); diff --git a/src/scheduler/cpp/data.h b/src/scheduler/cpp/data.h index 16ab7bd..cfa7015 100644 --- a/src/scheduler/cpp/data.h +++ b/src/scheduler/cpp/data.h @@ -16,7 +16,7 @@ typedef std::shared_ptr (*scheduler_fn_ptr) ( double budget, int verbose); -std::unordered_map> parse_configurations_file( +app_configs_t parse_configurations_file( std::string configurations_file); std::vector parse_model_file(std::string model_file); diff --git a/src/scheduler/cpp/stem_search.cpp b/src/scheduler/cpp/stem_search.cpp index 29543ab..4ab3d14 100644 --- a/src/scheduler/cpp/stem_search.cpp +++ b/src/scheduler/cpp/stem_search.cpp @@ -1,8 +1,11 @@ +#include #include #include #include +#include #include #include +#include #include #include #include @@ -15,95 +18,278 @@ #include "types/shared_stem.h" #include "types/utility.h" -ResultCurve get_pareto_curve( +std::vector get_pareto_curves( const SharedStem& stem, - double budget, - app_configs_t possible_app_configs, - std::vector app_ids) { + const double budget, + app_configs_t all_app_configs, + const std::vector& app_ids, + const std::vector& dp_prev = {}, + app_configs_t delta_app_configs = {}) { std::vector dp; - // cerr << stem << endl; - // int cnt = 0; - for (std::string& app_id : app_ids) { + int app_idx = 0; + bool dirty = false; + for (std::string app_id : app_ids) { ResultCurve results; // App configs allowed under stem. + // TODO: Remove since redundant (applied earlier). std::set allowed_configs; - // std::cerr << "Allowed: "; - for (const ScheduleUnit& unit : possible_app_configs[app_id]) { - if (stem.Allows(unit)) { + if (dirty || delta_app_configs.size() == 0) { + for (const ScheduleUnit& unit : all_app_configs[app_id]) { + assert(stem.Allows(unit)); + allowed_configs.insert(unit); + } + } else { + for (const ScheduleUnit& unit : delta_app_configs[app_id]) { + assert(stem.Allows(unit)); allowed_configs.insert(unit); - // std::cerr << unit << ","; } } // Prune possible_app_configs to those that are optimal. + // TODO: Remove since redundant (applied earlier). cost_t best_so_far = std::numeric_limits::infinity(); for (auto ii = allowed_configs.begin(); ii != allowed_configs.end(); ) { if (F_LESS(ii->GetBranchCost(), best_so_far)) { best_so_far = ii->GetBranchCost(); ++ii; } else { + assert(false); ii = allowed_configs.erase(ii); } } - if (dp.size() == 0) { - for (auto ii = allowed_configs.rbegin(); ii != allowed_configs.rend(); ++ii) { - const ScheduleUnit& app_config_unit = *ii; - // results.Add(std::make_shared(app_config_unit, stem.GetCost())); - results.Add(Result(app_config_unit, stem.GetCost())); + // TODO: Optimisation: if allowed_configs is empty, just return dp_prev. + if (dp_prev.size() > 0) { + // assert(dp_prev.find(app_idx) != dp_prev.end()); + if (allowed_configs.size() > 0) { + results.assign(dp_prev[app_idx]); + } else { + results.assign_vec(dp_prev[app_idx]); } - } else { - for (const auto& partial_result : dp[dp.size() - 1]) { + } + if (allowed_configs.size() > 0) { + if (app_idx == 0) { for (auto ii = allowed_configs.rbegin(); ii != allowed_configs.rend(); ++ii) { - const ScheduleUnit& unit = *ii; - // Prune configurations that are over budget. - if (!F_MORE(partial_result->GetCost() + unit.GetBranchCost(), budget)) { - // results.Add(std::make_shared(unit, partial_result)); - results.Add(Result(unit, partial_result)); - } else { - // Since we are enumerating allowed_configs in increasing F1/weight, - // we can break. - break; + const ScheduleUnit& app_config_unit = *ii; + results.Add(Result(app_config_unit, 0)); + } + } else { + for (const auto& partial_result : dp[dp.size() - 1]) { + for (auto ii = allowed_configs.rbegin(); ii != allowed_configs.rend(); ++ii) { + const ScheduleUnit& unit = *ii; + // Prune configurations that are over budget. + if (!F_MORE(partial_result->GetCost() + unit.GetBranchCost(), budget)) { + if (app_idx == app_ids.size() - 1) { + results.Add(Result(unit, partial_result, stem.GetCost())); + } else { + results.Add(Result(unit, partial_result)); + } + } else { + // Since we are enumerating allowed_configs in increasing F1/weight, + // we can break. + break; + } } } } } // cerr << "\t" << ++cnt << " " << results.size() << endl; + // if (results.IsDirty()) { + // std::cerr << "dirty at " << app_idx << std::endl; + // } + dirty = dirty || results.IsDirty(); results.Finalize(); dp.push_back(results); + app_idx++; } - if (dp[dp.size() - 1].size() > 0) { - dp[dp.size() - 1].BestResult(); + assert(app_ids.size() == dp.size()); + if (dp.back().size() > 0) { + dp.back().BestResult(); + } + return dp; +} + +app_configs_t filter_configs(app_configs_t possible_configs, + const SharedStem& stem) { + app_configs_t stem_app_configs; + for (const auto& kv : possible_configs) { + std::vector allowed_configs; + for (const ScheduleUnit& unit : kv.second) { + if (stem.Allows(unit)) { + allowed_configs.push_back(unit); + } + } + stem_app_configs[kv.first] = allowed_configs; } - return dp[dp.size() - 1]; + return stem_app_configs; } +std::pair partition_configs( + app_configs_t possible_configs, + const SharedStem& stem) { + app_configs_t stem_app_configs, remaining; + for (const auto& kv : possible_configs) { + std::vector allowed_configs, remaining_local; + for (const ScheduleUnit& unit : kv.second) { + if (stem.Allows(unit)) { + allowed_configs.push_back(unit); + } else { + remaining_local.push_back(unit); + } + } + stem_app_configs[kv.first] = allowed_configs; + remaining[kv.first] = remaining_local; + } + return {stem_app_configs, remaining}; +} -std::shared_ptr get_optimal_schedule( +// For each stem, filter those that don't match at the outset. +// Only supply those configs that are valid, but not under parent. +// Allow to supply a dp array, which will be used to start off. +Result::ptr_t stems_dp( + const std::set& fps_options, + const std::set& chokepoints, std::vector app_ids, app_configs_t possible_configurations, - layer_costs_t layer_costs, + const layer_costs_t& layer_costs_subset_sums, double budget, int verbose) { - // Enumerate through stems. - - // Initialise FPSes, chokepoints and max_steps. - std::set fps_options; - std::set chokepoints; - for (const auto& kv : possible_configurations) { - for (const auto& unit : kv.second) { - fps_options.insert(unit.GetFPS()); - chokepoints.insert(unit.GetNumFrozen()); - } - } + Result::ptr_t solution = nullptr; int max_steps = std::min(possible_configurations.size(), std::min(chokepoints.size(), fps_options.size())); - layer_costs_t layer_costs_subset_sums = get_subset_sums(layer_costs); + // FPS in descending order. + std::vector fps_options_(fps_options.rbegin(), fps_options.rend()); + std::vector chokepoints_(chokepoints.begin(), chokepoints.end()); - Result::ptr_t solution = nullptr; + // Stacks. + std::vector> chosen_idxs; + std::vector chosen_fpses, chosen_chokepoints; + std::vector> dps_stack; + std::vector remaining_configs; + + chosen_idxs.reserve(max_steps); + chosen_fpses.reserve(max_steps); + chosen_chokepoints.reserve(max_steps); + dps_stack.reserve(max_steps); + remaining_configs.reserve(max_steps); + + chosen_idxs.push_back({0, -1}); + chosen_chokepoints.push_back(-1); + chosen_fpses.push_back(-1); + dps_stack.push_back({}); + remaining_configs.push_back(possible_configurations); + + while (!chosen_idxs.empty()) { + // process + auto idxes = chosen_idxs.back(); + chosen_idxs.pop_back(); + chosen_chokepoints.pop_back(); + chosen_fpses.pop_back(); + if (idxes.first == chokepoints_.size() - 1 && + idxes.second == fps_options_.size() - 1) { + dps_stack.pop_back(); + remaining_configs.pop_back(); + continue; + } else if (idxes.second == fps_options_.size() - 1) { + chosen_idxs.push_back({idxes.first + 1, + chosen_idxs.size() > 0 ? chosen_idxs.back().second + 1 : 0}); + } else { + chosen_idxs.push_back({idxes.first, idxes.second + 1}); + } + std::pair curr = chosen_idxs.back(); + chosen_chokepoints.push_back(chokepoints_[curr.first]); + chosen_fpses.push_back(fps_options_[curr.second]); + + if (verbose > 1) { + for(auto&& kv : chosen_idxs) { + std::cerr << "(" << kv.first << ',' << kv.second << ") "; + } + std::cerr << ", "; + for(auto&& fps : chosen_fpses) { + std::cerr << fps << ' '; + } + std::cerr << ", "; + for(auto&& chokepoint : chosen_chokepoints) { + std::cerr << chokepoint << ' '; + } + std::cerr << std::endl; + std::cerr << "DP: "; + for(auto&& dps : dps_stack) { + for(auto&& dp : dps) { + std::cerr << dp.size() << ", "; + } + std::cerr << " | "; + } + std::cerr << std::endl; + } + + // Process the stem. + assert(chosen_chokepoints.size() == chosen_idxs.size()); + assert(chosen_fpses.size() == chosen_idxs.size()); + assert(dps_stack.size() == chosen_idxs.size()); + assert(remaining_configs.size() == chosen_idxs.size()); + SharedStem stem(chosen_chokepoints, chosen_fpses, + std::make_shared>(layer_costs_subset_sums)); + + if (verbose > 1) { + std::cerr << stem << std::endl; + } + if (F_MORE(stem.GetCost(), budget)) { + continue; + } + + auto valid_configs = filter_configs(possible_configurations, stem); + auto delta_new = partition_configs(remaining_configs.back(), stem); + auto& delta_configs = delta_new.first; + auto& remaining_configs_new = delta_new.second; + if (verbose > 2) { + std::cerr << remaining_configs.size() << "(" << remaining_configs.back() << ") " << delta_configs << " " << remaining_configs_new << std::endl; + } + std::vector curves = get_pareto_curves(stem, budget, valid_configs, app_ids, dps_stack.back(), delta_configs); + if (verbose > 2) { + std::cerr << curves.size() << " ("; + for(auto&& curve : curves) { + std::cerr << curve.size() << ','; + } + std::cerr << ")" << std::endl; + } + // Relax global solution. + if (curves.back().size() > 0) { + auto result = curves.back().BestResult(); + if (solution == nullptr || *solution < *result) { + solution = result; + std::cerr << "Improved: " << std::endl; + std::cerr << "\t" << stem << std::endl; + std::cerr << "\t" << *result << std::endl; + } + } + if (chosen_idxs.size() < max_steps && + curr.first + 1 < chokepoints_.size() && + curr.second + 1 < fps_options_.size()) { + remaining_configs.push_back(remaining_configs_new); + dps_stack.push_back(curves); + chosen_idxs.push_back({curr.first + 1, curr.second}); + chosen_chokepoints.push_back(-1); + chosen_fpses.push_back(-1); + } + } + return solution; +} + +Result::ptr_t stems_simple( + const std::set& fps_options, + const std::set& chokepoints, + std::vector app_ids, + app_configs_t possible_configurations, + const layer_costs_t& layer_costs_subset_sums, + double budget, + int verbose) { + Result::ptr_t solution = nullptr; + int max_steps = std::min(possible_configurations.size(), + std::min(chokepoints.size(), fps_options.size())); int cnt_stems_total = 0; // Naive: try all stems. @@ -151,19 +337,21 @@ std::shared_ptr get_optimal_schedule( } cnt_stems_in_budget++; - ResultCurve curve = get_pareto_curve(stem, + app_configs_t stem_configs = filter_configs(possible_configurations, stem); + + ResultCurve curve = get_pareto_curves(stem, budget, - possible_configurations, - app_ids); + stem_configs, + app_ids).back(); if (curve.size() > 0) { auto result = curve.BestResult(); if (solution == nullptr || *solution < *result) { solution = result; improved_stems++; - // std::cerr << "Improved: " << std::endl; - // std::cerr << "\t" << stem << std::endl; - // std::cerr << "\t" << *result << std::endl; + std::cerr << "Improved: " << std::endl; + std::cerr << "\t" << stem << std::endl; + std::cerr << "\t" << *result << std::endl; } } } while (std::prev_permutation(chokepoint_sels.begin(), @@ -172,14 +360,58 @@ std::shared_ptr get_optimal_schedule( cnt_stems_total += cnt_stems; std::cerr << num_steps << " " << cnt_stems << " " << cnt_stems_in_budget << ' ' << improved_stems << std::endl; } - std::cerr << "Total stems: " << cnt_stems_total << std::endl; + return solution; +} + +// Enumerate through stems. +std::shared_ptr get_optimal_schedule( + std::vector app_ids, + app_configs_t possible_configurations, + layer_costs_t layer_costs, + double budget, + int verbose) { + // Prune possible_configurations to only optimal ones. + for (auto& kv : possible_configurations) { + std::set app_configs(kv.second.begin(), kv.second.end()); + cost_t best_so_far = std::numeric_limits::infinity(); + for (auto ii = app_configs.begin(); ii != app_configs.end(); ) { + if (F_LESS(ii->GetBranchCost(), best_so_far)) { + best_so_far = ii->GetBranchCost(); + ++ii; + } else { + ii = app_configs.erase(ii); + } + } + kv.second.assign(app_configs.begin(), app_configs.end()); + } + + // Initialise FPSes, chokepoints and max_steps. + std::set fps_options; + std::set chokepoints; + for (const auto& kv : possible_configurations) { + for (const auto& unit : kv.second) { + fps_options.insert(unit.GetFPS()); + chokepoints.insert(unit.GetNumFrozen()); + } + } + layer_costs_t layer_costs_subset_sums = get_subset_sums(layer_costs); + + Result::ptr_t solution = stems_dp( + // Result::ptr_t solution = stems_simple( + fps_options, + chokepoints, + app_ids, + possible_configurations, + layer_costs_subset_sums, + budget, + verbose); assert(solution != nullptr); - assert(solution->GetSchedule().size() == possible_configurations.size()); auto schedule_ = Schedule(layer_costs, budget, solution->GetSchedule()); std::cerr << std::endl; std::cerr << "Schedule: " << schedule_ << std::endl; + assert(solution->GetSchedule().size() == possible_configurations.size()); std::cerr << "Stem Cost:" << schedule_.GetStemCost() << std::endl; std::cerr << schedule_.GetCost() << ' ' << solution->GetCost() << ' '; std::cerr << schedule_.GetAverageMetric() << ' ' << -(double)solution->GetBenefit().sum_ / app_ids.size() << std::endl; @@ -189,6 +421,7 @@ std::shared_ptr get_optimal_schedule( return std::make_shared(layer_costs, budget, solution->GetSchedule()); } + int main(int argc, char *argv[]) { std::string data_dir = argv[1]; std::string setup_suffix = argv[2]; diff --git a/src/scheduler/cpp/types/result.cpp b/src/scheduler/cpp/types/result.cpp index 5966dbc..4b64dbf 100644 --- a/src/scheduler/cpp/types/result.cpp +++ b/src/scheduler/cpp/types/result.cpp @@ -14,6 +14,13 @@ Result::Result(const ScheduleUnit& new_unit, ptr_t existing) : unit_(new_unit), prev_(existing) {} +Result::Result(const ScheduleUnit& new_unit, ptr_t existing, cost_t stem_cost) : + benefit_(existing->GetBenefit() + Benefit(new_unit.GetMetric())), + cost_(existing->GetCost() + new_unit.GetBranchCost() + stem_cost), + unit_(new_unit), + prev_(existing) {} + + void Result::CollectSchedule() { if (prev_ != nullptr) { std::list schedule_list = {unit_}; diff --git a/src/scheduler/cpp/types/result.h b/src/scheduler/cpp/types/result.h index 4f14533..583f0d3 100644 --- a/src/scheduler/cpp/types/result.h +++ b/src/scheduler/cpp/types/result.h @@ -23,10 +23,12 @@ class Result { ptr_t prev_; public: - explicit Result(const ScheduleUnit& first_unit, cost_t stem_cost); + Result(const ScheduleUnit& first_unit, cost_t stem_cost); Result(const ScheduleUnit& new_unit, ptr_t existing); + Result(const ScheduleUnit& new_unit, ptr_t existing, cost_t stem_cost); + inline cost_t GetCost() const { return cost_; } @@ -43,10 +45,6 @@ class Result { void CollectSchedule(); - // std::shared_ptr> GetSchedule() const { - // std::vector schedule; - // } - inline bool operator==(const Result &other) const { return benefit_ == other.GetBenefit() && F_EQL(cost_, other.GetCost()); } @@ -65,15 +63,6 @@ class Result { std::string GetString() const; }; -// class ResultHandle { -// public: -// Result::ptr_t ptr_; - -// explicit ResultHandle(const Result::ptr_t& ptr) : ptr_(ptr) {} - -// bool operator<(const ResultHandle& rhs) const { -// return *ptr_ < *rhs.ptr_; -// } -// }; +std::ostream& operator<<(std::ostream& os, const Result& obj); #endif // RESULT_H diff --git a/src/scheduler/cpp/types/result_curve.cpp b/src/scheduler/cpp/types/result_curve.cpp index 0fb9f3d..f0930bd 100644 --- a/src/scheduler/cpp/types/result_curve.cpp +++ b/src/scheduler/cpp/types/result_curve.cpp @@ -1,33 +1,6 @@ #include "result.h" #include "result_curve.h" -// // Preserves sorted invariant as it adds. -// void Add(Result::ptr_t result) { -// ResultHandle rh(result); -// auto after = results_.lower_bound(rh); -// // Insertion will be at the correct place by F1. -// // If a later point (higher F1) has lower cost, we should not insert. -// if (after == results_.end() || F_MORE(after->ptr_->GetCost(), result->GetCost())) { -// auto kv = results_.insert(ResultHandle(result)); -// assert(kv.second); - -// // Once inserted, all preceding points (lower F1) with higher cost will -// // be suboptimal and can be removed. -// auto before = kv.first; -// while (before != results_.begin()) { -// --before; -// cost_t before_cost = before->ptr_->GetCost(); -// if (F_LESS(before_cost, result->GetCost())) { -// ++before; -// break; -// } -// } -// if (before != kv.first) { -// results_.erase(before, kv.first); -// } -// } -// } - // Preserves sorted invariant as it adds. void ResultCurve::Add(Result result) { auto after = results_set_.lower_bound(result); @@ -37,6 +10,7 @@ void ResultCurve::Add(Result result) { auto kv = results_set_.insert(result); // cerr << "Real: " << std::distance(results_set_.begin(), kv.first) / (double)results_set_.size() << ' ' << std::distance(results_set_.begin(), kv.first) << '/' << results_set_.size() << endl; assert(kv.second); + dirty_ = true; // Once inserted, all preceding points (lower F1) with higher cost will // be suboptimal and can be removed. @@ -56,54 +30,18 @@ void ResultCurve::Add(Result result) { } void ResultCurve::Finalize() { - results_.reserve(results_set_.size()); - for (const auto& i : results_set_) { - results_.push_back(std::make_shared(i)); + if (results_set_.size() > 0) { + results_.reserve(results_set_.size()); + for (const auto& i : results_set_) { + results_.push_back(std::make_shared(i)); + } + results_set_.clear(); + dirty_ = false; } - results_set_.clear(); - // std::set tmp; - // for (const auto& i : results_) { - // tmp.insert(i); - // } - - // cost_t best_so_far = numeric_limits::infinity(); - - // std::vector ret_monotonic; - - // for (auto ii = tmp.rbegin(); ii != tmp.rend(); ++ii) { - // if (F_LESS(ii->GetCost(), best_so_far)) { - // ret_monotonic.push_back(*ii); - // best_so_far = ii->GetCost(); - // } - // } - // // std::cerr << "Before: "; - // // for(auto&& i : tmp) { - // // std::cerr << "(" << i->GetBenefit() << "," << i->GetCost() << "),"; - // // } - // // std::cerr << std::endl; - // // std::cerr << "After: "; - // // for(auto&& i : ret_monotonic) { - // // std::cerr << "(" << i->GetBenefit() << "," << i->GetCost() << "),"; - // // } - // // std::cerr << std::endl; - - // results_ = std::move(ret_monotonic); } Result::ptr_t ResultCurve::BestResult() const { - // auto best = *std::max_element(results_.begin(), results_.end()); - Result::ptr_t best = *--results_.end(); + Result::ptr_t best = results_.back(); best->CollectSchedule(); return best; - // if (std::max_element(results_.begin(), results_.end()) != results_.begin()) { - // std::cerr << "Max:" << *std::max_element(results_.begin(), results_.end()) << std::endl; - // std::cerr << "After: "; - // for (auto&& i : results_) { - // std::cerr << "(" << i->GetBenefit() << "," << i->GetCost() << "),"; - // } - // std::cerr << std::endl; - // } - // assert(**std::max_element(results_.begin(), results_.end()) == **results_.begin()); - // (*results_.begin())->CollectSchedule(); - // return *results_.begin(); } diff --git a/src/scheduler/cpp/types/result_curve.h b/src/scheduler/cpp/types/result_curve.h index 3b2e8d5..8150c4d 100644 --- a/src/scheduler/cpp/types/result_curve.h +++ b/src/scheduler/cpp/types/result_curve.h @@ -9,6 +9,7 @@ class ResultCurve { using results_t = std::vector; results_t results_; std::set results_set_; + bool dirty_ = false; public: using iterator = results_t::iterator; @@ -21,6 +22,18 @@ class ResultCurve { Result::ptr_t BestResult() const; + inline void assign(const ResultCurve& rhs) { + // TODO: set doesn't use pointer... + for (const auto& v : rhs) { + results_set_.insert(*v); + } + results_.clear(); + } + + inline void assign_vec(const ResultCurve& rhs) { + results_.assign(rhs.begin(), rhs.end()); + } + inline iterator begin() { return results_.begin(); } @@ -40,6 +53,10 @@ class ResultCurve { inline size_t size() const { return results_.size(); } + + inline bool IsDirty() const { + return dirty_; + } }; diff --git a/src/scheduler/cpp/types/shared_stem.cpp b/src/scheduler/cpp/types/shared_stem.cpp index 58dea73..7540182 100644 --- a/src/scheduler/cpp/types/shared_stem.cpp +++ b/src/scheduler/cpp/types/shared_stem.cpp @@ -15,7 +15,8 @@ SharedStem::SharedStem( layer_costs_subset_sums_(layer_costs_subset_sums) { assert(chokepoints.size() == fpses.size()); // Chokepoints should be strictly increasing. - assert(std::is_sorted(chokepoints.begin(), chokepoints.end())); + assert(std::is_sorted(chokepoints.begin(), chokepoints.end(), + std::less_equal())); // FPS should be strictly decreasing. // (Yes, less_equal is confusing but correct.) assert(std::is_sorted(fpses.rbegin(), fpses.rend(), diff --git a/src/scheduler/cpp/types/utility.h b/src/scheduler/cpp/types/utility.h index a68875d..21d7eb2 100644 --- a/src/scheduler/cpp/types/utility.h +++ b/src/scheduler/cpp/types/utility.h @@ -28,4 +28,13 @@ inline std::vector get_subset_sums(const std::vector& vals) { return subset_sums; } +inline std::ostream& operator<<(std::ostream& os, const app_configs_t& obj) { + for (auto&& kv : obj) { + os << kv.first << "(" << kv.second.size() << "),"; + } + return os << std::endl; +} + + + #endif // UTILITY_H diff --git a/test/_regtest_outputs/test_optimal_schedulers.test_regression[stems_cpp-5].out b/test/_regtest_outputs/test_optimal_schedulers.test_regression[stems_cpp-5].out index 832dda0..7106261 100644 --- a/test/_regtest_outputs/test_optimal_schedulers.test_regression[stems_cpp-5].out +++ b/test/_regtest_outputs/test_optimal_schedulers.test_regression[stems_cpp-5].out @@ -1,20 +1,20 @@ -2,0.133914,45,45,4,3,400 -2,0.119788,45,45,5,3,200 -2,0.0764066,33,33,5,3,400 -2,0.164278,45,45,5,3,500 -2,0.0965574,33,33,5,2,300 -3,0.0711344,33,33,33,3,4,2,100 -3,0.146127,33,33,33,3,5,3,400 +2,0.133914,45,69,4,3,400 +2,0.119788,45,69,5,3,200 +2,0.0764066,33,69,5,3,400 +2,0.164278,45,69,5,3,500 +2,0.0965574,33,51,5,2,300 +3,0.0675881,33,33,51,3,5,2,100 +3,0.146127,33,33,69,3,5,3,400 3,0.117303,33,45,45,5,5,3,300 -3,0.0270801,33,33,33,3,5,4,500 -3,0.0481635,39,33,39,4,4,3,100 -4,0.168909,69,57,51,69,4,4,4,4,100 +3,0.0270801,39,33,33,3,5,4,500 +3,0.0481635,39,33,51,4,4,3,100 +4,0.0628694,39,45,45,69,4,5,5,5,100 4,0.0655193,39,45,69,69,4,4,4,5,200 -4,0.120092,63,63,51,51,3,4,3,4,100 -4,0.071218,45,51,51,51,5,5,2,5,300 -4,0.239291,45,51,51,51,5,2,3,2,400 -5,0.200025,75,75,69,51,51,4,4,4,4,2,100 +4,0.0775514,33,33,51,51,3,4,3,5,100 +4,0.0712181,45,51,51,75,5,5,2,5,300 +4,0.239291,45,69,51,51,5,2,3,2,400 +5,0.177412,39,39,45,51,51,5,5,5,5,2,100 4,0.0479068,39,39,51,51,4,2,5,5,500 5,0.157281,39,33,33,45,45,5,5,2,4,5,500 5,0.0487246,39,39,45,51,51,5,3,3,5,5,400 -5,0.135929,39,33,33,45,45,5,4,5,5,2,500 +5,0.135929,39,33,33,45,51,5,4,5,5,2,500