Topological initialization
Some checks failed
Validate Operations / validate-operations (push) Failing after 27m23s
Some checks failed
Validate Operations / validate-operations (push) Failing after 27m23s
This commit is contained in:
318
src/PIM/Common/LabeledList.hpp
Normal file
318
src/PIM/Common/LabeledList.hpp
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include "llvm/ADT/ilist_node.h"
|
||||||
|
#include "llvm/ADT/simple_ilist.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <iterator>
|
||||||
|
#include <limits>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace onnx_mlir {
|
||||||
|
|
||||||
|
template <typename NodeT>
|
||||||
|
class LabeledList;
|
||||||
|
|
||||||
|
template <typename NodeT>
|
||||||
|
class LabeledListNode : public llvm::ilist_node<NodeT> {
|
||||||
|
friend class LabeledList<NodeT>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Label = uint64_t;
|
||||||
|
|
||||||
|
LabeledListNode() = default;
|
||||||
|
LabeledListNode(const LabeledListNode&) = delete;
|
||||||
|
LabeledListNode(LabeledListNode&&) = default;
|
||||||
|
LabeledListNode& operator=(LabeledListNode&&) = delete;
|
||||||
|
|
||||||
|
~LabeledListNode() { assert(owner_ == nullptr && "destroying a linked LabeledListNode"); }
|
||||||
|
|
||||||
|
bool isLinked() const { return owner_ != nullptr; }
|
||||||
|
Label getOrderLabel() const { return label; }
|
||||||
|
|
||||||
|
friend bool operator<(const LabeledListNode& lft, const LabeledListNode& rgt){
|
||||||
|
return lft.label < rgt.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const void* owner_ = nullptr;
|
||||||
|
Label label = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename NodeT>
|
||||||
|
class LabeledList {
|
||||||
|
|
||||||
|
using Label = typename NodeT::Label;
|
||||||
|
|
||||||
|
static constexpr Label kLowerSentinel = 0;
|
||||||
|
static constexpr Label kUpperSentinel = std::numeric_limits<Label>::max();
|
||||||
|
static constexpr Label kRelabelGap = 2;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using List = llvm::simple_ilist<NodeT>;
|
||||||
|
using Iterator = typename List::iterator;
|
||||||
|
using RIterator = typename List::reverse_iterator;
|
||||||
|
using ConstIterator = typename List::const_iterator;
|
||||||
|
|
||||||
|
LabeledList() = default;
|
||||||
|
LabeledList(const LabeledList&) = delete;
|
||||||
|
LabeledList& operator=(const LabeledList&) = delete;
|
||||||
|
LabeledList(LabeledList&&) = delete;
|
||||||
|
LabeledList& operator=(LabeledList&&) = delete;
|
||||||
|
|
||||||
|
~LabeledList() { clear(); }
|
||||||
|
|
||||||
|
bool empty() const { return size_ == 0; }
|
||||||
|
size_t size() const { return size_; }
|
||||||
|
|
||||||
|
NodeT* front() { return empty() ? nullptr : &nodes_.front(); }
|
||||||
|
const NodeT* front() const { return empty() ? nullptr : &nodes_.front(); }
|
||||||
|
|
||||||
|
NodeT* back() { return empty() ? nullptr : &nodes_.back(); }
|
||||||
|
const NodeT* back() const { return empty() ? nullptr : &nodes_.back(); }
|
||||||
|
|
||||||
|
static NodeT* previous(NodeT* node) {
|
||||||
|
if (!node || !owner(node))
|
||||||
|
return nullptr;
|
||||||
|
auto* list = owner(node);
|
||||||
|
auto it = node->getIterator();
|
||||||
|
if (it == list->nodes_.begin())
|
||||||
|
return nullptr;
|
||||||
|
return *std::prev(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const NodeT* previous(const NodeT* node) {
|
||||||
|
if (!node || !owner(node))
|
||||||
|
return nullptr;
|
||||||
|
const auto* list = owner(node);
|
||||||
|
auto it = node->getIterator();
|
||||||
|
if (it == list->nodes_.begin())
|
||||||
|
return nullptr;
|
||||||
|
return *std::prev(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NodeT* next(NodeT* node) {
|
||||||
|
if (!node || !owner(node))
|
||||||
|
return nullptr;
|
||||||
|
auto* list = owner(node);
|
||||||
|
auto it = std::next(node->getIterator());
|
||||||
|
if (it == list->nodes_.end())
|
||||||
|
return nullptr;
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const NodeT* next(const NodeT* node) {
|
||||||
|
if (!node || !owner(node))
|
||||||
|
return nullptr;
|
||||||
|
const auto* list = owner(node);
|
||||||
|
auto it = std::next(node->getIterator());
|
||||||
|
if (it == list->nodes_.end())
|
||||||
|
return nullptr;
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const NodeT* node) const { return node && node->owner_ == this; }
|
||||||
|
|
||||||
|
Label getOrderLabel(const NodeT* node) const {
|
||||||
|
assert(contains(node) && "node must belong to this list");
|
||||||
|
return node->label_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool comesBefore(const NodeT* lhs, const NodeT* rhs) const {
|
||||||
|
assert(contains(lhs) && contains(rhs) && "nodes must belong to this list");
|
||||||
|
return lhs->label_ < rhs->label_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pushFront(NodeT* node) { insertBefore(front(), node); }
|
||||||
|
|
||||||
|
void pushBack(NodeT* node) { insertBefore(nullptr, node); }
|
||||||
|
|
||||||
|
void insertBefore(NodeT* nextNode, NodeT* node) {
|
||||||
|
assert(node && "cannot insert a null node");
|
||||||
|
assert(!node->owner_ && "node is already linked");
|
||||||
|
assert(nextNode == nullptr || contains(nextNode));
|
||||||
|
|
||||||
|
Iterator nextIt = nextNode ? getIteratorFor(nextNode) : nodes_.end();
|
||||||
|
nodes_.insert(nextIt, *node);
|
||||||
|
node->owner_ = this;
|
||||||
|
++size_;
|
||||||
|
assignLabel(getIteratorFor(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertAfter(NodeT* prevNode, NodeT* node) {
|
||||||
|
assert(prevNode == nullptr || contains(prevNode));
|
||||||
|
if (prevNode == nullptr)
|
||||||
|
insertBefore(front(), node);
|
||||||
|
else
|
||||||
|
insertBefore(next(prevNode), node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(NodeT* node) {
|
||||||
|
assert(contains(node) && "node must belong to this list");
|
||||||
|
nodes_.remove(*node);
|
||||||
|
node->owner_ = nullptr;
|
||||||
|
node->label_ = 0;
|
||||||
|
--size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveBefore(NodeT* node, NodeT* nextNode) {
|
||||||
|
assert(contains(node) && "node must belong to this list");
|
||||||
|
assert(nextNode == nullptr || contains(nextNode));
|
||||||
|
|
||||||
|
Iterator nodeIt = getIteratorFor(node);
|
||||||
|
Iterator nextIt = nextNode ? getIteratorFor(nextNode) : nodes_.end();
|
||||||
|
if (nodeIt == nextIt || std::next(nodeIt) == nextIt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nodes_.splice(nextIt, nodes_, nodeIt);
|
||||||
|
assignLabel(getIteratorFor(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveAfter(NodeT* node, NodeT* prevNode) {
|
||||||
|
assert(contains(node) && "node must belong to this list");
|
||||||
|
assert(prevNode == nullptr || contains(prevNode));
|
||||||
|
|
||||||
|
Iterator nextIt = prevNode ? std::next(getIteratorFor(prevNode)) : nodes_.begin();
|
||||||
|
if (getIteratorFor(node) == nextIt)
|
||||||
|
return;
|
||||||
|
moveBefore(node, nextIt == nodes_.end() ? nullptr : &*nextIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
while (!nodes_.empty()) {
|
||||||
|
NodeT* node = &nodes_.front();
|
||||||
|
node->owner_ = nullptr;
|
||||||
|
node->label = 0;
|
||||||
|
nodes_.remove(*node);
|
||||||
|
}
|
||||||
|
size_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator begin() { return nodes_.begin(); }
|
||||||
|
|
||||||
|
Iterator end() { return nodes_.end(); }
|
||||||
|
|
||||||
|
RIterator rbegin() { return nodes_.rbegin(); }
|
||||||
|
RIterator rend() { return nodes_.rend(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const LabeledList* owner(const NodeT* node) { return node->owner_; }
|
||||||
|
static LabeledList* owner(NodeT* node) { return node->owner_; }
|
||||||
|
|
||||||
|
static Label lowerLabel(const NodeT* node) { return node ? node->label : kLowerSentinel; }
|
||||||
|
static Label upperLabel(const NodeT* node) { return node ? node->label : kUpperSentinel; }
|
||||||
|
|
||||||
|
static Label labelGap(Label lower, Label upper) {
|
||||||
|
assert(lower < upper && "labels must be strictly ordered");
|
||||||
|
return upper - lower;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hasMidpoint(Label lower, Label upper) { return labelGap(lower, upper) > 1; }
|
||||||
|
|
||||||
|
static bool hasRelabelSlack(Label lower, Label upper, size_t nodeCount) {
|
||||||
|
Label gap = labelGap(lower, upper);
|
||||||
|
return gap / static_cast<Label>(nodeCount + 1) >= kRelabelGap;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator getIteratorFor(NodeT* node) { return node->getIterator(); }
|
||||||
|
ConstIterator getiteratorFor(const NodeT* node) const { return node->getIterator(); }
|
||||||
|
|
||||||
|
NodeT* previousNode(Iterator it) {
|
||||||
|
if (it == nodes_.begin())
|
||||||
|
return nullptr;
|
||||||
|
return &*std::prev(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodeT* previousNode(ConstIterator it) const {
|
||||||
|
if (it == nodes_.begin())
|
||||||
|
return nullptr;
|
||||||
|
return &*std::prev(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeT* nextNode(Iterator it) {
|
||||||
|
++it;
|
||||||
|
if (it == nodes_.end())
|
||||||
|
return nullptr;
|
||||||
|
return &*it;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodeT* nextNode(ConstIterator it) const {
|
||||||
|
++it;
|
||||||
|
if (it == nodes_.end())
|
||||||
|
return nullptr;
|
||||||
|
return &*it;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assignLabel(Iterator it) {
|
||||||
|
Label lower = lowerLabel(previousNode(it));
|
||||||
|
Label upper = upperLabel(nextNode(it));
|
||||||
|
if (hasMidpoint(lower, upper)) {
|
||||||
|
(*it).label = lower + static_cast<Label>(labelGap(lower, upper) / 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
relabelAround(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void relabelAround(Iterator center) {
|
||||||
|
size_t targetCount = 1;
|
||||||
|
while (true) {
|
||||||
|
Iterator left = center;
|
||||||
|
Iterator right = center;
|
||||||
|
size_t actualCount = 1;
|
||||||
|
expandWindow(center, targetCount, left, right, actualCount);
|
||||||
|
|
||||||
|
Label lower = lowerLabel(previousNode(left));
|
||||||
|
Label upper = upperLabel(nextNode(right));
|
||||||
|
if (hasRelabelSlack(lower, upper, actualCount)) {
|
||||||
|
relabelWindow(left, actualCount, lower, upper);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left == nodes_.begin() && nextNode(right) == nullptr) {
|
||||||
|
assert(hasRelabelSlack(lower, upper, actualCount) && "label space exhausted");
|
||||||
|
relabelWindow(left, actualCount, lower, upper);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetCount *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void expandWindow(Iterator center, size_t targetCount, Iterator& left, Iterator& right, size_t& actualCount) {
|
||||||
|
left = center;
|
||||||
|
right = center;
|
||||||
|
actualCount = 1;
|
||||||
|
|
||||||
|
while (actualCount < targetCount && (left != nodes_.begin() || nextNode(right) != nullptr)) {
|
||||||
|
if (left != nodes_.begin()) {
|
||||||
|
--left;
|
||||||
|
++actualCount;
|
||||||
|
if (actualCount == targetCount)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nextNode(right) != nullptr) {
|
||||||
|
++right;
|
||||||
|
++actualCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void relabelWindow(Iterator left, size_t nodeCount, Label lower, Label upper) {
|
||||||
|
assert(nodeCount > 0 && "relabel window must not be empty");
|
||||||
|
Label step = labelGap(lower, upper) / static_cast<Label>(nodeCount + 1);
|
||||||
|
assert(step >= 1 && "relabel step must be positive");
|
||||||
|
|
||||||
|
Iterator it = left;
|
||||||
|
for (size_t index = 1; index <= nodeCount; ++index) {
|
||||||
|
(*it).label = lower + step * index;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List nodes_;
|
||||||
|
size_t size_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace onnx_mlir
|
||||||
@@ -54,7 +54,6 @@ DCPAnalysisResult DCPAnalysis::runAnalysis() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphDCP graphDCP(spatWeightedComputes, edges);
|
GraphDCP graphDCP(spatWeightedComputes, edges);
|
||||||
graphDCP.DCP();
|
graphDCP.DCP();
|
||||||
return graphDCP.getResult();
|
return graphDCP.getResult();
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -5,16 +8,17 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "src/Accelerators/PIM/Common/PimCommon.hpp"
|
|
||||||
#include "DCPAnalysis.hpp"
|
#include "DCPAnalysis.hpp"
|
||||||
#include "Graph.hpp"
|
#include "Graph.hpp"
|
||||||
#include "Task.hpp"
|
#include "Task.hpp"
|
||||||
#include "UniqueWorklist.hpp"
|
#include "UniqueWorklist.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
#include "src/Accelerators/PIM/Common/PimCommon.hpp"
|
||||||
|
|
||||||
std::optional<Edge_pair> addEdge(TaskDCP* parent, TaskDCP* child, Weight_t weight) {
|
std::optional<DoubleEdge> addEdge(TaskDCP* parent, TaskDCP* child, Weight_t weight) {
|
||||||
auto old_child = parent->addChild(child, weight);
|
auto old_child = parent->addChild(child, weight);
|
||||||
auto old_parent = child->addParent(parent, weight);
|
auto old_parent = child->addParent(parent, weight);
|
||||||
assert(old_child.has_value() == old_parent.has_value() && "The edge must be present in both element");
|
assert(old_child.has_value() == old_parent.has_value() && "The edge must be present in both element");
|
||||||
@@ -43,26 +47,34 @@ int getTranferCost(TaskDCP* parent, TaskDCP* child) {
|
|||||||
return child_position->second;
|
return child_position->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<std::optional<Edge_pair>, 2> GraphDCP::insertTaskInCPU(CPU cpu, TaskDCP* task, size_t position) {
|
TaskInsertion GraphDCP::insertTaskInCPU(CPU cpu, TaskDCP* task, size_t position) {
|
||||||
std::array<std::optional<Edge_pair>, 2> ret;
|
TaskInsertion ret;
|
||||||
task->setCPU(cpu);
|
task->setCPU(cpu);
|
||||||
task->setWeight(task->computeWeight(this, cpu));
|
task->setWeight(task->computeWeight(this, cpu));
|
||||||
auto& list = mapCPUTasks[cpu];
|
auto& tasksInCPU = mapCPUTasks[cpu];
|
||||||
unsigned int total_size = list.size();
|
unsigned int numCPUTask = tasksInCPU.size();
|
||||||
assert(position <= total_size && "Inserting in a not valid position");
|
assert(position <= numCPUTask && "Inserting in a not valid position");
|
||||||
auto inserted_point = list.begin();
|
auto insertedPoint = tasksInCPU.insert(std::next(tasksInCPU.begin(), position), task);
|
||||||
inserted_point = list.insert(std::next(list.begin(), position), task);
|
ret.oldTopologicalPosition = std::next(task->getTopologicalPosition());
|
||||||
|
ret.cpuModified = cpu;
|
||||||
|
ret.taskInserted = task;
|
||||||
|
ret.graph = this;
|
||||||
|
|
||||||
if (inserted_point != list.begin()) {
|
if (insertedPoint != tasksInCPU.begin()) {
|
||||||
auto precedent_point = std::prev(inserted_point, 1);
|
auto precedentPoint = std::prev(insertedPoint, 1);
|
||||||
auto old_edge = addEdge(*precedent_point, *inserted_point, 0);
|
auto oldEdge = addEdge(*precedentPoint, *insertedPoint, 0);
|
||||||
ret[0] = old_edge;
|
ret.beforeNode = oldEdge;
|
||||||
|
|
||||||
|
if (*task < **insertedPoint)
|
||||||
|
topologicalMoveAfter(task, *precedentPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::next(inserted_point) != list.end()) {
|
if (std::next(insertedPoint) != tasksInCPU.end()) {
|
||||||
auto next_point = std::next(inserted_point, 1);
|
auto nextPoint = std::next(insertedPoint, 1);
|
||||||
auto old_edge = addEdge(*inserted_point, *next_point, 0);
|
auto oldEdge = addEdge(*insertedPoint, *nextPoint, 0);
|
||||||
ret[1] = old_edge;
|
ret.afterNode = oldEdge;
|
||||||
|
if (**insertedPoint < *task)
|
||||||
|
topologicalMoveBefore(task, *nextPoint);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -88,7 +100,7 @@ void GraphDCP::removeTaskFromCPU(CPU cpu, TaskDCP* task) {
|
|||||||
std::vector<TaskDCP*> GraphDCP::getRoots() {
|
std::vector<TaskDCP*> GraphDCP::getRoots() {
|
||||||
std::vector<TaskDCP*> tmp;
|
std::vector<TaskDCP*> tmp;
|
||||||
for (auto& task : nodes)
|
for (auto& task : nodes)
|
||||||
if (!task.hasParent())
|
if (!task.hasParents())
|
||||||
tmp.push_back(&task);
|
tmp.push_back(&task);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -96,47 +108,33 @@ std::vector<TaskDCP*> GraphDCP::getRoots() {
|
|||||||
void GraphDCP::initAEST() {
|
void GraphDCP::initAEST() {
|
||||||
UniqueWorkList<std::deque<TaskDCP*>> worklists(getRoots());
|
UniqueWorkList<std::deque<TaskDCP*>> worklists(getRoots());
|
||||||
|
|
||||||
while (!worklists.empty()) {
|
auto& worklist = topologicalOrder;
|
||||||
TaskDCP& task = *worklists.front();
|
int max_dcpl = 0;
|
||||||
bool modified = true;
|
for (auto& task : worklist) {
|
||||||
while (modified) {
|
|
||||||
modified = false;
|
|
||||||
for (auto& child : task.childs) {
|
|
||||||
if (worklists.allElementContained(
|
|
||||||
child.first->parents.begin(), child.first->parents.end(), [](Edge_t edge) { return edge.first; })) {
|
|
||||||
modified |= worklists.push_back(child.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int max_parent_aest = 0;
|
int max_parent_aest = 0;
|
||||||
for (auto& parent : task.parents) {
|
for (Edge_t parentEdge : task.parents) {
|
||||||
max_parent_aest = std::max(
|
max_parent_aest =
|
||||||
parent.first->getAEST() + parent.first->getWeight() + getTranferCost(parent.first, &task), max_parent_aest);
|
std::max(parentEdge.first->getAEST() + parentEdge.first->getWeight() + getTranferCost(parentEdge.first, &task),
|
||||||
|
max_parent_aest);
|
||||||
}
|
}
|
||||||
task.setAEST(max_parent_aest);
|
task.setAEST(max_parent_aest);
|
||||||
worklists.pop_front();
|
max_dcpl = std::max(max_parent_aest + task.getWeight(), max_dcpl);
|
||||||
}
|
}
|
||||||
|
DCPL = max_dcpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GraphDCP::computeAEST(TaskDCP* task, CPU cpu) {
|
int GraphDCP::computeAEST(TaskDCP* task, CPU cpu) {
|
||||||
int max_parent_aest = 0;
|
int max_parent_aest = 0;
|
||||||
for (auto& parent : task->parents) {
|
for (Edge_t parentEdge : task->parents) {
|
||||||
int transfer_cost = 0;
|
int transfer_cost = 0;
|
||||||
if (!(parent.first->isScheduled() && cpu == *parent.first->getCPU()))
|
if (!(parentEdge.first->isScheduled() && cpu == *parentEdge.first->getCPU()))
|
||||||
transfer_cost = getTranferCost(parent.first, task);
|
transfer_cost = getTranferCost(parentEdge.first, task);
|
||||||
|
max_parent_aest =
|
||||||
max_parent_aest = std::max(parent.first->getAEST() + parent.first->getWeight() + transfer_cost, max_parent_aest);
|
std::max(parentEdge.first->getAEST() + parentEdge.first->getWeight() + transfer_cost, max_parent_aest);
|
||||||
}
|
}
|
||||||
return max_parent_aest;
|
return max_parent_aest;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GraphDCP::initDCPL() {
|
|
||||||
int max_aest = 0;
|
|
||||||
for (auto& node : nodes)
|
|
||||||
max_aest = std::max(node.getAEST() + node.getWeight(), max_aest);
|
|
||||||
return max_aest;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GraphDCP::computeDCPL(TaskDCP* task, CPU cpu) {
|
int GraphDCP::computeDCPL(TaskDCP* task, CPU cpu) {
|
||||||
int max_aest = 0;
|
int max_aest = 0;
|
||||||
for (auto& node : nodes)
|
for (auto& node : nodes)
|
||||||
@@ -148,59 +146,26 @@ int GraphDCP::computeDCPL(TaskDCP* task, CPU cpu) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GraphDCP::initALST() {
|
void GraphDCP::initALST() {
|
||||||
int dcpl = initDCPL();
|
int dcpl = getDCPL();
|
||||||
std::vector<TaskDCP*> roots = getRoots();
|
auto& worklists = topologicalOrder;
|
||||||
UniqueWorkList<std::vector<TaskDCP*>> worklists(roots);
|
|
||||||
worklists.reserve(nodes.size());
|
|
||||||
size_t i = 0;
|
|
||||||
while (i != worklists.size()) {
|
|
||||||
bool modified = true;
|
|
||||||
while (modified) {
|
|
||||||
modified = false;
|
|
||||||
for (auto& child : worklists.at(i)->childs) {
|
|
||||||
if (worklists.allElementContained(
|
|
||||||
child.first->parents.begin(), child.first->parents.end(), [](Edge_t edge) { return edge.first; })) {
|
|
||||||
modified |= worklists.push_back(child.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!worklists.empty()) {
|
for (TaskDCP& node : llvm::reverse(worklists)) {
|
||||||
TaskDCP& node = *worklists.back();
|
|
||||||
int min_alst = INT_MAX;
|
int min_alst = INT_MAX;
|
||||||
if (!node.hasChilds())
|
if (!node.hasChilds())
|
||||||
min_alst = dcpl - node.getWeight();
|
min_alst = dcpl - node.getWeight();
|
||||||
for (auto child : node.childs)
|
for (Edge_t childEdge : node.childs)
|
||||||
min_alst = std::min(min_alst, child.first->getALST() - node.getWeight() - getTranferCost(&node, child.first));
|
min_alst =
|
||||||
|
std::min(min_alst, childEdge.first->getALST() - node.getWeight() - getTranferCost(&node, childEdge.first));
|
||||||
node.setALST(min_alst);
|
node.setALST(min_alst);
|
||||||
worklists.pop_back();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<TaskDCP*, int> GraphDCP::computeALST(TaskDCP* task, CPU cpu) {
|
llvm::DenseMap<TaskDCP*, int> GraphDCP::computeALST(TaskDCP* task, CPU cpu) {
|
||||||
int dcpl = computeDCPL(task, cpu);
|
int dcpl = computeDCPL(task, cpu);
|
||||||
std::unordered_map<TaskDCP*, int> temp_ALST;
|
llvm::DenseMap<TaskDCP*, int> temp_ALST;
|
||||||
UniqueWorkList<std::vector<TaskDCP*>> worklists(getRoots());
|
|
||||||
size_t i = 0;
|
|
||||||
while (i != worklists.size()) {
|
|
||||||
|
|
||||||
bool modified = true;
|
auto& worklists = topologicalOrder;
|
||||||
while (modified) {
|
for (TaskDCP& node : llvm::reverse(worklists)) {
|
||||||
modified = false;
|
|
||||||
for (auto& child : worklists.at(i)->childs) {
|
|
||||||
if (worklists.allElementContained(
|
|
||||||
child.first->parents.begin(), child.first->parents.end(), [](Edge_t edge) { return edge.first; })) {
|
|
||||||
modified |= worklists.push_back(child.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!worklists.empty()) {
|
|
||||||
TaskDCP& node = *worklists.back();
|
|
||||||
int min_alst = INT_MAX;
|
int min_alst = INT_MAX;
|
||||||
if (!node.hasChilds()) {
|
if (!node.hasChilds()) {
|
||||||
if (&node != task)
|
if (&node != task)
|
||||||
@@ -209,14 +174,13 @@ std::unordered_map<TaskDCP*, int> GraphDCP::computeALST(TaskDCP* task, CPU cpu)
|
|||||||
min_alst = dcpl - node.computeWeight(this, cpu);
|
min_alst = dcpl - node.computeWeight(this, cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto child : node.childs) {
|
for (Edge_t childEdge : node.childs) {
|
||||||
int transfer_cost = getTranferCost(&node, child.first);
|
int transfer_cost = getTranferCost(&node, childEdge.first);
|
||||||
if (&node == task && child.first->isScheduled() && cpu == *child.first->getCPU())
|
if (&node == task && childEdge.first->isScheduled() && cpu == *childEdge.first->getCPU())
|
||||||
transfer_cost = 0;
|
transfer_cost = 0;
|
||||||
min_alst = std::min(min_alst, temp_ALST[child.first] - node.getWeight() - transfer_cost);
|
min_alst = std::min(min_alst, temp_ALST[childEdge.first] - node.getWeight() - transfer_cost);
|
||||||
}
|
}
|
||||||
temp_ALST[&node] = min_alst;
|
temp_ALST[&node] = min_alst;
|
||||||
worklists.pop_back();
|
|
||||||
}
|
}
|
||||||
return temp_ALST;
|
return temp_ALST;
|
||||||
}
|
}
|
||||||
@@ -253,6 +217,124 @@ TaskDCP* GraphDCP::findCandidate(std::vector<TaskDCP*> nodes) {
|
|||||||
return *best_node;
|
return *best_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphDCP::initTopological() {
|
||||||
|
UniqueWorkList<std::vector<TaskDCP*>> worklists(getRoots());
|
||||||
|
long long flag = getUniqueFlag();
|
||||||
|
for (auto root : worklists)
|
||||||
|
root->setFlag(flag);
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (i != worklists.size()) {
|
||||||
|
for (auto& child : worklists.at(i)->childs) {
|
||||||
|
TaskDCP* childTask = child.first;
|
||||||
|
if (std::all_of(childTask->parents.begin(), childTask->parents.end(), [flag](Edge_t edge) {
|
||||||
|
return edge.first->getFlag() == flag;
|
||||||
|
})) {
|
||||||
|
worklists.push_back(childTask);
|
||||||
|
childTask->setFlag(flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto task : worklists)
|
||||||
|
topologicalOrder.pushBack(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphDCP::topologicalMoveAfter(TaskDCP* task, TaskDCP* pivotPoint) {
|
||||||
|
auto moveChildAfterMe = [this](TaskDCP* origTask) -> void {
|
||||||
|
auto cmp = [](Edge_t lft, Edge_t rgt) { return *rgt.first < *lft.first; };
|
||||||
|
TaskDCP* insertionPoint = origTask;
|
||||||
|
std::vector<Edge_t>& childEdges = origTask->childs;
|
||||||
|
std::vector<TaskDCP*> worklist;
|
||||||
|
worklist.push_back(origTask);
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < worklist.size()) {
|
||||||
|
auto task = worklist[i];
|
||||||
|
// build min heap Complexity 3N
|
||||||
|
std::make_heap(childEdges.begin(), childEdges.end(), cmp);
|
||||||
|
auto lastPoppedIter = childEdges.end();
|
||||||
|
bool foundChildInOrder = false;
|
||||||
|
while (lastPoppedIter != childEdges.begin()) {
|
||||||
|
std::pop_heap(childEdges.begin(), lastPoppedIter, cmp);
|
||||||
|
lastPoppedIter = std::prev(lastPoppedIter, 1);
|
||||||
|
auto currentChild = (*lastPoppedIter).first;
|
||||||
|
if (*currentChild < *task) {
|
||||||
|
topologicalOrder.moveAfter(currentChild, insertionPoint);
|
||||||
|
insertionPoint = currentChild;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foundChildInOrder = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundChildInOrder)
|
||||||
|
lastPoppedIter++;
|
||||||
|
|
||||||
|
for (auto it = lastPoppedIter; it != childEdges.end(); ++it)
|
||||||
|
if (it->first->hasChilds())
|
||||||
|
worklist.push_back(it->first);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!(*task < *pivotPoint)) {
|
||||||
|
return;
|
||||||
|
topologicalOrder.moveAfter(task, pivotPoint);
|
||||||
|
if (task->hasChilds())
|
||||||
|
moveChildAfterMe(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphDCP::topologicalMoveBefore(TaskDCP* task, TaskDCP* pivotPoint) {
|
||||||
|
|
||||||
|
auto moveParentBeforeMe = [this](TaskDCP* origTask) -> void {
|
||||||
|
auto cmp = [](Edge_t lft, Edge_t rgt) { return *lft.first < *rgt.first; };
|
||||||
|
TaskDCP* insertionPoint = origTask;
|
||||||
|
std::vector<Edge_t>& parentEdges = origTask->parents;
|
||||||
|
std::vector<TaskDCP*> worklist;
|
||||||
|
worklist.push_back(origTask);
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < worklist.size()) {
|
||||||
|
auto task = worklist[i];
|
||||||
|
// build max heap Complexity 3N
|
||||||
|
std::make_heap(parentEdges.begin(), parentEdges.end(), cmp);
|
||||||
|
auto lastPoppedIter = parentEdges.end();
|
||||||
|
bool foundParentInOrder = false;
|
||||||
|
while (lastPoppedIter != parentEdges.begin()) {
|
||||||
|
std::pop_heap(parentEdges.begin(), lastPoppedIter, cmp);
|
||||||
|
lastPoppedIter = std::prev(lastPoppedIter, 1);
|
||||||
|
auto currentParent = (*lastPoppedIter).first;
|
||||||
|
if (*currentParent < *task) {
|
||||||
|
topologicalOrder.moveBefore(currentParent, insertionPoint);
|
||||||
|
insertionPoint = currentParent;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foundParentInOrder = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundParentInOrder)
|
||||||
|
lastPoppedIter++;
|
||||||
|
|
||||||
|
for (auto it = lastPoppedIter; it != parentEdges.end(); ++it)
|
||||||
|
if (it->first->hasParents())
|
||||||
|
worklist.push_back(it->first);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!(*task < *pivotPoint)) {
|
||||||
|
return;
|
||||||
|
topologicalOrder.moveBefore(task, pivotPoint);
|
||||||
|
if (task->hasParents())
|
||||||
|
moveParentBeforeMe(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GraphDCP::FindSlot GraphDCP::findSlot(TaskDCP* candidate, CPU cpu, bool push) {
|
GraphDCP::FindSlot GraphDCP::findSlot(TaskDCP* candidate, CPU cpu, bool push) {
|
||||||
int aest_on_cpu = computeAEST(candidate, cpu);
|
int aest_on_cpu = computeAEST(candidate, cpu);
|
||||||
auto tmp_ALST = computeALST(candidate, cpu);
|
auto tmp_ALST = computeALST(candidate, cpu);
|
||||||
@@ -353,8 +435,8 @@ void GraphDCP::selectProcessor(TaskDCP* candidate, bool push) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (candidate->hasChilds()) {
|
else if (candidate->hasChilds()) {
|
||||||
auto dcpl = initDCPL();
|
auto dcpl = getDCPL();
|
||||||
auto old_edges = insertTaskInCPU(current_cpu, candidate, slot.index);
|
auto taskInsertion = insertTaskInCPU(current_cpu, candidate, slot.index);
|
||||||
initAEST();
|
initAEST();
|
||||||
initALST();
|
initALST();
|
||||||
Edge_t smallest_child {nullptr, 0};
|
Edge_t smallest_child {nullptr, 0};
|
||||||
@@ -377,15 +459,9 @@ void GraphDCP::selectProcessor(TaskDCP* candidate, bool push) {
|
|||||||
best_composite = slot.aest + child_slot.aest;
|
best_composite = slot.aest + child_slot.aest;
|
||||||
best_slot = slot;
|
best_slot = slot;
|
||||||
}
|
}
|
||||||
removeTaskFromCPU(current_cpu, candidate);
|
taskInsertion.rollBack();
|
||||||
initAEST();
|
initAEST();
|
||||||
initALST();
|
initALST();
|
||||||
for (auto opt_edge : old_edges) {
|
|
||||||
if (opt_edge.has_value()) {
|
|
||||||
auto double_edge = *opt_edge;
|
|
||||||
addEdge(double_edge.first.first, double_edge.second.first, double_edge.first.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (best_process == -1) {
|
if (best_process == -1) {
|
||||||
@@ -398,6 +474,7 @@ void GraphDCP::selectProcessor(TaskDCP* candidate, bool push) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GraphDCP::DCP() {
|
void GraphDCP::DCP() {
|
||||||
|
initTopological();
|
||||||
initAEST();
|
initAEST();
|
||||||
initALST();
|
initALST();
|
||||||
to_dot();
|
to_dot();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -11,7 +12,7 @@
|
|||||||
#include "Task.hpp"
|
#include "Task.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
|
||||||
std::optional<Edge_pair> addEdge(TaskDCP* parent, TaskDCP* child, Weight_t weight);
|
std::optional<DoubleEdge> addEdge(TaskDCP* parent, TaskDCP* child, Weight_t weight);
|
||||||
void removeEdge(TaskDCP* parent, TaskDCP* child);
|
void removeEdge(TaskDCP* parent, TaskDCP* child);
|
||||||
int getTranferCost(TaskDCP* parent, TaskDCP* child);
|
int getTranferCost(TaskDCP* parent, TaskDCP* child);
|
||||||
|
|
||||||
@@ -23,20 +24,32 @@ class GraphDCP {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<TaskDCP> nodes;
|
std::vector<TaskDCP> nodes;
|
||||||
|
onnx_mlir::LabeledList<TaskDCP> topologicalOrder;
|
||||||
std::unordered_map<CPU, std::list<TaskDCP*>> mapCPUTasks;
|
std::unordered_map<CPU, std::list<TaskDCP*>> mapCPUTasks;
|
||||||
CPU last_cpu = 0;
|
CPU last_cpu = 0;
|
||||||
|
long long flag = 1;
|
||||||
|
int DCPL;
|
||||||
|
|
||||||
std::array<std::optional<Edge_pair>, 2> insertTaskInCPU(CPU cpu, TaskDCP* task, size_t position);
|
TaskInsertion insertTaskInCPU(CPU cpu, TaskDCP* task, size_t position);
|
||||||
void removeTaskFromCPU(CPU cpu, TaskDCP* task);
|
void removeTaskFromCPU(CPU cpu, TaskDCP* task);
|
||||||
|
|
||||||
std::vector<TaskDCP*> getRoots();
|
std::vector<TaskDCP*> getRoots();
|
||||||
|
|
||||||
|
long long getUniqueFlag() {return flag++;};
|
||||||
|
|
||||||
void initAEST();
|
void initAEST();
|
||||||
int computeAEST(TaskDCP* task, CPU cpu);
|
|
||||||
int initDCPL();
|
int initDCPL();
|
||||||
int computeDCPL(TaskDCP* task, CPU cpu);
|
|
||||||
void initALST();
|
void initALST();
|
||||||
std::unordered_map<TaskDCP*, int> computeALST(TaskDCP* task, CPU cpu);
|
|
||||||
|
int computeAEST(TaskDCP* task, CPU cpu);
|
||||||
|
int computeDCPL(TaskDCP* task, CPU cpu);
|
||||||
|
int getDCPL() {return DCPL;};
|
||||||
|
|
||||||
|
void initTopological();
|
||||||
|
void topologicalMoveAfter(TaskDCP* task, TaskDCP * pivotPoint);
|
||||||
|
void topologicalMoveBefore(TaskDCP* task, TaskDCP * pivotPoint);
|
||||||
|
|
||||||
|
llvm::DenseMap<TaskDCP*, int> computeALST(TaskDCP* task, CPU cpu);
|
||||||
|
|
||||||
TaskDCP* findCandidate(std::vector<TaskDCP*> nodes);
|
TaskDCP* findCandidate(std::vector<TaskDCP*> nodes);
|
||||||
void selectProcessor(TaskDCP* candidate, bool push);
|
void selectProcessor(TaskDCP* candidate, bool push);
|
||||||
@@ -45,13 +58,17 @@ class GraphDCP {
|
|||||||
FindSlot findSlot(TaskDCP* candidate, CPU cpu, bool push);
|
FindSlot findSlot(TaskDCP* candidate, CPU cpu, bool push);
|
||||||
void to_dot();
|
void to_dot();
|
||||||
|
|
||||||
|
friend TaskInsertion;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void DCP();
|
void DCP();
|
||||||
GraphDCP(llvm::ArrayRef<onnx_mlir::spatial::SpatWeightedCompute> spatWeightedComputes,
|
GraphDCP(llvm::ArrayRef<onnx_mlir::spatial::SpatWeightedCompute> spatWeightedComputes,
|
||||||
llvm::ArrayRef<EdgesIndex> edges)
|
llvm::ArrayRef<EdgesIndex> edges)
|
||||||
: nodes(), mapCPUTasks() {
|
: nodes(), mapCPUTasks() {
|
||||||
for (auto spatWeightedCompute : spatWeightedComputes)
|
for (auto spatWeightedCompute : spatWeightedComputes){
|
||||||
nodes.emplace_back(spatWeightedCompute);
|
nodes.emplace_back(spatWeightedCompute);
|
||||||
|
}
|
||||||
|
|
||||||
for (auto [start, end, weight] : edges)
|
for (auto [start, end, weight] : edges)
|
||||||
makeEdge(start, end, weight);
|
makeEdge(start, end, weight);
|
||||||
|
|||||||
@@ -44,4 +44,17 @@ bool TaskDCP::hasDescendent(TaskDCP* child) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO fare qualcosa di sensato
|
// TODO fare qualcosa di sensato
|
||||||
int TaskDCP::computeWeight(GraphDCP* graph, CPU cpu) { return orig_weight; }
|
int TaskDCP::computeWeight(GraphDCP* graph, CPU cpu) { return origWeight; }
|
||||||
|
|
||||||
|
void TaskInsertion::rollBack() {
|
||||||
|
graph->removeTaskFromCPU(cpuModified, taskInserted);
|
||||||
|
if (beforeNode.has_value()) {
|
||||||
|
auto double_edge = *beforeNode;
|
||||||
|
addEdge(double_edge.first.first, double_edge.second.first, double_edge.first.second);
|
||||||
|
}
|
||||||
|
if (afterNode.has_value()) {
|
||||||
|
auto double_edge = *beforeNode;
|
||||||
|
addEdge(double_edge.first.first, double_edge.second.first, double_edge.first.second);
|
||||||
|
}
|
||||||
|
graph->topologicalOrder.moveBefore( taskInserted,&*oldTopologicalPosition );
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,22 +2,25 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <iterator>
|
||||||
|
#include <list>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "src/Accelerators/PIM/Dialect/Spatial/SpatialOps.hpp"
|
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
#include "src/Accelerators/PIM/Dialect/Spatial/SpatialOps.hpp"
|
||||||
|
|
||||||
std::optional<Edge_pair> addEdge(TaskDCP* parent, TaskDCP* child, Weight_t weight);
|
std::optional<DoubleEdge> addEdge(TaskDCP* parent, TaskDCP* child, Weight_t weight);
|
||||||
void removeEdge(TaskDCP* parent, TaskDCP* child);
|
void removeEdge(TaskDCP* parent, TaskDCP* child);
|
||||||
|
|
||||||
class TaskDCP {
|
class TaskDCP : public onnx_mlir::LabeledListNode<TaskDCP> {
|
||||||
onnx_mlir::spatial::SpatWeightedCompute spatWeightedCompute;
|
onnx_mlir::spatial::SpatWeightedCompute spatWeightedCompute;
|
||||||
int aest;
|
int aest;
|
||||||
int alst;
|
int alst;
|
||||||
std::optional<CPU> scheduledCPU;
|
std::optional<CPU> scheduledCPU;
|
||||||
int weight;
|
int weight;
|
||||||
int orig_weight;
|
int origWeight;
|
||||||
|
long long flag = 0;
|
||||||
|
|
||||||
std::optional<Edge_t> addChild(TaskDCP* child, Weight_t weight);
|
std::optional<Edge_t> addChild(TaskDCP* child, Weight_t weight);
|
||||||
std::optional<Edge_t> addChild(TaskDCP& child, Weight_t weight) { return addChild(&child, weight); }
|
std::optional<Edge_t> addChild(TaskDCP& child, Weight_t weight) { return addChild(&child, weight); }
|
||||||
@@ -36,12 +39,12 @@ public:
|
|||||||
std::vector<Edge_t> childs;
|
std::vector<Edge_t> childs;
|
||||||
TaskDCP() = default;
|
TaskDCP() = default;
|
||||||
TaskDCP(onnx_mlir::spatial::SpatWeightedCompute spatWeightedCompute)
|
TaskDCP(onnx_mlir::spatial::SpatWeightedCompute spatWeightedCompute)
|
||||||
: spatWeightedCompute(spatWeightedCompute),
|
: onnx_mlir::LabeledListNode<TaskDCP>(), spatWeightedCompute(spatWeightedCompute),
|
||||||
aest(0),
|
aest(0),
|
||||||
alst(0),
|
alst(0),
|
||||||
scheduledCPU(),
|
scheduledCPU(),
|
||||||
weight(getSpatWeightCompute(spatWeightedCompute)),
|
weight(getSpatWeightCompute(spatWeightedCompute)),
|
||||||
orig_weight(weight),
|
origWeight(weight),
|
||||||
parents(),
|
parents(),
|
||||||
childs() {}
|
childs() {}
|
||||||
|
|
||||||
@@ -55,13 +58,13 @@ public:
|
|||||||
if (isScheduled())
|
if (isScheduled())
|
||||||
return weight;
|
return weight;
|
||||||
else
|
else
|
||||||
return orig_weight;
|
return origWeight;
|
||||||
}
|
}
|
||||||
void setWeight(int val) { weight = val; }
|
void setWeight(int val) { weight = val; }
|
||||||
void resetWeight() { weight = orig_weight; }
|
void resetWeight() { weight = origWeight; }
|
||||||
int computeWeight(GraphDCP* graph, CPU cpu);
|
int computeWeight(GraphDCP* graph, CPU cpu);
|
||||||
|
|
||||||
bool hasParent() { return parents.size() != 0; }
|
bool hasParents() { return parents.size() != 0; }
|
||||||
bool hasChilds() { return childs.size() != 0; }
|
bool hasChilds() { return childs.size() != 0; }
|
||||||
|
|
||||||
int getAEST() { return aest; }
|
int getAEST() { return aest; }
|
||||||
@@ -81,7 +84,24 @@ public:
|
|||||||
bool isScheduled() const { return scheduledCPU.has_value(); }
|
bool isScheduled() const { return scheduledCPU.has_value(); }
|
||||||
onnx_mlir::spatial::SpatWeightedCompute getSpatWeightedCompute() { return spatWeightedCompute; }
|
onnx_mlir::spatial::SpatWeightedCompute getSpatWeightedCompute() { return spatWeightedCompute; }
|
||||||
|
|
||||||
friend std::optional<Edge_pair> addEdge(TaskDCP* parent, TaskDCP* child, Weight_t weight);
|
void setFlag(long long val) { flag = val; }
|
||||||
|
long long getFlag() const { return flag; }
|
||||||
|
|
||||||
|
onnx_mlir::LabeledList<TaskDCP>::Iterator getTopologicalPosition() { return getIterator(); }
|
||||||
|
|
||||||
|
friend std::optional<DoubleEdge> addEdge(TaskDCP* parent, TaskDCP* child, Weight_t weight);
|
||||||
friend void removeEdge(TaskDCP* parent, TaskDCP* child);
|
friend void removeEdge(TaskDCP* parent, TaskDCP* child);
|
||||||
friend int getTranferCost(TaskDCP* parent, TaskDCP* child);
|
friend int getTranferCost(TaskDCP* parent, TaskDCP* child);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct TaskInsertion {
|
||||||
|
std::optional<DoubleEdge> beforeNode;
|
||||||
|
std::optional<DoubleEdge> afterNode;
|
||||||
|
onnx_mlir::LabeledList<TaskDCP>::Iterator oldTopologicalPosition;
|
||||||
|
CPU cpuModified;
|
||||||
|
TaskDCP* taskInserted;
|
||||||
|
GraphDCP* graph;
|
||||||
|
|
||||||
|
void rollBack();
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <iostream>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
@@ -15,7 +17,7 @@ class UniqueWorkList {
|
|||||||
|
|
||||||
using V = typename T::value_type;
|
using V = typename T::value_type;
|
||||||
T storage;
|
T storage;
|
||||||
std::unordered_set<V> set;
|
llvm::DenseSet<V> set;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UniqueWorkList() = default;
|
UniqueWorkList() = default;
|
||||||
@@ -24,7 +26,7 @@ public:
|
|||||||
UniqueWorkList(const arg_ty& from)
|
UniqueWorkList(const arg_ty& from)
|
||||||
: storage() {
|
: storage() {
|
||||||
for (auto& element : from) {
|
for (auto& element : from) {
|
||||||
if (set.count(element) == 0) {
|
if (!set.contains(element)) {
|
||||||
storage.push_back(element);
|
storage.push_back(element);
|
||||||
set.insert(element);
|
set.insert(element);
|
||||||
}
|
}
|
||||||
@@ -41,7 +43,7 @@ public:
|
|||||||
V& back() { return storage.back(); }
|
V& back() { return storage.back(); }
|
||||||
|
|
||||||
bool push_back(const V& val) {
|
bool push_back(const V& val) {
|
||||||
if (set.count(val) == 0) {
|
if (!set.contains(val)) {
|
||||||
storage.push_back(val);
|
storage.push_back(val);
|
||||||
set.insert(val);
|
set.insert(val);
|
||||||
return true;
|
return true;
|
||||||
@@ -61,10 +63,11 @@ public:
|
|||||||
|
|
||||||
void pop_back() { storage.pop_back(); }
|
void pop_back() { storage.pop_back(); }
|
||||||
|
|
||||||
|
|
||||||
template <typename Iterator, typename Mapper>
|
template <typename Iterator, typename Mapper>
|
||||||
bool allElementContained(Iterator start, Iterator end, Mapper map) {
|
bool allElementContained(Iterator start, Iterator end, Mapper map) {
|
||||||
while (start != end) {
|
while (start != end) {
|
||||||
if (set.count(map(*start)) == 0)
|
if (!set.contains(map(*start)))
|
||||||
return false;
|
return false;
|
||||||
std::advance(start, 1);
|
std::advance(start, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,20 +6,24 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <list>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "src/Accelerators/PIM/Common/LabeledList.hpp"
|
||||||
#include "src/Accelerators/PIM/Dialect/Spatial/SpatialOps.hpp"
|
#include "src/Accelerators/PIM/Dialect/Spatial/SpatialOps.hpp"
|
||||||
#include "src/Support/TypeUtilities.hpp"
|
#include "src/Support/TypeUtilities.hpp"
|
||||||
|
|
||||||
|
|
||||||
using CPU = int;
|
using CPU = int;
|
||||||
using Weight_t = int;
|
using Weight_t = int;
|
||||||
class TaskDCP;
|
class TaskDCP;
|
||||||
class GraphDCP;
|
class GraphDCP;
|
||||||
using Edge_t = std::pair<TaskDCP*, Weight_t>;
|
using Edge_t = std::pair<TaskDCP*, Weight_t>;
|
||||||
using Edge_pair = std::pair<Edge_t, Edge_t>;
|
using DoubleEdge = std::pair<Edge_t, Edge_t>;
|
||||||
using EdgesIndex = std::tuple<int64_t, int64_t, int64_t>;
|
using EdgesIndex = std::tuple<int64_t, int64_t, int64_t>;
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void fastRemove(std::vector<std::pair<T*, Weight_t>>& vector, T* to_remove) {
|
void fastRemove(std::vector<std::pair<T*, Weight_t>>& vector, T* to_remove) {
|
||||||
auto position =
|
auto position =
|
||||||
|
|||||||
Reference in New Issue
Block a user