From e011edd175794f796e1fe0a356f89c6f09af38f3 Mon Sep 17 00:00:00 2001 From: tqchen <tianqi.tchen@gmail.com> Date: Fri, 28 Oct 2016 17:17:21 -0700 Subject: [PATCH] Add Tensor, cleanup test, all present tests pass --- HalideIR | 2 +- include/tvm/expr.h | 14 +++++++++++ include/tvm/tensor.h | 34 ++++++++++++------------- include/tvm/tvm.h | 4 --- src/{ir => lang}/ir_node.cc | 0 src/lang/tensor.cc | 47 +++++++++++++++++++++++++++++++++++ tests/cpp/expr_test.cc | 37 --------------------------- tests/cpp/tensor_test.cc | 8 +----- tests/cpp/unittest.mk | 2 +- tests/python/test_domain.py | 29 --------------------- tests/python/test_schedule.py | 41 ------------------------------ tests/python/test_split.py | 22 ---------------- tests/python/test_tensor.py | 30 ---------------------- 13 files changed, 80 insertions(+), 190 deletions(-) rename src/{ir => lang}/ir_node.cc (100%) create mode 100644 src/lang/tensor.cc delete mode 100644 tests/python/test_domain.py delete mode 100644 tests/python/test_schedule.py delete mode 100644 tests/python/test_split.py delete mode 100644 tests/python/test_tensor.py diff --git a/HalideIR b/HalideIR index 84a568ce8..f72e31311 160000 --- a/HalideIR +++ b/HalideIR @@ -1 +1 @@ -Subproject commit 84a568ce86ca64ff4e186b78745152061499cbf4 +Subproject commit f72e313118a61b0cc49987b9eebfc77300d2de0d diff --git a/include/tvm/expr.h b/include/tvm/expr.h index 3cd101faa..fcc5ddaa6 100644 --- a/include/tvm/expr.h +++ b/include/tvm/expr.h @@ -7,13 +7,27 @@ #define TVM_EXPR_H_ #include <ir/Expr.h> +#include <ir/IROperator.h> #include <type_traits> #include "./base.h" namespace tvm { using Halide::Type; +using Halide::Float; +using Halide::Int; +using Halide::UInt; +using Halide::Handle; + +// functions +using Halide::cast; +using Halide::min; +using Halide::max; +using Halide::abs; +using Halide::select; + using Halide::Expr; +using Var = Halide::VarExpr; } // namespace tvm #endif // TVM_EXPR_H_ diff --git a/include/tvm/tensor.h b/include/tvm/tensor.h index a8ddc3c3b..d86e088ec 100644 --- a/include/tvm/tensor.h +++ b/include/tvm/tensor.h @@ -9,9 +9,10 @@ #include <string> #include <vector> #include <type_traits> +#include <tvm/array.h> +#include <ir/FunctionBase.h> #include "./base.h" #include "./expr.h" -#include "./array.h" namespace tvm { @@ -35,11 +36,13 @@ inline FCompute GetFCompute(std::function<Expr(Var, Var, Var, Var)> f) { return [f] (const Array<Var>& i) { return f(i[0], i[1], i[2], i[3]); }; } +using Halide::IR::FunctionRef; + /*! * \brief Tensor structure representing a possible input, * or intermediate computation result. */ -class Tensor : public NodeRef { +class Tensor : public FunctionRef { public: /*! \brief default constructor, used internally */ Tensor() {} @@ -51,7 +54,7 @@ class Tensor : public NodeRef { */ explicit Tensor(Array<Expr> shape, std::string name = "tensor", - DataType dtype = kFloat32); + Type dtype = Float(32)); /*! * \brief constructor of intermediate result. * \param shape Shape of the tensor. @@ -91,10 +94,6 @@ class Tensor : public NodeRef { * \return the result expression representing tensor read. */ Expr operator()(Array<Expr> indices) const; - /*! \return list of input tensors to this tensor */ - std::vector<Tensor> InputTensors() const; - /*! \return whether the tensor stores a result of reduction */ - bool IsRTensor() const; // overload print function friend std::ostream& operator<<(std::ostream &os, const Tensor& t); }; @@ -105,9 +104,9 @@ class TensorNode : public Node { /*! \brief optional name of the tensor */ std::string name; /*! \brief data type in the content of the tensor */ - DataType dtype; + Type dtype; /*! \brief The index representing each dimension, used by source expression. */ - Array<Var> dim_index; + Array<Var> dim_var; /*! \brief The shape of the tensor */ Array<Expr> shape; /*! \brief source expression */ @@ -115,16 +114,15 @@ class TensorNode : public Node { /*! \brief constructor */ TensorNode() {} const char* type_key() const override { - return "TensorNode"; - } - void VisitAttrs(AttrVisitor* visitor) override { - visitor->Visit("name", &name); - visitor->Visit("dtype", &dtype); + return "Tensor"; } - void VisitNodeRefFields(FNodeRefVisit fvisit) override { - fvisit("dim_index", &dim_index); - fvisit("shape", &shape); - fvisit("source", &source); + void VisitAttrs(AttrVisitor* v) final { + v->Visit("name", &name); + v->Visit("dtype", &dtype); + v->Visit("dim_var", &dim_var); + v->Visit("shape", &shape); + v->Visit("source", &source); + } }; diff --git a/include/tvm/tvm.h b/include/tvm/tvm.h index 2ed7df069..e825272bb 100644 --- a/include/tvm/tvm.h +++ b/include/tvm/tvm.h @@ -8,10 +8,6 @@ #include "./base.h" #include "./expr.h" -#include "./op.h" #include "./tensor.h" -#include "./domain.h" -#include "./array.h" -#include "./expr_util.h" #endif // TVM_TVM_H_ diff --git a/src/ir/ir_node.cc b/src/lang/ir_node.cc similarity index 100% rename from src/ir/ir_node.cc rename to src/lang/ir_node.cc diff --git a/src/lang/tensor.cc b/src/lang/tensor.cc new file mode 100644 index 000000000..f503927dc --- /dev/null +++ b/src/lang/tensor.cc @@ -0,0 +1,47 @@ +/*! + * Copyright (c) 2016 by Contributors + * \file tensor.cc + */ +#include <tvm/tensor.h> +#include <ir/IR.h> +#include <memory> + +namespace tvm { + +Tensor::Tensor(Array<Expr> shape, std::string name, Type dtype) { + auto node = std::make_shared<TensorNode>(); + node->name = std::move(name); + node->dtype = dtype; + node->shape = std::move(shape); + node_ = std::move(node); +} + +Tensor::Tensor(Array<Expr> shape, FCompute fcompute, std::string name) { + auto node = std::make_shared<TensorNode>(); + node->name = std::move(name); + node->shape = std::move(shape); + size_t ndim = node->shape.size(); + std::vector<Var> dim_index; + for (size_t i = 0; i < ndim; ++i) { + std::ostringstream os; + os << "dim_index" << i; + dim_index.push_back(Var(os.str())); + } + node->dim_var = Array<Var>(dim_index); + node->source = fcompute(node->dim_var); + node->dtype = node->source.type(); + node_ = std::move(node); +} + +Expr Tensor::operator()(Array<Expr> indices) const { + using Halide::Internal::Call; + CHECK_EQ(ndim(), indices.size()) + << "Tensor dimension mismatch in read" + << "ndim = " << ndim() << ", indices.size=" << indices.size(); + return Call::make( + (*this)->dtype, (*this)->name, indices, Call::Halide, *this); +} + +TVM_REGISTER_NODE_TYPE(TensorNode); + +} // namespace tvm diff --git a/tests/cpp/expr_test.cc b/tests/cpp/expr_test.cc index 57c1b4ef2..f64fc8651 100644 --- a/tests/cpp/expr_test.cc +++ b/tests/cpp/expr_test.cc @@ -11,43 +11,6 @@ TEST(Expr, Basic) { CHECK(os.str() == "max(((x + 1) + 2), 100)"); } -TEST(Expr, Reduction) { - using namespace tvm; - Var x("x"); - RDomain rdom({{0, 3}}); - auto z = sum(x + 1 + 2, rdom); - std::ostringstream os; - os << z; - CHECK(os.str() == "reduce(+, ((x + 1) + 2), rdomain([[0, 3)]))"); -} - -TEST(Expr, Simplify) { - using namespace tvm; - Var x("x"); - auto z = max(x + 1 + 2, x + 10) * 100; - std::ostringstream os; - os << Simplify(z); - CHECK(os.str() == "((x * 100) + 1000)"); -} - -TEST(Expr, Bind) { - using namespace tvm; - Var x("x"), y("y"), z("z"); - Var i("i"), j("j"); - Tensor A({y, z}, "A"); - Expr e1 = x * 5; - std::unordered_map<Expr, Expr> dict = {{x, y * 10 + z}}; - std::ostringstream os1, os2; - os1 << Bind(e1, dict); - CHECK(os1.str() == "(((y * 10) + z) * 5)"); - - Expr e2 = A(i, j); - dict.clear(); - dict[i] = 64 * x; - dict[j] = z + 16 * y; - os2 << Bind(e2, dict); - CHECK(os2.str() == "A[(64 * x), (z + (16 * y))]"); -} int main(int argc, char ** argv) { testing::InitGoogleTest(&argc, argv); diff --git a/tests/cpp/tensor_test.cc b/tests/cpp/tensor_test.cc index a22ff3abf..6d4a8e586 100644 --- a/tests/cpp/tensor_test.cc +++ b/tests/cpp/tensor_test.cc @@ -8,16 +8,10 @@ TEST(Tensor, Basic) { Var m("m"), n("n"), l("l"); Tensor A({m, l}, "A"); Tensor B({n, l}, "B"); - RDomain rd({{0, l}}); auto C = Tensor({m, n}, [&](Var i, Var j) { - return sum(A(i, rd.i0()) * B(j, rd.i0()), rd); + return A(i, j) * B(j, i); }, "C"); - - auto inputs = C.InputTensors(); - CHECK(inputs[0] == A); - CHECK(inputs[1] == B); - CHECK(C.IsRTensor()); } int main(int argc, char ** argv) { diff --git a/tests/cpp/unittest.mk b/tests/cpp/unittest.mk index a0c4cf685..d71de900a 100644 --- a/tests/cpp/unittest.mk +++ b/tests/cpp/unittest.mk @@ -4,7 +4,7 @@ GTEST_INC=$(GTEST_PATH)/include/ TEST_SRC = $(wildcard tests/cpp/*_test.cc) TEST = $(patsubst tests/cpp/%_test.cc, tests/cpp/%_test, $(TEST_SRC)) -tests/cpp/%_test: tests/cpp/%_test.cc lib/libtvm.a +tests/cpp/%_test: tests/cpp/%_test.cc lib/libtvm.a HalideIR/lib/libHalideIR.a $(CXX) -std=c++11 $(CFLAGS) -MM -MT tests/cpp/$* $< >tests/cpp/$*.d $(CXX) -std=c++11 $(CFLAGS) -I$(GTEST_INC) -o $@ $(filter %.cc %.a, $^) \ -L$(GTEST_LIB) $(LDFLAGS) -lgtest diff --git a/tests/python/test_domain.py b/tests/python/test_domain.py deleted file mode 100644 index ffdbc0fa4..000000000 --- a/tests/python/test_domain.py +++ /dev/null @@ -1,29 +0,0 @@ -import tvm - -def test_range_infer(): - x = tvm.Var('x') - y = tvm.Var('y') - t = tvm.Var('t') - z = x + y + t - zr = tvm.infer_range(z, {x: tvm.Range(10, 20), y : tvm.Range(10, 11)}) - assert str(zr) == "((t0 + 20), (t0 + 30))" - -def test_tensor_dom_infer(): - A = tvm.Tensor(2, name='A') - B = tvm.Tensor(2, name='B') - rd = tvm.RDom(tvm.Range(A.shape[1])) - T = tvm.Tensor(2, lambda i, j: - tvm.reduce_sum(A(i, rd.index[0]) * B(j, rd.index[0]), rdom=rd), - shape=(A.shape[0], B.shape[0])) - C = tvm.Tensor(2, lambda i, j: T(i,j), - shape=(A.shape[0], B.shape[0])) - - cdom = [tvm.Range(0, 10), tvm.Range(1, 11)] - tdom = C.infer_input_domains(cdom, inputs=[T])[T] - assert T.is_rtensor - assert str(tdom[0]) == "(0, 10)" - - -if __name__ == "__main__": - test_range_infer() - test_tensor_dom_infer() diff --git a/tests/python/test_schedule.py b/tests/python/test_schedule.py deleted file mode 100644 index 4252b3680..000000000 --- a/tests/python/test_schedule.py +++ /dev/null @@ -1,41 +0,0 @@ -import tvm - -def test_schedule(): - A = tvm.Tensor(2, name='A') - B = tvm.Tensor(2, name='B') - rd = tvm.RDom(tvm.Range(A.shape[1])) - T = tvm.Tensor(2, lambda i, j: - tvm.reduce_sum(A(i, rd.index[0]) * B(j, rd.index[0]), rdom=rd), - shape=(A.shape[0], B.shape[0]), name="T") - C = tvm.Tensor(2, lambda i, j: T(i,j), - shape=(A.shape[0], B.shape[0]), name="C") - - bufA = tvm.Buffer(tvm.Scope.Thread, name='A') - bufB = tvm.Buffer(tvm.Scope.Thread, name='B') - bufT = tvm.Buffer(tvm.Scope.Thread, name='T') - - schA = tvm.Schedule(A, buffer=bufA) - schB = tvm.Schedule(B, buffer=bufB) - schT = tvm.Schedule(T, buffer=bufT) - schC = tvm.Schedule(C) - Cx0 = tvm.Split(dim=0, factor=64) - Cy0 = tvm.Split(dim=1, factor=64) - Cx1 = tvm.Split(dim=0, factor=8) - Cy1 = tvm.Split(dim=1, factor=8) - Tk = tvm.Split(dim=0, factor=8, rdom=True) - - schC.add_split(Cx0) - schC.add_split(Cy0) - schC.add_split(Cx1) - schC.add_split(Cy1) - schT.add_split(Tk) - schC.attach(Cy1, schT) - schT.attach(Tk, schA) - schT.attach(Tk, schB) - - body = schC.realize() - print('\n'.join(body)) - - -if __name__ == "__main__": - test_schedule() diff --git a/tests/python/test_split.py b/tests/python/test_split.py deleted file mode 100644 index b20062d8b..000000000 --- a/tests/python/test_split.py +++ /dev/null @@ -1,22 +0,0 @@ -import tvm - - -def test_split_dom_infer(): - A = tvm.Tensor(2, name='A') - split1 = tvm.Split(0, 64) - split2 = tvm.Split(1, 64) - split3 = tvm.Split(0, 8) - dom = [tvm.Range(A.shape[0]), tvm.Range(A.shape[1])] - dom1 = split1.infer_inner_domain(dom) - dom2 = split2.infer_inner_domain(dom1) - dom3 = split3.infer_inner_domain(dom2) - i1 = split1.loop_index.name - i2 = split2.loop_index.name - i3 = split3.loop_index.name - assert str(dom1) == "[((%s * 64), ((%s * 64) + 64)), (0, A_shape_1_0)]" % (i1, i1) - assert str(dom2) == "[((%s * 64), ((%s * 64) + 64)), ((%s * 64), ((%s * 64) + 64))]" % (i1, i1, i2, i2) - assert str(dom3) == "[(((%s * 64) + (%s * 8)), (((%s * 64) + (%s * 8)) + 8)), ((%s * 64), ((%s * 64) + 64))]" % (i1, i3, i1, i3, i2, i2) - - -if __name__ == "__main__": - test_split_dom_infer() diff --git a/tests/python/test_tensor.py b/tests/python/test_tensor.py deleted file mode 100644 index 949a19696..000000000 --- a/tests/python/test_tensor.py +++ /dev/null @@ -1,30 +0,0 @@ -import tvm - -def test_tensor(): - A = tvm.Tensor(2, name='A') - B = tvm.Tensor(2, name='B') - T = tvm.Tensor(3, lambda i, j, k: A(i, k) * B(j, k), - shape=(A.shape[0], B.shape[0], A.shape[1])) - print(tvm.format_str(T.expr)) - -def test_tensor_inputs(): - A = tvm.Tensor(2, name='A') - B = tvm.Tensor(2, name='B') - T = tvm.Tensor(3, lambda i, j, k: A(i, k) * B(j, k), - shape=(A.shape[0], B.shape[0], A.shape[1])) - assert(T.input_tensors() == set([A, B])) - -def test_tensor_reduce(): - A = tvm.Tensor(2, name='A') - B = tvm.Tensor(2, name='B') - T = tvm.Tensor(3, lambda i, j, k: A(i, k) * B(j, k), - shape=(A.shape[0], B.shape[0], A.shape[1])) - rd = tvm.RDom(tvm.Range(A.shape[1])) - C = tvm.Tensor(2, lambda i, j: tvm.reduce_sum(T(i, j, rd.index[0]), rdom=rd), - shape=(A.shape[0], B.shape[0])) - print(tvm.format_str(C.expr)) - -if __name__ == "__main__": - test_tensor() - test_tensor_inputs() - test_tensor_reduce() -- GitLab