/* Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "paddle/fluid/pybind/jit.h" #include "glog/logging.h" #include "paddle/fluid/framework/variable.h" #include "paddle/fluid/imperative/layer.h" #include "paddle/fluid/jit/function.h" #include "paddle/fluid/jit/function_schema.h" #include "paddle/fluid/jit/layer.h" #include "paddle/fluid/jit/serializer.h" #include "paddle/fluid/pybind/sot/eval_frame.h" #include "paddle/fluid/pybind/sot/eval_frame_tools.h" #include "paddle/fluid/pybind/sot/frame_proxy.h" #include "paddle/fluid/pybind/sot/guards.h" #include "paddle/fluid/pybind/sot/macros.h" #include "paddle/phi/common/data_type.h" #include "paddle/phi/common/place.h" #include "paddle/utils/pybind.h" #include "pybind11/pybind11.h" #include "pybind11/pytypes.h" namespace py = pybind11; namespace paddle::pybind { PyTypeObject *g_jit_function_pytype = nullptr; using Variable = paddle::framework::Variable; void BindJit(pybind11::module *m) { py::class_(*m, "Layer", R"DOC(Layer Class.)DOC") .def("function_names", &jit::Layer::FunctionNames) .def("function", &jit::Layer::Function) .def("function_info", &jit::Layer::FunctionInfo); py::class_> function( *m, "Function", R"DOC(Function Class.)DOC"); g_jit_function_pytype = reinterpret_cast(function.ptr()); py::class_>( *m, "FunctionInfo", R"DOC(BaseFunctionInfo Class.)DOC") .def("name", &jit::BaseFunctionInfo::FunctionName) .def("input_names", &jit::BaseFunctionInfo::InputArgNames) .def("output_names", &jit::BaseFunctionInfo::OutputArgNames); m->def("Load", [](const std::string &path, const CPUPlace &cpu_place) { return paddle::jit::Load(path, cpu_place); }); m->def("Load", [](const std::string &path, const GPUPlace &cuda_place) { return paddle::jit::Load(path, cuda_place); }); } void BindGuard(pybind11::module *m) { #if SOT_IS_SUPPORTED py::class_>( *m, "GuardBase", R"DOC(GuardBase Class.)DOC") .def("check", &GuardBase::check_pybind); py::class_>( *m, "LambdaGuard", R"DOC(LambdaGuard Class.)DOC") .def(py::init(), py::arg("guard_check_fn")); py::class_>( *m, "GuardGroup", R"DOC(GuardGroup Class.)DOC") .def(py::init> &>(), py::arg("guards")); py::class_>( *m, "TypeMatchGuard", R"DOC(TypeMatchGuard Class.)DOC") .def(py::init(), py::arg("py_type")); py::class_>( *m, "IdMatchGuard", R"DOC(IdMatchGuard Class.)DOC") .def(py::init(), py::arg("py_obj")); py::class_>( *m, "LengthMatchGuard", R"DOC(LengthMatchGuard Class.)DOC") .def(py::init(), py::arg("length")); py::class_>( *m, "ValueMatchGuard", R"DOC(ValueMatchGuard Class.)DOC") .def(py::init(), py::arg("py_value")); py::class_>( *m, "DtypeMatchGuard", R"DOC(DtypeMatchGuard Class.)DOC") .def(py::init(), py::arg("dtype")) .def(py::init(), py::arg("dtype")); py::class_>( *m, "AttributeMatchGuard", R"DOC(AttributeMatchGuard Class.)DOC") .def(py::init(), py::arg("obj"), py::arg("attr_name")); py::class_>( *m, "ShapeMatchGuard", R"DOC(ShapeMatchGuard Class.)DOC") .def(py::init &, int64_t>(), py::arg("shape"), py::arg("min_non_specialized_number")); py::class_>( *m, "LayerMatchGuard", R"DOC(LayerMatchGuard Class.)DOC") .def(py::init(), py::arg("layer_obj")); py::class_>( *m, "InstanceCheckGuard", R"DOC(InstanceCheckGuard Class.)DOC") .def(py::init(), py::arg("isinstance_obj")); py::class_>( *m, "NumPyDtypeMatchGuard", R"DOC(NumPyDtypeMatchGuard Class.)DOC") .def(py::init(), py::arg("dtype")); py::class_>( *m, "NumPyArrayValueMatchGuard", R"DOC(NumPyArrayValueMatchGuard Class.)DOC") .def(py::init(), py::arg("array")); py::class_>( *m, "NumPyArrayShapeMatchGuard", R"DOC(NumPyArrayShapeMatchGuard Class.)DOC") .def(py::init &, int64_t>(), py::arg("shape"), py::arg("min_non_specialized_number")); py::class_>( *m, "WeakRefMatchGuard", R"DOC(WeakRefMatchGuard Class.)DOC") .def(py::init(), py::arg("func")); py::class_>( *m, "IsNotDenseTensorHoldAllocationMatchGuard", R"DOC(IsNotDenseTensorHoldAllocationMatchGuard Class.)DOC") .def(py::init()); m->def( "merge_guard", [](const std::vector> &py_guards) { return GuardGroup(py_guards); }, py::arg("py_guards")); #endif } void BindGuardTree(pybind11::module *m) { #if SOT_IS_SUPPORTED py::class_>( *m, "GuardTree", R"DOC(GuardTree Class.)DOC") .def(py::init>> &>(), py::arg("guard_chain_list")) .def_property_readonly( "guard_nodes", [](GuardTree &self) { return self.get_guard_nodes(); }) .def( "lookup", [](GuardTree &self, py::object frame) { return self.lookup(reinterpret_cast(frame.ptr())); }, py::arg("frame")) .def( "add_guard_chain", [](GuardTree &self, const std::vector> &guard_chain) { self.add_guard_chain(guard_chain); }, py::arg("guard_chain")) .def("stringify", &GuardTree::stringify); py::class_>( *m, "GuardNodeBase", R"DOC(GuardNodeBase Class.)DOC") .def_property( "return_cache_index", [](GuardNodeBase &self) { return self.return_cache_index; }, [](GuardNodeBase &self, int index) { self.return_cache_index = index; }) .def_property( "next_guard_nodes", [](GuardNodeBase &self) { return self.next_guard_nodes; }, [](GuardNodeBase &self, const std::vector> &next_guard_nodes) { self.next_guard_nodes = next_guard_nodes; }) .def( "lookup", [](GuardNodeBase &self, py::object frame) { return self.lookup(reinterpret_cast(frame.ptr())); }, py::arg("frame")); py::class_, GuardNodeBase, std::shared_ptr>>(*m, "CheckGuardNode0") .def_property_readonly("exprs", [](CheckGuardNode<0> &self) { return self.exprs; }) .def("get_guard_name", &CheckGuardNode<0>::get_guard_name); py::class_, GuardNodeBase, std::shared_ptr>>(*m, "CheckGuardNode1") .def_property_readonly("exprs", [](CheckGuardNode<1> &self) { return self.exprs; }) .def("get_guard_name", &CheckGuardNode<1>::get_guard_name); py::class_, GuardNodeBase, std::shared_ptr>>(*m, "CheckGuardNode2") .def_property_readonly("exprs", [](CheckGuardNode<2> &self) { return self.exprs; }) .def("get_guard_name", &CheckGuardNode<2>::get_guard_name); py::class_, std::shared_ptr>( *m, "IsGradEnabledGuardNode", R"DOC(IsGradEnabledGuardNode Class.)DOC") .def(py::init> &, const std::optional &>(), py::arg("is_grad_enabled"), py::arg("next_guard_nodes") = py::list(), py::arg("return_cache_index") = py::none()); py::class_, std::shared_ptr>( *m, "GuardNode", R"DOC(GuardNode Class.)DOC") .def(py::init &, const std::array, 1> &, const std::vector> &, const std::optional &>(), py::arg("guard"), py::arg("exprs"), py::arg("next_guard_nodes") = py::list(), py::arg("return_cache_index") = py::none()) .def_property_readonly("guard", [](LegacyGuardNode &self) { return self.guard; }); py::class_, std::shared_ptr>( *m, "TensorDistMetaMatchGuardNode", R"DOC(TensorDistMetaMatchGuardNode Class.)DOC") .def(py::init, 2> &, const std::vector> &, const std::optional &>(), py::arg("dist_info"), py::arg("exprs"), py::arg("next_guard_nodes") = py::list(), py::arg("return_cache_index") = py::none()); py::class_>( *m, "ExprGuardNode", R"DOC(ExprGuardNode Class.)DOC") .def(py::init &, const std::vector> &, const std::optional &>(), py::arg("expr"), py::arg("next_guard_nodes") = py::list(), py::arg("return_cache_index") = py::none()); py::class_>( *m, "DummyGuardNode", R"DOC(DummyGuardNode Class.)DOC") .def(py::init> &, const std::optional &>(), py::arg("return_true") = true, py::arg("next_guard_nodes") = py::list(), py::arg("return_cache_index") = py::none()); py::class_>( *m, "ExprNodeBase", R"DOC(ExprNodeBase Class.)DOC") .def( "eval", [](ExprNodeBase &self, py::object frame) { return self.eval(reinterpret_cast(frame.ptr())); }, py::arg("frame")) .def("stringify", &ExprNodeBase::stringify, py::arg("indent") = 0); py::class_>( *m, "ConstantExprNode", R"DOC(ConstantExprNode Class.)DOC") .def(py::init(), py::arg("value_ptr")); py::class_>( *m, "ExternVarExprNode", R"DOC(ExternVarExprNode Class.)DOC") .def(py::init(), py::arg("var_name"), py::arg("value_ptr")); py::class_>( *m, "LocalVarExprNode", R"DOC(LocalVarExprNode Class.)DOC") .def(py::init(), py::arg("var_name")); py::class_>( *m, "GlobalVarExprNode", R"DOC(GlobalVarExprNode Class.)DOC") .def(py::init(), py::arg("var_name")); py::class_>( *m, "AttributeExprNode", R"DOC(AttributeExprNode Class.)DOC") .def(py::init, const std::string &>(), py::arg("var_expr"), py::arg("attr_name")); py::class_>( *m, "ItemExprNode", R"DOC(ItemExprNode Class.)DOC") .def(py::init, std::shared_ptr>(), py::arg("var_expr"), py::arg("key_expr")); py::class_>( *m, "BinaryExprNode", R"DOC(BinaryExprNode Class.)DOC") .def(py::init, std::shared_ptr, const std::string &>(), py::arg("lhs"), py::arg("rhs"), py::arg("op")); py::class_>( *m, "UnaryExprNode", R"DOC(UnaryExprNode Class.)DOC") .def(py::init, const std::string &>(), py::arg("expr"), py::arg("op")); #endif } void BindSot(pybind11::module *m) { #if SOT_IS_SUPPORTED PyInit__eval_frame(); #if PY_3_11_PLUS PyInit__frame_proxy(); #endif m->def( "set_eval_frame", [](const py::object &py_func) { VLOG(5) << "start call set_eval_frame_py."; auto ret = set_eval_frame_py(py_func.ptr()); auto obj = py::reinterpret_borrow(ret); return obj; }, py::arg("callback")); m->def("has_custom_getattro", [](py::object obj) { PyObject *py_obj = obj.ptr(); if (!PyType_Check(py_obj)) { PADDLE_THROW(common::errors::InvalidArgument( "The input object should be a type object, but got %s.", py::str(py_obj).cast())); } PyTypeObject *type = reinterpret_cast(py_obj); return type->tp_getattro != PyObject_GenericGetAttr; }); m->def( "sot_setup_codes_with_graph", [](const py::object &py_codes) { auto ret = setup_codes_with_graph(py_codes.ptr()); auto obj = py::reinterpret_borrow(ret); return obj; }, py::arg("py_codes")); m->def( "sot_set_with_graph", [](const py::object &py_codes) { auto ret = set_with_graph(py_codes.ptr()); auto obj = py::reinterpret_borrow(ret); return obj; }, py::arg("py_codes")); m->def( "eval_frame_no_skip_codes", [](const py::object &py_codes) { auto ret = no_skip_codes(py_codes.ptr()); auto obj = py::reinterpret_borrow(ret); return obj; }, py::arg("py_codes")); m->def( "eval_frame_skip_file_prefix", [](const py::object &py_codes) { auto ret = skip_file_prefix(py_codes.ptr()); auto obj = py::reinterpret_borrow(ret); return obj; }, py::arg("py_codes")); BindGuard(m); BindGuardTree(m); #endif } } // namespace paddle::pybind