slighlty faster
This commit is contained in:
@@ -195,9 +195,9 @@ struct PimsimSchedulerCostModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::optional<uint64_t> getStaticTripCount(scf::ForOp loop);
|
std::optional<uint64_t> getStaticTripCount(scf::ForOp loop);
|
||||||
[[maybe_unused]] Cost getOperationCost(Operation& op);
|
Cost getOperationCost(Operation& op);
|
||||||
|
|
||||||
[[maybe_unused]] Cost getRegionCost(Region& body) {
|
Cost getRegionCost(Region& body) {
|
||||||
Cost cost = 0;
|
Cost cost = 0;
|
||||||
for (Block& block : body)
|
for (Block& block : body)
|
||||||
for (Operation& op : block)
|
for (Operation& op : block)
|
||||||
@@ -205,7 +205,7 @@ std::optional<uint64_t> getStaticTripCount(scf::ForOp loop);
|
|||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] Cost getOperationCost(Operation& op) {
|
Cost getOperationCost(Operation& op) {
|
||||||
if (auto loop = dyn_cast<scf::ForOp>(&op)) {
|
if (auto loop = dyn_cast<scf::ForOp>(&op)) {
|
||||||
std::optional<uint64_t> tripCount = getStaticTripCount(loop);
|
std::optional<uint64_t> tripCount = getStaticTripCount(loop);
|
||||||
if (!tripCount)
|
if (!tripCount)
|
||||||
@@ -271,8 +271,7 @@ std::optional<uint64_t> getStaticTripCount(scf::ForOp loop) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Cost getComputeBodyCost(Region& body) {
|
Cost getComputeBodyCost(Region& body) {
|
||||||
constexpr Cost kOperationCost = 100;
|
return getRegionCost(body);
|
||||||
return checkedMultiply(static_cast<Cost>(countComputeBodyOperationInstances(body)), kOperationCost);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t countOperationInstances(Operation& op) {
|
uint64_t countOperationInstances(Operation& op) {
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <optional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "PeftScheduler.hpp"
|
#include "PeftScheduler.hpp"
|
||||||
@@ -133,6 +135,58 @@ void verifyOctTableSize(size_t nodeCount, size_t processorCount) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<CrossbarUsage> planCrossbarReservations(const ComputeGraph& graph,
|
||||||
|
size_t processorCount,
|
||||||
|
size_t crossbarCapacity,
|
||||||
|
const MeshModel& mesh) {
|
||||||
|
std::vector<size_t> weightedTasks;
|
||||||
|
for (size_t task = 0; task < graph.nodes.size(); ++task)
|
||||||
|
if (!graph.nodes[task].crossbarUsage.empty())
|
||||||
|
weightedTasks.push_back(task);
|
||||||
|
llvm::sort(weightedTasks, [&](size_t lhs, size_t rhs) {
|
||||||
|
if (graph.nodes[lhs].crossbarUsage.size() != graph.nodes[rhs].crossbarUsage.size())
|
||||||
|
return graph.nodes[lhs].crossbarUsage.size() > graph.nodes[rhs].crossbarUsage.size();
|
||||||
|
return graph.nodes[lhs].originalOrder < graph.nodes[rhs].originalOrder;
|
||||||
|
});
|
||||||
|
|
||||||
|
std::vector<CrossbarUsage> reservations(processorCount);
|
||||||
|
std::vector<Time> reservedLoad(processorCount, 0);
|
||||||
|
for (size_t task : weightedTasks) {
|
||||||
|
size_t bestProcessor = std::numeric_limits<size_t>::max();
|
||||||
|
using ReservationScore = std::tuple<Time, size_t, size_t, size_t>;
|
||||||
|
std::optional<ReservationScore> bestScore;
|
||||||
|
for (size_t processor = 0; processor < processorCount; ++processor) {
|
||||||
|
size_t crossbarUnion =
|
||||||
|
getCrossbarUnionSize(reservations[processor], graph.nodes[task].crossbarUsage);
|
||||||
|
if (crossbarUnion > crossbarCapacity)
|
||||||
|
continue;
|
||||||
|
size_t addedCrossbars = crossbarUnion - reservations[processor].size();
|
||||||
|
ReservationScore score {reservedLoad[processor],
|
||||||
|
addedCrossbars,
|
||||||
|
mesh.getCenterDistance(processor),
|
||||||
|
processor};
|
||||||
|
if (!bestScore || score < *bestScore) {
|
||||||
|
bestProcessor = processor;
|
||||||
|
bestScore = score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bestProcessor == std::numeric_limits<size_t>::max()) {
|
||||||
|
std::string message =
|
||||||
|
llvm::formatv("PEFT reservation planner: cannot place task {0} with {1} distinct weights in {2} "
|
||||||
|
"processors of capacity {3}",
|
||||||
|
graph.nodes[task].originalOrder,
|
||||||
|
graph.nodes[task].crossbarUsage.size(),
|
||||||
|
processorCount,
|
||||||
|
crossbarCapacity)
|
||||||
|
.str();
|
||||||
|
llvm::report_fatal_error(llvm::StringRef(message));
|
||||||
|
}
|
||||||
|
insertCrossbarWeights(reservations[bestProcessor], graph.nodes[task].crossbarUsage);
|
||||||
|
reservedLoad[bestProcessor] = addOrMax(reservedLoad[bestProcessor], graph.nodes[task].cost);
|
||||||
|
}
|
||||||
|
return reservations;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Time getPeftTransferTime(Time transferCost, size_t sourceProcessor, size_t targetProcessor, size_t processorCount) {
|
Time getPeftTransferTime(Time transferCost, size_t sourceProcessor, size_t targetProcessor, size_t processorCount) {
|
||||||
@@ -145,6 +199,8 @@ MergeScheduleResult runPeftScheduler(const ComputeGraph& graph, const PeftSchedu
|
|||||||
if (processorCount == 0)
|
if (processorCount == 0)
|
||||||
llvm::report_fatal_error("PEFT scheduler: processor count must be positive");
|
llvm::report_fatal_error("PEFT scheduler: processor count must be positive");
|
||||||
MeshModel mesh = MeshModel::infer(processorCount);
|
MeshModel mesh = MeshModel::infer(processorCount);
|
||||||
|
std::vector<CrossbarUsage> capacityReservations =
|
||||||
|
planCrossbarReservations(graph, processorCount, options.crossbarCapacity, mesh);
|
||||||
|
|
||||||
verifyOctTableSize(nodeCount, processorCount);
|
verifyOctTableSize(nodeCount, processorCount);
|
||||||
std::vector<std::vector<size_t>> reverseLevels = buildReverseLevels(graph);
|
std::vector<std::vector<size_t>> reverseLevels = buildReverseLevels(graph);
|
||||||
@@ -245,7 +301,8 @@ MergeScheduleResult runPeftScheduler(const ComputeGraph& graph, const PeftSchedu
|
|||||||
|
|
||||||
for (size_t processor = 0; processor < processorCount; ++processor) {
|
for (size_t processor = 0; processor < processorCount; ++processor) {
|
||||||
unsigned int overlapCount = countCrossbarOverlap(processorCrossbars[processor], graph.nodes[task].crossbarUsage);
|
unsigned int overlapCount = countCrossbarOverlap(processorCrossbars[processor], graph.nodes[task].crossbarUsage);
|
||||||
size_t crossbarUnion = getCrossbarUnionSize(processorCrossbars[processor], graph.nodes[task].crossbarUsage);
|
size_t crossbarUnion =
|
||||||
|
getCrossbarUnionSize(capacityReservations[processor], graph.nodes[task].crossbarUsage);
|
||||||
smallestCrossbarUnion = std::min(smallestCrossbarUnion, crossbarUnion);
|
smallestCrossbarUnion = std::min(smallestCrossbarUnion, crossbarUnion);
|
||||||
if (!graph.nodes[task].crossbarUsage.empty() && crossbarUnion > options.crossbarCapacity) {
|
if (!graph.nodes[task].crossbarUsage.empty() && crossbarUnion > options.crossbarCapacity) {
|
||||||
crossbarRejected = true;
|
crossbarRejected = true;
|
||||||
@@ -337,6 +394,7 @@ MergeScheduleResult runPeftScheduler(const ComputeGraph& graph, const PeftSchedu
|
|||||||
schedules[task] = {bestProcessor, bestEst, bestEft};
|
schedules[task] = {bestProcessor, bestEst, bestEft};
|
||||||
scheduled[task] = true;
|
scheduled[task] = true;
|
||||||
++scheduledCount;
|
++scheduledCount;
|
||||||
|
insertCrossbarWeights(capacityReservations[bestProcessor], graph.nodes[task].crossbarUsage);
|
||||||
insertCrossbarWeights(processorCrossbars[bestProcessor], graph.nodes[task].crossbarUsage);
|
insertCrossbarWeights(processorCrossbars[bestProcessor], graph.nodes[task].crossbarUsage);
|
||||||
|
|
||||||
// 3. CRITICAL FIX: Topological Append
|
// 3. CRITICAL FIX: Topological Append
|
||||||
|
|||||||
Reference in New Issue
Block a user