From cc20479fd158ff1b81e1d03863bf569a749e34a1 Mon Sep 17 00:00:00 2001 From: Gword <471184555@qq.com> Date: Thu, 25 Jun 2020 16:16:37 +0800 Subject: [PATCH 1/7] numpy code op --- src/numpy_func.h | 45 ++++++++++++++ src/ops/numpy_code_op.cc | 124 +++++++++++++++++++++++++++++++++++++++ src/ops/numpy_code_op.h | 32 ++++++++++ src/pyjt/py_converter.h | 36 ++++++++++++ 4 files changed, 237 insertions(+) create mode 100644 src/numpy_func.h create mode 100644 src/ops/numpy_code_op.cc create mode 100644 src/ops/numpy_code_op.h diff --git a/src/numpy_func.h b/src/numpy_func.h new file mode 100644 index 00000000..8c798a6e --- /dev/null +++ b/src/numpy_func.h @@ -0,0 +1,45 @@ +// *************************************************************** +// Copyright (c) 2020 Jittor. Authors: Dun Liang . All Rights Reserved. +// This file is subject to the terms and conditions defined in +// file 'LICENSE.txt', which is part of this source code package. +// *************************************************************** +#pragma once +#include +#include "common.h" +#include "var_holder.h" +#include "ops/array_op.h" + +namespace jittor { + +struct NumpyResult; + +struct NumpyFunc { + typedef NumpyResult R; + std::function callback; + std::function deleter; + NumpyFunc() = default; + NumpyFunc(NumpyFunc&& other) : callback(other.callback), deleter(other.deleter) { + other.callback = nullptr; + other.deleter = nullptr; + }; + NumpyFunc(const NumpyFunc&) = delete; + NumpyFunc(std::function&& callback) : callback(move(callback)) {} + NumpyFunc(std::function&& callback, std::function&& deleter) + : callback(move(callback)), deleter(move(deleter)) {}; + ~NumpyFunc() { + if (deleter) { + deleter(); + } + } + void operator =(NumpyFunc&& other) { this->~NumpyFunc(); new (this) NumpyFunc(move(other)); } +}; + +struct NumpyResult { + // vector allocations; + map> varrays; + map ints; + map arrays; + // mem ptr, dtype, shape --> numpy array +}; + +} // jittor \ No newline at end of file diff --git a/src/ops/numpy_code_op.cc b/src/ops/numpy_code_op.cc new file mode 100644 index 00000000..1b6cd954 --- /dev/null +++ b/src/ops/numpy_code_op.cc @@ -0,0 +1,124 @@ +// *************************************************************** +// Copyright (c) 2020 Jittor. Authors: Dun Liang . All Rights Reserved. +// This file is subject to the terms and conditions defined in +// file 'LICENSE.txt', which is part of this source code package. +// *************************************************************** +#include +#include "var.h" +#include "ops/numpy_code_op.h" +#include "ops/op_register.h" + +#ifndef JIT + +namespace jittor { + +static auto make_numpy_code = get_op_info("numpy_code") + .get_constructor&&, NumpyFunc&&, NumpyResults&&>(); + +static inline void check_vary_shape(NanoVector v) { + ASSERT(v.size()) << "Vary shape should not be zero dimension"; + for (int i=0; i= 0)) + << "Vary shape should only occur in the first dimension:" << v; +} + +NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs={}, NumpyFunc&& forward, vector&& backward) + : _inputs(inputs), forward(forward),backward(backward) +{ + _outputs.push_back(create_output(shape, dtype)); + CHECKop(_inputs.size(),<=,10); + + if (_outputs[0]->num < 0) { + flags.set(NodeFlags::_vary_shape); + check_vary_shape(_outputs[0]->shape); + } +} + +NumpyCodeOp::NumpyCodeOp(vector&& shapes, vector&& dtypes, vector&& inputs={}, NumpyFunc&& forward, vector&& backward) + : _inputs(inputs), forward(forward),backward(backward) +{ + CHECKop(shapes.size(),==,dtypes.size()) << "Number of outputs' shapes and dtypes should be the same"; + _outputs.resize(shapes.size()); + CHECKop(_inputs.size(),<=,10); + CHECKop(_outputs.size(),<=,10); + CHECKop(_outputs.size(),>,0); + for (int i=0; inum < 0) { + flags.set(NodeFlags::_vary_shape); + check_vary_shape(_outputs[i]->shape); + } + } +} + +NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs={}, NumpyFunc&& forward, NumpyResults&& results) + : _inputs(inputs), forward(forward), _results(results) +{ + _outputs.push_back(create_output(shape, dtype)); + CHECKop(_inputs.size(),<=,10); + + if (_outputs[0]->num < 0) { + flags.set(NodeFlags::_vary_shape); + check_vary_shape(_outputs[0]->shape); + } +} + +void NumpyCodeOp::grad(Var* out, Var* dout, Var* v, int v_index) { + NumpyResult result; + // set results + // set dout index + result.ints["dout_index"] = _outputs.find(out); + result.arrays["dout"] = ArrayArgs{ + dout->ptr, + dout->shape, + dout->dtype(), + }; + + // code op: + /* + return make_code( + _inputs[v_index]->shape, + _inputs[v_index]->dtype(), + move(inputs), + move(cpu_src), {}, alias+cpu_header, + move(cuda_src), {}, alias+cuda_header + ); + */ + return make_numpy_code( + _inputs[v_index]->shape, + _inputs[v_index]->dtype(), + inputs, + backward[v_index], + result, + ) +} + +void NumpyCodeOp::run() { + NumpyResult result=_results; + vector inputs(_inputs.size()); + vector outputs(_outputs.size()); + /* + const void* ptr; + NanoVector shape; + NanoString dtype; + */ + for (int i=0; iptr, + _inputs[i]->shape, + _inputs[i]->dtype(), + }; + for (int i=0; iptr, + _outputs[i]->shape, + _outputs[i]->dtype(), + }; + result.varrays["inputs"] = move(inputs); + result.varrays["outputs"] = move(outputs); + forward.callback(&results); +} + +} // jittor + +#endif // JIT \ No newline at end of file diff --git a/src/ops/numpy_code_op.h b/src/ops/numpy_code_op.h new file mode 100644 index 00000000..9dc5a3fc --- /dev/null +++ b/src/ops/numpy_code_op.h @@ -0,0 +1,32 @@ +// *************************************************************** +// Copyright (c) 2020 Jittor. Authors: Dun Liang . All Rights Reserved. +// This file is subject to the terms and conditions defined in +// file 'LICENSE.txt', which is part of this source code package. +// *************************************************************** +#pragma once +#include "op.h" + +namespace jittor { + +struct NumpyCodeOp : Op { + vector _inputs; + vector _outputs; + NumpyFunc forward; + vector backward; + NumpyResult _results; + + NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs={}, NumpyFunc&& forward, vector&& backward); + + // @attrs(multiple_outputs) + NumpyCodeOp(vector&& shapes, vector&& dtypes, vector&& inputs={}, NumpyFunc&& forward, vector&& backward); + + // @pybind(None) + NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs={}, NumpyFunc&& forward, NumpyResults&& results); + + const char* name() const override { return "numpy_code"; } + VarPtr grad(Var* out, Var* dout, Var* v, int v_index) override; + + void run() override; +}; + +} // jittor \ No newline at end of file diff --git a/src/pyjt/py_converter.h b/src/pyjt/py_converter.h index f874cc59..dbf20d25 100644 --- a/src/pyjt/py_converter.h +++ b/src/pyjt/py_converter.h @@ -455,6 +455,42 @@ DEF_IS(FetchFunc, T) from_py_object(PyObject* obj) { return func; } +struct NumpyFunc; + +DEF_IS(NumpyFunc, bool) is_type(PyObject* obj) { + return PyCallable_Check(obj); +} + +DEF_IS(NumpyFunc, T) from_py_object(PyObject* obj) { + // PyObject_Call + Py_INCREF(obj); + T func( + // callback + [obj](typename T::R* result) { + // import numpy + PyObjHolder np(PyImport_ImportModule("numpy")); + // data = {} + PyObjHolder data(to_py_object(results->varrays)); + PyObjHolder data2(to_py_object(results->ints)); + PyObjHolder data3(to_py_object(results->arrays)); + // data.update(data2) + PyDict_Update(data.obj, data2.obj); + // data.update(data3) + PyDict_Update(data.obj, data3.obj); + // args = [] + PyObjHolder args(PyList_new()); + auto ok = PyList_Append(args.obj, np.obj); + ASSERT(ok); + auto ok = PyList_Append(args.obj, data.obj); + ASSERT(ok); + PyObjHolder ret(PyObject_Call(obj, args.obj/* PyObject* */, nullptr)); + }, + // deleter + [obj]() { Py_DECREF(obj); } + ); + return func; +} + #define CHECK_IS_2(check_type) \ template struct is_##check_type : public std::false_type {}; \ template \ From fae73d9ca15e5b3e354a8d2fcffdb225e55e9881 Mon Sep 17 00:00:00 2001 From: Gword <471184555@qq.com> Date: Fri, 3 Jul 2020 11:44:19 +0800 Subject: [PATCH 2/7] test numpy code op --- python/jittor/test/test_numpy_code_op.py | 47 +++++++++++++++ src/ops/numpy_code_op.cc | 75 +++++++++++++---------- src/ops/numpy_code_op.h | 7 ++- src/pyjt/py_converter.h | 77 +++++++++++++----------- 4 files changed, 134 insertions(+), 72 deletions(-) create mode 100644 python/jittor/test/test_numpy_code_op.py diff --git a/python/jittor/test/test_numpy_code_op.py b/python/jittor/test/test_numpy_code_op.py new file mode 100644 index 00000000..80f15ff2 --- /dev/null +++ b/python/jittor/test/test_numpy_code_op.py @@ -0,0 +1,47 @@ +# *************************************************************** +# Copyright (c) 2020 Jittor. Authors: Dun Liang . All Rights Reserved. +# This file is subject to the terms and conditions defined in +# file 'LICENSE.txt', which is part of this source code package. +# *************************************************************** +import unittest +import jittor as jt +import numpy as np + +class TestCodeOp(unittest.TestCase): + def forward_code(np, data): + a,b = data["inputs"] + c,d = data["outputs"] + np.add(a,b,out=c) + np.substract(a,b,out=d) + + def backward_code1(np, data): + dout = data["dout"] + da, db = data["outputs"] + np.copyto(dout, da) + np.copyto(dout, db) + + def backward_code2(np, data): + dout = data["dout"] + da, db = data["outputs"] + np.copyto(dout, da) + np.negtive(dout, db) + + def test(self): + a = jt.random((5,1)) + b = jt.random((5,1)) + + c, d = jt.numpy_code( + [a.shape, a.shape], + [a.dtype, a.dtype], + [a, b], + self.forward_code, + [self.backward_code1,self.backward_code2], + ) + + print("a:",a) + print("b:",b) + print("a+b:",c) + print("a-b:",d) + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/ops/numpy_code_op.cc b/src/ops/numpy_code_op.cc index 1b6cd954..98a596f4 100644 --- a/src/ops/numpy_code_op.cc +++ b/src/ops/numpy_code_op.cc @@ -13,7 +13,7 @@ namespace jittor { static auto make_numpy_code = get_op_info("numpy_code") - .get_constructor&&, NumpyFunc&&, NumpyResults&&>(); + .get_constructor&&, NumpyFunc&&, NumpyResult&&>(); static inline void check_vary_shape(NanoVector v) { ASSERT(v.size()) << "Vary shape should not be zero dimension"; @@ -22,8 +22,8 @@ static inline void check_vary_shape(NanoVector v) { << "Vary shape should only occur in the first dimension:" << v; } -NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs={}, NumpyFunc&& forward, vector&& backward) - : _inputs(inputs), forward(forward),backward(backward) +NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc&& forward, vector&& sbackward) + : _inputs(inputs), forward(move(forward)) { _outputs.push_back(create_output(shape, dtype)); CHECKop(_inputs.size(),<=,10); @@ -32,10 +32,13 @@ NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inpu flags.set(NodeFlags::_vary_shape); check_vary_shape(_outputs[0]->shape); } + for (int i=0; i&& shapes, vector&& dtypes, vector&& inputs={}, NumpyFunc&& forward, vector&& backward) - : _inputs(inputs), forward(forward),backward(backward) +NumpyCodeOp::NumpyCodeOp(vector&& shapes, vector&& dtypes, vector&& inputs, NumpyFunc&& forward, vector&& sbackward) + : _inputs(inputs), forward(move(forward)) { CHECKop(shapes.size(),==,dtypes.size()) << "Number of outputs' shapes and dtypes should be the same"; _outputs.resize(shapes.size()); @@ -49,10 +52,13 @@ NumpyCodeOp::NumpyCodeOp(vector&& shapes, vector&& dtype check_vary_shape(_outputs[i]->shape); } } + for (int i=0; i&& inputs={}, NumpyFunc&& forward, NumpyResults&& results) - : _inputs(inputs), forward(forward), _results(results) +NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc&& forward, NumpyResult&& results) + : _inputs(inputs), forward(move(forward)), _results(move(results)) { _outputs.push_back(create_output(shape, dtype)); CHECKop(_inputs.size(),<=,10); @@ -63,17 +69,23 @@ NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inpu } } -void NumpyCodeOp::grad(Var* out, Var* dout, Var* v, int v_index) { +VarPtr NumpyCodeOp::grad(Var* out, Var* dout, Var* v, int v_index) { NumpyResult result; // set results // set dout index - result.ints["dout_index"] = _outputs.find(out); - result.arrays["dout"] = ArrayArgs{ - dout->ptr, - dout->shape, - dout->dtype(), - }; - + // result.ints["dout_index"] = _outputs.find(out); + for (int i=0; i<_outputs.size(); i++) { + if (_outputs[i] == out) { + result.ints["dout_index"] = i; + break; + } + } + result.arrays["dout"].ptr=dout; + result.arrays["dout"].shape=dout->shape; + result.arrays["dout"].dtype=dout->dtype(); + auto inputs = clone(_inputs); + inputs.push_back(dout); + // code op: /* return make_code( @@ -87,14 +99,13 @@ void NumpyCodeOp::grad(Var* out, Var* dout, Var* v, int v_index) { return make_numpy_code( _inputs[v_index]->shape, _inputs[v_index]->dtype(), - inputs, - backward[v_index], - result, - ) + move(inputs), + move(backward[v_index]), + move(result)); } void NumpyCodeOp::run() { - NumpyResult result=_results; + NumpyResult result=move(_results); vector inputs(_inputs.size()); vector outputs(_outputs.size()); /* @@ -102,21 +113,19 @@ void NumpyCodeOp::run() { NanoVector shape; NanoString dtype; */ - for (int i=0; iptr, - _inputs[i]->shape, - _inputs[i]->dtype(), - }; - for (int i=0; iptr, - _outputs[i]->shape, - _outputs[i]->dtype(), - }; + for (int i=0; iptr(); + inputs[i].shape=_inputs[i]->shape; + inputs[i].dtype=_inputs[i]->dtype(); + } + for (int i=0; iptr(); + outputs[i].shape=_outputs[i]->shape; + outputs[i].dtype=_outputs[i]->dtype(); + } result.varrays["inputs"] = move(inputs); result.varrays["outputs"] = move(outputs); - forward.callback(&results); + forward.callback(&result); } } // jittor diff --git a/src/ops/numpy_code_op.h b/src/ops/numpy_code_op.h index 9dc5a3fc..c364b1ab 100644 --- a/src/ops/numpy_code_op.h +++ b/src/ops/numpy_code_op.h @@ -5,6 +5,7 @@ // *************************************************************** #pragma once #include "op.h" +#include "numpy_func.h" namespace jittor { @@ -15,13 +16,13 @@ struct NumpyCodeOp : Op { vector backward; NumpyResult _results; - NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs={}, NumpyFunc&& forward, vector&& backward); + NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc&& forward, vector&& backward); // @attrs(multiple_outputs) - NumpyCodeOp(vector&& shapes, vector&& dtypes, vector&& inputs={}, NumpyFunc&& forward, vector&& backward); + NumpyCodeOp(vector&& shapes, vector&& dtypes, vector&& inputs, NumpyFunc&& forward, vector&& backward); // @pybind(None) - NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs={}, NumpyFunc&& forward, NumpyResults&& results); + NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc&& forward, NumpyResult&& results); const char* name() const override { return "numpy_code"; } VarPtr grad(Var* out, Var* dout, Var* v, int v_index) override; diff --git a/src/pyjt/py_converter.h b/src/pyjt/py_converter.h index dbf20d25..b474c78c 100644 --- a/src/pyjt/py_converter.h +++ b/src/pyjt/py_converter.h @@ -67,7 +67,7 @@ DEF_IS(int, bool) is_type(PyObject* obj) { return PyLong_CheckExact(obj); } -DEF_IS(int, PyObject*) to_py_object(const T& a) { +DEF_IS(int, PyObject*) to_py_object(const int& a) { return PyLong_FromLong(a); } @@ -374,6 +374,14 @@ DEF_IS(DataView, PyObject*) to_py_object(T a) { return oh.release(); } +struct NumpyFunc; + +DEF_IS(NumpyFunc, bool) is_type(PyObject* obj) { + return PyCallable_Check(obj); +} + +DEF_IS(NumpyFunc, T) from_py_object(PyObject* obj); + #define CHECK_IS_1(check_type) \ template struct is_##check_type : public std::false_type {}; \ template \ @@ -455,41 +463,6 @@ DEF_IS(FetchFunc, T) from_py_object(PyObject* obj) { return func; } -struct NumpyFunc; - -DEF_IS(NumpyFunc, bool) is_type(PyObject* obj) { - return PyCallable_Check(obj); -} - -DEF_IS(NumpyFunc, T) from_py_object(PyObject* obj) { - // PyObject_Call - Py_INCREF(obj); - T func( - // callback - [obj](typename T::R* result) { - // import numpy - PyObjHolder np(PyImport_ImportModule("numpy")); - // data = {} - PyObjHolder data(to_py_object(results->varrays)); - PyObjHolder data2(to_py_object(results->ints)); - PyObjHolder data3(to_py_object(results->arrays)); - // data.update(data2) - PyDict_Update(data.obj, data2.obj); - // data.update(data3) - PyDict_Update(data.obj, data3.obj); - // args = [] - PyObjHolder args(PyList_new()); - auto ok = PyList_Append(args.obj, np.obj); - ASSERT(ok); - auto ok = PyList_Append(args.obj, data.obj); - ASSERT(ok); - PyObjHolder ret(PyObject_Call(obj, args.obj/* PyObject* */, nullptr)); - }, - // deleter - [obj]() { Py_DECREF(obj); } - ); - return func; -} #define CHECK_IS_2(check_type) \ template struct is_##check_type : public std::false_type {}; \ @@ -583,4 +556,36 @@ DEF_IS_1(fast_shared_ptr, T) from_py_object(PyObject* obj) { } + +DEF_IS(NumpyFunc, T) from_py_object(PyObject* obj) { + // PyObject_Call + Py_INCREF(obj); + T func( + // callback + [obj](typename T::R* result) { + // import numpy + PyObjHolder np(PyImport_ImportModule("numpy")); + // data = {} + //PyObjHolder data(to_py_object>>(result->varrays)); + PyObjHolder data(to_py_object(result->varrays)); + PyObjHolder data2(to_py_object(result->ints)); + PyObjHolder data3(to_py_object(result->arrays)); + // data.update(data2) + PyDict_Update(data.obj, data2.obj); + // data.update(data3) + PyDict_Update(data.obj, data3.obj); + // args = [] + PyObjHolder args(PyList_New(0)); + int ok = PyList_Append(args.obj, np.obj); + ASSERT(ok); + ok = PyList_Append(args.obj, data.obj); + ASSERT(ok); + PyObjHolder ret(PyObject_Call(obj, args.obj, nullptr)); + }, + // deleter + [obj]() { Py_DECREF(obj); } + ); + return func; +} + } // jittor From dfa1a4d999bdbcc6076face4e18e61ed8733fb1f Mon Sep 17 00:00:00 2001 From: Gword <471184555@qq.com> Date: Mon, 6 Jul 2020 16:51:21 +0800 Subject: [PATCH 3/7] numpy code op test --- python/jittor/test/test_numpy_code_op.py | 43 +++++++++++------ src/grad.cc | 44 ++++++++--------- src/numpy_func.h | 19 ++++++-- src/ops/numpy_code_op.cc | 60 +++++++++++------------- src/ops/numpy_code_op.h | 7 ++- src/pyjt/py_converter.h | 28 +++++------ 6 files changed, 112 insertions(+), 89 deletions(-) diff --git a/python/jittor/test/test_numpy_code_op.py b/python/jittor/test/test_numpy_code_op.py index 80f15ff2..9258bf03 100644 --- a/python/jittor/test/test_numpy_code_op.py +++ b/python/jittor/test/test_numpy_code_op.py @@ -1,5 +1,8 @@ # *************************************************************** -# Copyright (c) 2020 Jittor. Authors: Dun Liang . All Rights Reserved. +# Copyright (c) 2020 Jittor. Authors: +# Guowei Yang <471184555@qq.com> +# Dun Liang . +# All Rights Reserved. # This file is subject to the terms and conditions defined in # file 'LICENSE.txt', which is part of this source code package. # *************************************************************** @@ -8,23 +11,27 @@ import jittor as jt import numpy as np class TestCodeOp(unittest.TestCase): - def forward_code(np, data): + def forward_code(self, np, data): a,b = data["inputs"] c,d = data["outputs"] np.add(a,b,out=c) - np.substract(a,b,out=d) + np.subtract(a,b,out=d) + p, r = c.__array_interface__['data'] - def backward_code1(np, data): + def backward_code1(self, np, data): dout = data["dout"] - da, db = data["outputs"] - np.copyto(dout, da) - np.copyto(dout, db) + a,b,dout = data["inputs"] + out = data["outputs"][0] + np.copyto(out, dout) - def backward_code2(np, data): + def backward_code2(self, np, data): dout = data["dout"] - da, db = data["outputs"] - np.copyto(dout, da) - np.negtive(dout, db) + out_index = data["out_index"] + out = data["outputs"][0] + if out_index==0: + np.copyto(out, dout) + else: + np.negative(dout, out) def test(self): a = jt.random((5,1)) @@ -38,10 +45,16 @@ class TestCodeOp(unittest.TestCase): [self.backward_code1,self.backward_code2], ) - print("a:",a) - print("b:",b) - print("a+b:",c) - print("a-b:",d) + assert np.allclose(c.data,(a+b).data) + assert np.allclose(d.data,(a-b).data) + dca, dcb = jt.grad(c,[a,b]) + dda, ddb = jt.grad(d,[a,b]) + one=np.ones(a.shape) + mone=one*-1.0 + assert np.allclose(dca.data,one) + assert np.allclose(dcb.data,one) + assert np.allclose(dda.data,one) + assert np.allclose(ddb.data,mone) if __name__ == "__main__": unittest.main() \ No newline at end of file diff --git a/src/grad.cc b/src/grad.cc index e1e78446..2652a79e 100644 --- a/src/grad.cc +++ b/src/grad.cc @@ -93,28 +93,30 @@ vector grad(Var* loss, vector targets) { auto index = it.index; if (op->tflag != nt) continue; // TODO: support two outputs backprop. - Var* out = op->outputs().back(); - Var* dout = grads[out->custom_data]; - VarPtr dvar = make_grad(op, out, dout, var, index); - registe_node_trace_grad(dvar.ptr, op, index); - if (dvar) - ASSERT(dvar->num==var->num && dvar->shape.size()==var->shape.size()) - << "dvar" << dvar << "var" << var; - if (!grad) - grad = move(dvar); - else if (dvar) { - grad = make_binary(grad, dvar, ns_add); - #ifdef PREVENT_LARGE_FUSED_OP - gsum ++; - if (gsum>=PREVENT_LARGE_FUSED_OP) { - // TODO: this is a dirty fix for - // stopping fuse lots of op together, - // try to find a better solution - grad->flags.set(NodeFlags::_stop_fuse); + for (Var* out : op->outputs()) { + if (out->tflag != nt) continue; + Var* dout = grads[out->custom_data]; + VarPtr dvar = make_grad(op, out, dout, var, index); + registe_node_trace_grad(dvar.ptr, op, index); + if (dvar) + ASSERT(dvar->num==var->num && dvar->shape.size()==var->shape.size()) + << "dvar" << dvar << "var" << var; + if (!grad) + grad = move(dvar); + else if (dvar) { + grad = make_binary(grad, dvar, ns_add); + #ifdef PREVENT_LARGE_FUSED_OP + gsum ++; + if (gsum>=PREVENT_LARGE_FUSED_OP) { + // TODO: this is a dirty fix for + // stopping fuse lots of op together, + // try to find a better solution + grad->flags.set(NodeFlags::_stop_fuse); + } + #endif + assign_attrs(grad.ptr, var); + registe_node_trace_grad(grad.ptr, var, index); } - #endif - assign_attrs(grad.ptr, var); - registe_node_trace_grad(grad.ptr, var, index); } } } diff --git a/src/numpy_func.h b/src/numpy_func.h index 8c798a6e..4ab01dee 100644 --- a/src/numpy_func.h +++ b/src/numpy_func.h @@ -1,5 +1,8 @@ // *************************************************************** -// Copyright (c) 2020 Jittor. Authors: Dun Liang . All Rights Reserved. +// Copyright (c) 2020 Jittor. Authors: +// Guowei Yang <471184555@qq.com> +// Dun Liang . +// All Rights Reserved. // This file is subject to the terms and conditions defined in // file 'LICENSE.txt', which is part of this source code package. // *************************************************************** @@ -17,15 +20,21 @@ struct NumpyFunc { typedef NumpyResult R; std::function callback; std::function deleter; + std::function inc_ref; NumpyFunc() = default; - NumpyFunc(NumpyFunc&& other) : callback(other.callback), deleter(other.deleter) { + NumpyFunc(NumpyFunc&& other) : callback(other.callback), deleter(other.deleter), inc_ref(other.inc_ref) { other.callback = nullptr; other.deleter = nullptr; + other.inc_ref = nullptr; + }; + NumpyFunc(const NumpyFunc& other) : callback(other.callback), deleter(other.deleter), inc_ref(other.inc_ref) { + inc_ref(); }; - NumpyFunc(const NumpyFunc&) = delete; NumpyFunc(std::function&& callback) : callback(move(callback)) {} NumpyFunc(std::function&& callback, std::function&& deleter) : callback(move(callback)), deleter(move(deleter)) {}; + NumpyFunc(std::function&& callback, std::function&& deleter, std::function&& inc_ref) + : callback(move(callback)), deleter(move(deleter)), inc_ref(move(inc_ref)) {}; ~NumpyFunc() { if (deleter) { deleter(); @@ -36,9 +45,9 @@ struct NumpyFunc { struct NumpyResult { // vector allocations; - map> varrays; + map> varrays; map ints; - map arrays; + map arrays; // mem ptr, dtype, shape --> numpy array }; diff --git a/src/ops/numpy_code_op.cc b/src/ops/numpy_code_op.cc index 98a596f4..d74db0b2 100644 --- a/src/ops/numpy_code_op.cc +++ b/src/ops/numpy_code_op.cc @@ -1,5 +1,8 @@ // *************************************************************** -// Copyright (c) 2020 Jittor. Authors: Dun Liang . All Rights Reserved. +// Copyright (c) 2020 Jittor. Authors: +// Guowei Yang <471184555@qq.com> +// Dun Liang . +// All Rights Reserved. // This file is subject to the terms and conditions defined in // file 'LICENSE.txt', which is part of this source code package. // *************************************************************** @@ -13,7 +16,7 @@ namespace jittor { static auto make_numpy_code = get_op_info("numpy_code") - .get_constructor&&, NumpyFunc&&, NumpyResult&&>(); + .get_constructor&&, NumpyFunc, NumpyResult&&>(); static inline void check_vary_shape(NanoVector v) { ASSERT(v.size()) << "Vary shape should not be zero dimension"; @@ -33,7 +36,7 @@ NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inpu check_vary_shape(_outputs[0]->shape); } for (int i=0; i&& shapes, vector&& dtype } } for (int i=0; i&& inputs, NumpyFunc&& forward, NumpyResult&& results) - : _inputs(inputs), forward(move(forward)), _results(move(results)) +NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc forward, NumpyResult&& results) + : _inputs(inputs), forward(forward), _results(move(results)) { _outputs.push_back(create_output(shape, dtype)); CHECKop(_inputs.size(),<=,10); @@ -71,55 +74,48 @@ NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inpu VarPtr NumpyCodeOp::grad(Var* out, Var* dout, Var* v, int v_index) { NumpyResult result; - // set results - // set dout index - // result.ints["dout_index"] = _outputs.find(out); + + int out_index=-1; for (int i=0; i<_outputs.size(); i++) { if (_outputs[i] == out) { - result.ints["dout_index"] = i; + out_index = i; break; } } + ASSERT(out_index!=-1); + result.ints["out_index"] = out_index; result.arrays["dout"].ptr=dout; result.arrays["dout"].shape=dout->shape; result.arrays["dout"].dtype=dout->dtype(); auto inputs = clone(_inputs); inputs.push_back(dout); - // code op: - /* - return make_code( - _inputs[v_index]->shape, - _inputs[v_index]->dtype(), - move(inputs), - move(cpu_src), {}, alias+cpu_header, - move(cuda_src), {}, alias+cuda_header - ); - */ return make_numpy_code( _inputs[v_index]->shape, _inputs[v_index]->dtype(), - move(inputs), - move(backward[v_index]), + move(inputs), + backward[v_index], move(result)); } void NumpyCodeOp::run() { - NumpyResult result=move(_results); - vector inputs(_inputs.size()); - vector outputs(_outputs.size()); - /* - const void* ptr; - NanoVector shape; - NanoString dtype; - */ + NumpyResult result; + result.varrays = _results.varrays; + result.ints = _results.ints; + result.arrays = _results.arrays; + + if (result.arrays.count("dout") > 0){ + result.arrays["dout"].ptr=((Var*)result.arrays["dout"].ptr)->ptr(); + } + vector inputs(_inputs.size()); + vector outputs(_outputs.size()); for (int i=0; iptr(); + inputs[i].ptr=_inputs[i]->ptr(); inputs[i].shape=_inputs[i]->shape; inputs[i].dtype=_inputs[i]->dtype(); } for (int i=0; iptr(); + outputs[i].ptr=_outputs[i]->ptr(); outputs[i].shape=_outputs[i]->shape; outputs[i].dtype=_outputs[i]->dtype(); } diff --git a/src/ops/numpy_code_op.h b/src/ops/numpy_code_op.h index c364b1ab..35a88400 100644 --- a/src/ops/numpy_code_op.h +++ b/src/ops/numpy_code_op.h @@ -1,5 +1,8 @@ // *************************************************************** -// Copyright (c) 2020 Jittor. Authors: Dun Liang . All Rights Reserved. +// Copyright (c) 2020 Jittor. Authors: +// Guowei Yang <471184555@qq.com> +// Dun Liang . +// All Rights Reserved. // This file is subject to the terms and conditions defined in // file 'LICENSE.txt', which is part of this source code package. // *************************************************************** @@ -22,7 +25,7 @@ struct NumpyCodeOp : Op { NumpyCodeOp(vector&& shapes, vector&& dtypes, vector&& inputs, NumpyFunc&& forward, vector&& backward); // @pybind(None) - NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc&& forward, NumpyResult&& results); + NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc forward, NumpyResult&& results); const char* name() const override { return "numpy_code"; } VarPtr grad(Var* out, Var* dout, Var* v, int v_index) override; diff --git a/src/pyjt/py_converter.h b/src/pyjt/py_converter.h index 369963bb..ba66f79d 100644 --- a/src/pyjt/py_converter.h +++ b/src/pyjt/py_converter.h @@ -354,7 +354,6 @@ DEF_IS(VarHolder*, T) from_py_object(PyObject* obj, unique_ptr& holde struct DataView; DEF_IS(DataView, PyObject*) to_py_object(T a) { - auto obj = GET_OBJ_FROM_RAW_PTR(a.vh); int64 dims[a.shape.size()]; for (int i=0; i>>(result->varrays)); PyObjHolder data(to_py_object(result->varrays)); PyObjHolder data2(to_py_object(result->ints)); PyObjHolder data3(to_py_object(result->arrays)); - // data.update(data2) PyDict_Update(data.obj, data2.obj); - // data.update(data3) PyDict_Update(data.obj, data3.obj); + // args = [] - PyObjHolder args(PyList_New(0)); - int ok = PyList_Append(args.obj, np.obj); - ASSERT(ok); - ok = PyList_Append(args.obj, data.obj); - ASSERT(ok); + PyObjHolder args(PyTuple_New(2)); + PyTuple_SET_ITEM(args.obj, 0, np.obj); + PyTuple_SET_ITEM(args.obj, 1, data.obj); PyObjHolder ret(PyObject_Call(obj, args.obj, nullptr)); }, // deleter - [obj]() { Py_DECREF(obj); } + [obj]() { Py_DECREF(obj); }, + // inc_ref + [obj]() { Py_INCREF(obj); } ); return func; } From a6caacf54ed222e4477dd9dacdf0f76ce6d7fc97 Mon Sep 17 00:00:00 2001 From: Gword <471184555@qq.com> Date: Mon, 13 Jul 2020 21:17:33 +0800 Subject: [PATCH 4/7] update --- python/jittor/test/test_numpy_code_op.py | 2 - src/numpy_func.h | 2 - src/ops/numpy_code_op.cc | 33 +++----- src/ops/numpy_code_op.h | 96 +++++++++++++++++++++++- src/pyjt/py_converter.h | 2 +- 5 files changed, 105 insertions(+), 30 deletions(-) diff --git a/python/jittor/test/test_numpy_code_op.py b/python/jittor/test/test_numpy_code_op.py index 9258bf03..e127250f 100644 --- a/python/jittor/test/test_numpy_code_op.py +++ b/python/jittor/test/test_numpy_code_op.py @@ -16,11 +16,9 @@ class TestCodeOp(unittest.TestCase): c,d = data["outputs"] np.add(a,b,out=c) np.subtract(a,b,out=d) - p, r = c.__array_interface__['data'] def backward_code1(self, np, data): dout = data["dout"] - a,b,dout = data["inputs"] out = data["outputs"][0] np.copyto(out, dout) diff --git a/src/numpy_func.h b/src/numpy_func.h index 4ab01dee..4fb8edf1 100644 --- a/src/numpy_func.h +++ b/src/numpy_func.h @@ -44,11 +44,9 @@ struct NumpyFunc { }; struct NumpyResult { - // vector allocations; map> varrays; map ints; map arrays; - // mem ptr, dtype, shape --> numpy array }; } // jittor \ No newline at end of file diff --git a/src/ops/numpy_code_op.cc b/src/ops/numpy_code_op.cc index d74db0b2..0e2f61fd 100644 --- a/src/ops/numpy_code_op.cc +++ b/src/ops/numpy_code_op.cc @@ -30,11 +30,7 @@ NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inpu { _outputs.push_back(create_output(shape, dtype)); CHECKop(_inputs.size(),<=,10); - - if (_outputs[0]->num < 0) { - flags.set(NodeFlags::_vary_shape); - check_vary_shape(_outputs[0]->shape); - } + ASSERT(_outputs[0]->num >= 0); for (int i=0; i&& shapes, vector&& dtype CHECKop(_outputs.size(),>,0); for (int i=0; inum < 0) { - flags.set(NodeFlags::_vary_shape); - check_vary_shape(_outputs[i]->shape); - } + ASSERT(_outputs[i]->num >= 0); } for (int i=0; i&& inpu : _inputs(inputs), forward(forward), _results(move(results)) { _outputs.push_back(create_output(shape, dtype)); - CHECKop(_inputs.size(),<=,10); - - if (_outputs[0]->num < 0) { - flags.set(NodeFlags::_vary_shape); - check_vary_shape(_outputs[0]->shape); - } + CHECKop(_inputs.size(),<=,10) + ASSERT(_outputs[0]->num >= 0); } VarPtr NumpyCodeOp::grad(Var* out, Var* dout, Var* v, int v_index) { - NumpyResult result; + NumpyResult result; int out_index=-1; for (int i=0; i<_outputs.size(); i++) { @@ -84,18 +73,18 @@ VarPtr NumpyCodeOp::grad(Var* out, Var* dout, Var* v, int v_index) { } ASSERT(out_index!=-1); result.ints["out_index"] = out_index; - result.arrays["dout"].ptr=dout; + result.arrays["dout"].ptr=dout; result.arrays["dout"].shape=dout->shape; result.arrays["dout"].dtype=dout->dtype(); auto inputs = clone(_inputs); inputs.push_back(dout); - return make_numpy_code( + return make_numpy_code( _inputs[v_index]->shape, _inputs[v_index]->dtype(), - move(inputs), - backward[v_index], - move(result)); + move(inputs), + backward[v_index], + move(result)); } void NumpyCodeOp::run() { @@ -121,7 +110,7 @@ void NumpyCodeOp::run() { } result.varrays["inputs"] = move(inputs); result.varrays["outputs"] = move(outputs); - forward.callback(&result); + forward.callback(&result); } } // jittor diff --git a/src/ops/numpy_code_op.h b/src/ops/numpy_code_op.h index 35a88400..2ef16ed0 100644 --- a/src/ops/numpy_code_op.h +++ b/src/ops/numpy_code_op.h @@ -19,13 +19,103 @@ struct NumpyCodeOp : Op { vector backward; NumpyResult _results; + /** + Code Operator for easily customized op. + + ---------------- + + * [in] shape: the output shape, a integer array + + * [in] dtype: the output data type + + * [in] inputs: A list of input jittor Vars + + * [in] cpu_src: cpu source code string, buildin value: + + * in{x}, in{x}_shape{y}, in{x}_stride{y}, in{x}_type, in{x}_p, @in0(...) + * out{x}, out{x}_shape{y}, out{x}_stride{y}, out{x}_type, out{x}_p, @out0(...) + * out, out_shape{y}, out_stride{y}, out_type, out_p, @out(...) + + * [in] cpu_grad_src: A list of string, cpu source code string for gradient, represents gradiant for each inputm buildin value, buildin value: + + * in{x}, in{x}_shape{y}, in{x}_stride{y}, in{x}_type, in{x}_p, @in0(...) + * out{x}, out{x}_shape{y}, out{x}_stride{y}, out{x}_type, out{x}_p, @out0(...) + * out, out_shape{y}, out_stride{y}, out_type, out_p, @out(...) + * pout{x}, pout{x}_shape{y}, pout{x}_stride{y}, pout{x}_type, pout{x}_p, @pout{x}(...) + * pout, pout_shape{y}, pout_stride{y}, pout_type, pout_p, @pout(...) + * dout, dout_shape{y}, dout_stride{y}, dout_type, dout_p, @dout(...) + + * [in] cpu_header: cpu header code string. + + * [in] cuda_src: cuda source code string. + + * [in] cuda_grad_src: A list of string. + + * [in] cuda_header: cuda header code string. + + ---------------- + + Example-1:: + + def forward_code(self, np, data): + a = data["inputs"] + b = data["outputs"] + np.add(a,a,out=b) + + def backward_code(self, np, data): + dout = data["dout"] + out = data["outputs"][0] + np.copyto(out, dout) + + a = jt.random((5,1)) + c, d = jt.numpy_code( + a.shape, + a.dtype, + [a], + forward_code, + [backward_code], + ) + + Example-2:: + + def forward_code(self, np, data): + a,b = data["inputs"] + c,d = data["outputs"] + np.add(a,b,out=c) + np.subtract(a,b,out=d) + + def backward_code1(self, np, data): + dout = data["dout"] + out = data["outputs"][0] + np.copyto(out, dout) + + def backward_code2(self, np, data): + dout = data["dout"] + out_index = data["out_index"] + out = data["outputs"][0] + if out_index==0: + np.copyto(out, dout) + else: + np.negative(dout, out) + + a = jt.random((5,1)) + b = jt.random((5,1)) + c, d = jt.numpy_code( + [a.shape, a.shape], + [a.dtype, a.dtype], + [a, b], + forward_code, + [backward_code1,backward_code2], + ) + + */ NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc&& forward, vector&& backward); // @attrs(multiple_outputs) NumpyCodeOp(vector&& shapes, vector&& dtypes, vector&& inputs, NumpyFunc&& forward, vector&& backward); - - // @pybind(None) - NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc forward, NumpyResult&& results); + + // @pybind(None) + NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc forward, NumpyResult&& results); const char* name() const override { return "numpy_code"; } VarPtr grad(Var* out, Var* dout, Var* v, int v_index) override; diff --git a/src/pyjt/py_converter.h b/src/pyjt/py_converter.h index ba66f79d..b97ff57a 100644 --- a/src/pyjt/py_converter.h +++ b/src/pyjt/py_converter.h @@ -67,7 +67,7 @@ DEF_IS(int, bool) is_type(PyObject* obj) { return PyLong_CheckExact(obj); } -DEF_IS(int, PyObject*) to_py_object(const int& a) { +DEF_IS(int, PyObject*) to_py_object(const T& a) { return PyLong_FromLong(a); } From 96883622c6d59f6ff6b48dd0ec86e7c045f33926 Mon Sep 17 00:00:00 2001 From: Gword <471184555@qq.com> Date: Mon, 13 Jul 2020 22:09:56 +0800 Subject: [PATCH 5/7] update --- python/jittor/test/test_numpy_code_op.py | 113 ++++++++++++++++++----- src/ops/numpy_code_op.cc | 2 +- src/ops/numpy_code_op.h | 18 ++-- src/pyjt/py_converter.h | 4 +- 4 files changed, 101 insertions(+), 36 deletions(-) diff --git a/python/jittor/test/test_numpy_code_op.py b/python/jittor/test/test_numpy_code_op.py index e127250f..90c42c8b 100644 --- a/python/jittor/test/test_numpy_code_op.py +++ b/python/jittor/test/test_numpy_code_op.py @@ -11,38 +11,60 @@ import jittor as jt import numpy as np class TestCodeOp(unittest.TestCase): - def forward_code(self, np, data): - a,b = data["inputs"] - c,d = data["outputs"] - np.add(a,b,out=c) - np.subtract(a,b,out=d) - - def backward_code1(self, np, data): - dout = data["dout"] - out = data["outputs"][0] - np.copyto(out, dout) - - def backward_code2(self, np, data): - dout = data["dout"] - out_index = data["out_index"] - out = data["outputs"][0] - if out_index==0: - np.copyto(out, dout) - else: - np.negative(dout, out) - def test(self): + def forward_code(np, data): + a = data["inputs"][0] + b = data["outputs"][0] + np.add(a,a,out=b) + + def backward_code(np, data): + dout = data["dout"] + out = data["outputs"][0] + np.copyto(out, dout*2.0) + + a = jt.random((5,1)) + b = jt.numpy_code( + a.shape, + a.dtype, + [a], + forward_code, + [backward_code], + ) + assert np.allclose(b.data,(a+a).data) + da = jt.grad(b,a) + one=np.ones(a.shape) + assert np.allclose(da.data,one*2.0) + + def test_multi_input(self): + def forward_code(np, data): + a,b = data["inputs"] + c,d = data["outputs"] + np.add(a,b,out=c) + np.subtract(a,b,out=d) + + def backward_code1(np, data): + dout = data["dout"] + out = data["outputs"][0] + np.copyto(out, dout) + + def backward_code2(np, data): + dout = data["dout"] + out_index = data["out_index"] + out = data["outputs"][0] + if out_index==0: + np.copyto(out, dout) + else: + np.negative(dout, out) + a = jt.random((5,1)) b = jt.random((5,1)) - c, d = jt.numpy_code( [a.shape, a.shape], [a.dtype, a.dtype], [a, b], - self.forward_code, - [self.backward_code1,self.backward_code2], + forward_code, + [backward_code1,backward_code2], ) - assert np.allclose(c.data,(a+b).data) assert np.allclose(d.data,(a-b).data) dca, dcb = jt.grad(c,[a,b]) @@ -54,5 +76,48 @@ class TestCodeOp(unittest.TestCase): assert np.allclose(dda.data,one) assert np.allclose(ddb.data,mone) + @unittest.skipIf(True, "Memory leak testing is not in progress, Skip") + def test_memory_leak(self): + def forward_code(np, data): + a,b = data["inputs"] + c,d = data["outputs"] + np.add(a,b,out=c) + np.subtract(a,b,out=d) + + def backward_code1(np, data): + dout = data["dout"] + out = data["outputs"][0] + np.copyto(out, dout) + + def backward_code2(np, data): + dout = data["dout"] + out_index = data["out_index"] + out = data["outputs"][0] + if out_index==0: + np.copyto(out, dout) + else: + np.negative(dout, out) + + for i in range(1000000): + a = jt.random((10000,1)) + b = jt.random((10000,1)) + c, d = jt.numpy_code( + [a.shape, a.shape], + [a.dtype, a.dtype], + [a, b], + forward_code, + [backward_code1,backward_code2], + ) + assert np.allclose(c.data,(a+b).data) + assert np.allclose(d.data,(a-b).data) + dca, dcb = jt.grad(c,[a,b]) + dda, ddb = jt.grad(d,[a,b]) + one=np.ones(a.shape) + mone=one*-1.0 + assert np.allclose(dca.data,one) + assert np.allclose(dcb.data,one) + assert np.allclose(dda.data,one) + assert np.allclose(ddb.data,mone) + if __name__ == "__main__": unittest.main() \ No newline at end of file diff --git a/src/ops/numpy_code_op.cc b/src/ops/numpy_code_op.cc index 0e2f61fd..9587417a 100644 --- a/src/ops/numpy_code_op.cc +++ b/src/ops/numpy_code_op.cc @@ -57,7 +57,7 @@ NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inpu : _inputs(inputs), forward(forward), _results(move(results)) { _outputs.push_back(create_output(shape, dtype)); - CHECKop(_inputs.size(),<=,10) + CHECKop(_inputs.size(),<=,10); ASSERT(_outputs[0]->num >= 0); } diff --git a/src/ops/numpy_code_op.h b/src/ops/numpy_code_op.h index 2ef16ed0..479c1146 100644 --- a/src/ops/numpy_code_op.h +++ b/src/ops/numpy_code_op.h @@ -57,18 +57,18 @@ struct NumpyCodeOp : Op { Example-1:: - def forward_code(self, np, data): - a = data["inputs"] - b = data["outputs"] + def forward_code(np, data): + a = data["inputs"][0] + b = data["outputs"][0] np.add(a,a,out=b) - def backward_code(self, np, data): + def backward_code(np, data): dout = data["dout"] out = data["outputs"][0] - np.copyto(out, dout) + np.copyto(out, dout*2.0) a = jt.random((5,1)) - c, d = jt.numpy_code( + b = jt.numpy_code( a.shape, a.dtype, [a], @@ -78,18 +78,18 @@ struct NumpyCodeOp : Op { Example-2:: - def forward_code(self, np, data): + def forward_code(np, data): a,b = data["inputs"] c,d = data["outputs"] np.add(a,b,out=c) np.subtract(a,b,out=d) - def backward_code1(self, np, data): + def backward_code1(np, data): dout = data["dout"] out = data["outputs"][0] np.copyto(out, dout) - def backward_code2(self, np, data): + def backward_code2(np, data): dout = data["dout"] out_index = data["out_index"] out = data["outputs"][0] diff --git a/src/pyjt/py_converter.h b/src/pyjt/py_converter.h index b97ff57a..7beff471 100644 --- a/src/pyjt/py_converter.h +++ b/src/pyjt/py_converter.h @@ -578,8 +578,8 @@ DEF_IS(NumpyFunc, T) from_py_object(PyObject* obj) { // args = [] PyObjHolder args(PyTuple_New(2)); - PyTuple_SET_ITEM(args.obj, 0, np.obj); - PyTuple_SET_ITEM(args.obj, 1, data.obj); + PyTuple_SET_ITEM(args.obj, 0, np.release()); + PyTuple_SET_ITEM(args.obj, 1, data.release()); PyObjHolder ret(PyObject_Call(obj, args.obj, nullptr)); }, // deleter From 928977cff00191fa26d8aed911f7afa89596431b Mon Sep 17 00:00:00 2001 From: Gword <471184555@qq.com> Date: Tue, 14 Jul 2020 17:49:11 +0800 Subject: [PATCH 6/7] merge --- src/grad.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/grad.cc b/src/grad.cc index e3f7ca4c..78fe28ec 100644 --- a/src/grad.cc +++ b/src/grad.cc @@ -92,10 +92,6 @@ vector grad(Var* loss, vector targets) { Op* op = it.op; auto index = it.index; if (op->tflag != nt) continue; -<<<<<<< HEAD - // TODO: support two outputs backprop. -======= ->>>>>>> b27082f9444a4e627f7dfc574d0114302ba27b5e for (Var* out : op->outputs()) { if (out->tflag != nt) continue; Var* dout = grads[out->custom_data]; From 784d089c842cf420312e0d4f0188ae0b5a10c0c3 Mon Sep 17 00:00:00 2001 From: Gword <471184555@qq.com> Date: Tue, 14 Jul 2020 17:59:27 +0800 Subject: [PATCH 7/7] update --- src/ops/numpy_code_op.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/ops/numpy_code_op.cc b/src/ops/numpy_code_op.cc index 9587417a..08319823 100644 --- a/src/ops/numpy_code_op.cc +++ b/src/ops/numpy_code_op.cc @@ -17,13 +17,6 @@ namespace jittor { static auto make_numpy_code = get_op_info("numpy_code") .get_constructor&&, NumpyFunc, NumpyResult&&>(); - -static inline void check_vary_shape(NanoVector v) { - ASSERT(v.size()) << "Vary shape should not be zero dimension"; - for (int i=0; i= 0)) - << "Vary shape should only occur in the first dimension:" << v; -} NumpyCodeOp::NumpyCodeOp(NanoVector shape, NanoString dtype, vector&& inputs, NumpyFunc&& forward, vector&& sbackward) : _inputs(inputs), forward(move(forward))