diff --git a/include/tvm/tensor.h b/include/tvm/tensor.h index 3df636f338edd07ee31107d30db0982f3615b051..60f5c5a2d505d9bc2420021632d351275992904d 100644 --- a/include/tvm/tensor.h +++ b/include/tvm/tensor.h @@ -239,4 +239,13 @@ DEFINE_OVERLOAD_SLICE_BINARY_OP(>); // NOLINT(*) DEFINE_OVERLOAD_SLICE_BINARY_OP(<); // NOLINT(*) } // namespace tvm + +namespace std { +template <> +struct hash<::tvm::Operation> { + std::size_t operator()(const ::tvm::Operation& k) const { + return k.hash(); + } +}; +} #endif // TVM_TENSOR_H_ diff --git a/src/README.md b/src/README.md index 33f4e6cc49c73c90a6045f2a466348e9b15bfc07..d1d8201e02d8bf1c9d43809e8f6d94cbee4b4731 100644 --- a/src/README.md +++ b/src/README.md @@ -2,5 +2,5 @@ - c_api C API related functions - lang The definition of DSL related data structure +- schedule The operations on the schedule graph before converting to IR. - pass The optimization pass on the IR structure -- bound Bound inference logics. diff --git a/src/bound/bound.cc b/src/schedule/bound.cc similarity index 96% rename from src/bound/bound.cc rename to src/schedule/bound.cc index 052920b932a6b20e7bb9395d8e433b50d0ec1a61..50a62e10432f37bd766e512a4eba85ee1d265ede 100644 --- a/src/bound/bound.cc +++ b/src/schedule/bound.cc @@ -8,7 +8,7 @@ #include "./bound.h" namespace tvm { -namespace bound { +namespace schedule { // result = ceil((a / b)), both a and b are positive integer inline Expr DivCeil(Expr a, Expr b) { @@ -89,5 +89,10 @@ void PassUp(const Schedule& s, } } -} // namespace bound + +std::unordered_map<IterVar, Range> InferBound(Schedule sch) { + return {}; +} + +} // namespace schedule } // namespace tvm diff --git a/src/bound/bound.h b/src/schedule/bound.h similarity index 78% rename from src/bound/bound.h rename to src/schedule/bound.h index 5c73d832ae9cdee8e186d6d085b7bdb287925463..ac6becca35e2a21530a2f271c261af281bb8861b 100644 --- a/src/bound/bound.h +++ b/src/schedule/bound.h @@ -3,15 +3,15 @@ * \file bound.h * \brief The bound inference logics on the schedule. */ -#ifndef TVM_BOUND_BOUND_H_ -#define TVM_BOUND_BOUND_H_ +#ifndef TVM_SCHEDULE_BOUND_H_ +#define TVM_SCHEDULE_BOUND_H_ #include <tvm/expr.h> #include <tvm/schedule.h> #include <unordered_map> namespace tvm { -namespace bound { +namespace schedule { /*! * \brief Infer the bound of all iteration variables relates to the schedule. @@ -21,7 +21,7 @@ namespace bound { */ std::unordered_map<IterVar, Range> InferBound(Schedule sch); -} // namespace bound +} // namespace schedule } // namespace tvm -#endif // TVM_BOUND_BOUND_H_ +#endif // TVM_SCHEDULE_BOUND_H_ diff --git a/src/schedule/graph.cc b/src/schedule/graph.cc new file mode 100644 index 0000000000000000000000000000000000000000..96ba4c986b40c6dc352ac480e332ab85d4e466e5 --- /dev/null +++ b/src/schedule/graph.cc @@ -0,0 +1,67 @@ +/*! + * Copyright (c) 2016 by Contributors + * \file graph.cc + * \brief Utilities to get information about schedule graph. + */ +#include <tvm/ir.h> +#include <tvm/ir_visitor.h> +#include <unordered_set> +#include "./int_set.h" +#include "./graph.h" + +namespace tvm { +namespace schedule { + +// construct a read graph that gives readers of each operation +// that the root depend on +ReadGraph CreateReadGraph(Operation root) { + std::unordered_map<Operation, std::vector<Tensor> > rmap; + rmap[root] = {}; + std::vector<Operation> stack{root}; + while (!stack.empty()) { + Operation r = stack.back(); + stack.pop_back(); + auto& vec = rmap.at(r); + if (r.as<ComputeOpNode>()) { + auto fvisit = [&vec, &rmap, &stack](const NodeRef& n) { + auto *call = n.as<ir::Call>(); + if (call != nullptr && call->func.defined()) { + Tensor t(call->func.node_); + vec.push_back(t); + if (t->op.defined() && rmap.count(t->op) == 0) { + rmap[t->op] = {}; stack.push_back(t->op); + } + } + }; + ir::PostOrderVisit(r.as<ComputeOpNode>()->body, fvisit); + } else { + LOG(FATAL) << "unknown operation mode"; + } + } + return rmap; +} + + +void PostDFSOrder(const Operation& op, + const ReadGraph& g, + std::unordered_set<Operation>* visited, + std::vector<Operation>* post_order) { + visited->insert(op); + for (const auto& t : g.at(op)) { + if (t->op.defined() && !visited->count(t->op)) { + PostDFSOrder(t->op, g, visited, post_order); + } + } + post_order->push_back(op); +} + +std::vector<Operation> PostDFSOrder( + const Operation& root, const ReadGraph& g) { + std::unordered_set<Operation> visited; + std::vector<Operation> post_order; + PostDFSOrder(root, g, &visited, &post_order); + return post_order; +} + +} // namespace schedule +} // namespace tvm diff --git a/src/schedule/graph.h b/src/schedule/graph.h new file mode 100644 index 0000000000000000000000000000000000000000..cf57a213a036f4d17846da723ccd915f537576c4 --- /dev/null +++ b/src/schedule/graph.h @@ -0,0 +1,47 @@ +/*! + * Copyright (c) 2016 by Contributors + * \file graph.h + * \brief Utilities to get information about schedule graph. + */ +#ifndef TVM_SCHEDULE_GRAPH_H_ +#define TVM_SCHEDULE_GRAPH_H_ + +#include <tvm/expr.h> +#include <tvm/schedule.h> +#include <unordered_map> +#include <vector> + +namespace tvm { +namespace schedule { + +/*! + * \brief data structure of Operation->Tensors it reads + */ +using ReadGraph = std::unordered_map<Operation, std::vector<Tensor> >; + +/*! + * \brief Get read graph of each operation to all the + * Tensors that it directly depends on. + * + * The result map contains Operations needed to finish root Operation. + * \param root The root operation. + * \return The result map. + */ +ReadGraph CreateReadGraph(const Operation& root); + +/*! + * \brief Get a post DFS ordered of operations in the graph. + * \param root The root of the graph. + * \param g The read graph. + * \return vector order of Operations in PostDFS order. + * + * \note PostDFSOrder is a special case of Topoligical order, + * and can be used when topoligical order is needed. + */ +std::vector<Operation> PostDFSOrder( + const Operation& root, const ReadGraph& g); + +} // namespace schedule +} // namespace tvm + +#endif // TVM_SCHEDULE_GRAPH_H_ diff --git a/src/bound/int_set.cc b/src/schedule/int_set.cc similarity index 99% rename from src/bound/int_set.cc rename to src/schedule/int_set.cc index 4a4c8a5740d51d269eb0bb7f39c4e2c91a38313f..8b05da931e2a1a99f21cc0ad0061055118c709cc 100644 --- a/src/bound/int_set.cc +++ b/src/schedule/int_set.cc @@ -7,7 +7,7 @@ #include "./int_set.h" namespace tvm { -namespace bound { +namespace schedule { using namespace ir; @@ -338,6 +338,5 @@ IntSet Eval(Expr e, return m.Eval(e); } -} // namespace bound +} // namespace schedule } // namespace tvm - diff --git a/src/bound/int_set.h b/src/schedule/int_set.h similarity index 95% rename from src/bound/int_set.h rename to src/schedule/int_set.h index f5531ea4b86680f199ceaabd4796a91a92be9de6..dbcf497958eff25529917cb052937c255fb40abe 100644 --- a/src/bound/int_set.h +++ b/src/schedule/int_set.h @@ -3,14 +3,14 @@ * \file int_set.h * \brief Abstraction for all integer set operations. */ -#ifndef TVM_BOUND_INT_SET_H_ -#define TVM_BOUND_INT_SET_H_ +#ifndef TVM_SCHEDULE_INT_SET_H_ +#define TVM_SCHEDULE_INT_SET_H_ #include <tvm/expr.h> #include <tvm/schedule.h> namespace tvm { -namespace bound { +namespace schedule { // internal node container of int set. class IntSetNode; @@ -97,7 +97,7 @@ void PassUp(const FuseNode* s, */ IntSet Union(const Array<IntSet>& sets); -} // namespace bound +} // namespace schedule } // namespace tvm -#endif // TVM_BOUND_INT_SET_H_ +#endif // TVM_SCHEDULE_INT_SET_H_