mesytec-mnode/external/taskflow-3.8.0/taskflow/sycl/sycl_graph.hpp
2025-01-04 01:25:05 +01:00

255 lines
5.5 KiB
C++

#pragma once
#include <CL/sycl.hpp>
#include "sycl_meta.hpp"
namespace tf {
// ----------------------------------------------------------------------------
// syclGraph class
// ----------------------------------------------------------------------------
// class: syclGraph
class syclGraph : public CustomGraphBase {
friend class syclNode;
friend class syclTask;
friend class syclFlow;
friend class Taskflow;
friend class Executor;
constexpr static int OFFLOADED = 0x01;
constexpr static int TOPOLOGY_CHANGED = 0x02;
public:
syclGraph() = default;
~syclGraph() = default;
syclGraph(const syclGraph&) = delete;
syclGraph(syclGraph&&);
syclGraph& operator = (const syclGraph&) = delete;
syclGraph& operator = (syclGraph&&);
template <typename... ArgsT>
syclNode* emplace_back(ArgsT&&...);
bool empty() const;
void clear();
void dump(std::ostream&, const void*, const std::string&) const override final;
private:
int _state {0};
std::vector<std::unique_ptr<syclNode>> _nodes;
};
// ----------------------------------------------------------------------------
// syclNode definitions
// ----------------------------------------------------------------------------
// class: syclNode
class syclNode {
friend class syclGraph;
friend class syclTask;
friend class syclFlow;
friend class Taskflow;
friend class Executor;
struct Empty {
};
struct CGH {
std::function<void(sycl::handler&)> work;
template <typename F>
CGH(F&& func) : work {std::forward<F>(func)} {}
};
using handle_t = std::variant<
Empty,
CGH
>;
public:
// variant index
constexpr static auto EMPTY = get_index_v<Empty, handle_t>;
constexpr static auto COMMAND_GROUP_HANDLER = get_index_v<CGH, handle_t>;
syclNode() = delete;
template <typename... ArgsT>
syclNode(syclGraph&, ArgsT&&...);
private:
syclGraph& _graph;
std::string _name;
int _level;
sycl::event _event;
handle_t _handle;
SmallVector<syclNode*> _successors;
SmallVector<syclNode*> _dependents;
void _precede(syclNode*);
};
// ----------------------------------------------------------------------------
// syclNode definitions
// ----------------------------------------------------------------------------
// Constructor
template <typename... ArgsT>
syclNode::syclNode(syclGraph& g, ArgsT&&... args) :
_graph {g},
_handle {std::forward<ArgsT>(args)...} {
}
// Procedure: _precede
inline void syclNode::_precede(syclNode* v) {
_graph._state |= syclGraph::TOPOLOGY_CHANGED;
_successors.push_back(v);
v->_dependents.push_back(this);
}
// ----------------------------------------------------------------------------
// syclGraph definitions
// ----------------------------------------------------------------------------
// Move constructor
inline syclGraph::syclGraph(syclGraph&& g) :
_nodes {std::move(g._nodes)} {
assert(g._nodes.empty());
}
// Move assignment
inline syclGraph& syclGraph::operator = (syclGraph&& rhs) {
// lhs
_nodes = std::move(rhs._nodes);
assert(rhs._nodes.empty());
return *this;
}
// Function: empty
inline bool syclGraph::empty() const {
return _nodes.empty();
}
// Procedure: clear
inline void syclGraph::clear() {
_state = syclGraph::TOPOLOGY_CHANGED;
_nodes.clear();
}
// Function: emplace_back
template <typename... ArgsT>
syclNode* syclGraph::emplace_back(ArgsT&&... args) {
_state |= syclGraph::TOPOLOGY_CHANGED;
auto node = std::make_unique<syclNode>(std::forward<ArgsT>(args)...);
_nodes.emplace_back(std::move(node));
return _nodes.back().get();
// TODO: object pool
//auto node = new syclNode(std::forward<ArgsT>(args)...);
//_nodes.push_back(node);
//return node;
}
// Procedure: dump the graph to a DOT format
inline void syclGraph::dump(
std::ostream& os, const void* root, const std::string& root_name
) const {
// recursive dump with stack
std::stack<std::tuple<const syclGraph*, const syclNode*, int>> stack;
stack.push(std::make_tuple(this, nullptr, 1));
int pl = 0;
while(!stack.empty()) {
auto [graph, parent, l] = stack.top();
stack.pop();
for(int i=0; i<pl-l+1; i++) {
os << "}\n";
}
if(parent == nullptr) {
if(root) {
os << "subgraph cluster_p" << root << " {\nlabel=\"syclFlow: ";
if(root_name.empty()) os << 'p' << root;
else os << root_name;
os << "\";\n" << "color=\"red\"\n";
}
else {
os << "digraph syclFlow {\n";
}
}
else {
os << "subgraph cluster_p" << parent << " {\nlabel=\"syclSubflow: ";
if(parent->_name.empty()) os << 'p' << parent;
else os << parent->_name;
os << "\";\n" << "color=\"purple\"\n";
}
for(auto& v : graph->_nodes) {
os << 'p' << v.get() << "[label=\"";
if(v->_name.empty()) {
os << 'p' << v.get() << "\"";
}
else {
os << v->_name << "\"";
}
os << "];\n";
for(const auto s : v->_successors) {
os << 'p' << v.get() << " -> " << 'p' << s << ";\n";
}
if(v->_successors.size() == 0) {
if(parent == nullptr) {
if(root) {
os << 'p' << v.get() << " -> p" << root << ";\n";
}
}
else {
os << 'p' << v.get() << " -> p" << parent << ";\n";
}
}
}
// set the previous level
pl = l;
}
for(int i=0; i<pl; i++) {
os << "}\n";
}
}
} // end of namespace tf -----------------------------------------------------