diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 00097c25d2ba5..ce22def914851 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -123,7 +123,6 @@ option(onnxruntime_GCOV_COVERAGE "Compile with options necessary to run code cov option(onnxruntime_DONT_VECTORIZE "Do not vectorize operations in Eigen" OFF) option(onnxruntime_USE_FULL_PROTOBUF "Link to libprotobuf instead of libprotobuf-lite when this option is ON" OFF) -option(onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS "Enable operator implemented in language other than cpp" OFF) option(onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS "Dump debug information about node inputs and outputs when executing the model." OFF) cmake_dependent_option(onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS_ENABLE_DUMP_TO_SQLDB "Build dump debug information about node inputs and outputs with support for sql database." OFF "onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS" OFF) option(onnxruntime_USE_DML "Build with DirectML support" OFF) @@ -439,13 +438,6 @@ if (onnxruntime_ENABLE_MEMORY_PROFILE) endif() set(ONNX_ML 1) -if (NOT onnxruntime_ENABLE_PYTHON) - set(onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS OFF) -endif() - -if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS) - add_compile_definitions(ENABLE_LANGUAGE_INTEROP_OPS) -endif() if (NOT (UNIX AND onnxruntime_ENABLE_PYTHON AND onnxruntime_ENABLE_TRAINING AND (NOT onnxruntime_BUILD_SHARED_LIB))) if (onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) @@ -578,7 +570,7 @@ endif() #Need python to generate def file if (onnxruntime_BUILD_SHARED_LIB OR onnxruntime_ENABLE_PYTHON) if (onnxruntime_ENABLE_PYTHON) - if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS OR onnxruntime_REQUIRE_PYTHON_EMBED_LIB) + if (onnxruntime_REQUIRE_PYTHON_EMBED_LIB) find_package(Python 3.8 COMPONENTS Interpreter Development NumPy) else() find_package(Python 3.8 COMPONENTS Interpreter Development.Module NumPy) diff --git a/cmake/onnxruntime.cmake b/cmake/onnxruntime.cmake index e15c8a046dc20..977aa44b0e8d7 100644 --- a/cmake/onnxruntime.cmake +++ b/cmake/onnxruntime.cmake @@ -205,13 +205,6 @@ set(onnxruntime_INTERNAL_LIBRARIES onnxruntime_flatbuffers ) -if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS) - list(APPEND onnxruntime_INTERNAL_LIBRARIES - onnxruntime_language_interop - onnxruntime_pyop - ) -endif() - if (onnxruntime_USE_EXTENSIONS) list(APPEND onnxruntime_INTERNAL_LIBRARIES onnxruntime_extensions diff --git a/cmake/onnxruntime_language_interop_ops.cmake b/cmake/onnxruntime_language_interop_ops.cmake deleted file mode 100644 index 5d88332eb2e9a..0000000000000 --- a/cmake/onnxruntime_language_interop_ops.cmake +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -include(onnxruntime_pyop.cmake) -file (GLOB onnxruntime_language_interop_ops_src "${ONNXRUNTIME_ROOT}/core/language_interop_ops/language_interop_ops.cc") -onnxruntime_add_static_library(onnxruntime_language_interop ${onnxruntime_language_interop_ops_src}) -add_dependencies(onnxruntime_language_interop onnxruntime_pyop) -onnxruntime_add_include_to_target(onnxruntime_language_interop onnxruntime_common onnxruntime_graph onnxruntime_framework onnxruntime_pyop onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers safeint_interface Boost::mp11) -target_include_directories(onnxruntime_language_interop PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS}) \ No newline at end of file diff --git a/cmake/onnxruntime_pyop.cmake b/cmake/onnxruntime_pyop.cmake deleted file mode 100644 index f7583690945a1..0000000000000 --- a/cmake/onnxruntime_pyop.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -onnxruntime_add_static_library(onnxruntime_pyop "${ONNXRUNTIME_ROOT}/core/language_interop_ops/pyop/pyop.cc") -add_dependencies(onnxruntime_pyop ${onnxruntime_EXTERNAL_DEPENDENCIES}) -onnxruntime_add_include_to_target(onnxruntime_pyop onnxruntime_common onnxruntime_graph onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers ${GSL_TARGET} Boost::mp11) -target_include_directories(onnxruntime_pyop PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS}) -onnxruntime_add_include_to_target(onnxruntime_pyop Python::Module Python::NumPy) -if (TARGET Python::Python) - target_link_libraries(onnxruntime_pyop PRIVATE Python::Python) -else() - target_link_libraries(onnxruntime_pyop PRIVATE Python::Module) -endif() diff --git a/cmake/onnxruntime_python.cmake b/cmake/onnxruntime_python.cmake index da5732e484d6b..3c2833d87d652 100644 --- a/cmake/onnxruntime_python.cmake +++ b/cmake/onnxruntime_python.cmake @@ -193,10 +193,6 @@ target_link_libraries(onnxruntime_pybind11_state PRIVATE ${pybind11_lib} ) -if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS) - target_link_libraries(onnxruntime_pybind11_state PRIVATE onnxruntime_language_interop onnxruntime_pyop) -endif() - set(onnxruntime_pybind11_state_dependencies ${onnxruntime_EXTERNAL_DEPENDENCIES} ${pybind11_dep} @@ -1027,6 +1023,3 @@ if (onnxruntime_USE_QNN) endif() endif() -if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS) - include(onnxruntime_language_interop_ops.cmake) -endif() diff --git a/cmake/onnxruntime_training.cmake b/cmake/onnxruntime_training.cmake index f9ba2b341f741..01590a431205c 100644 --- a/cmake/onnxruntime_training.cmake +++ b/cmake/onnxruntime_training.cmake @@ -141,10 +141,6 @@ if (onnxruntime_BUILD_UNIT_TESTS) Boost::mp11 safeint_interface ) - if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS) - list(APPEND ONNXRUNTIME_LIBS onnxruntime_language_interop onnxruntime_pyop) - endif() - if(UNIX AND NOT APPLE) if (HAS_NO_MAYBE_UNINITIALIZED) target_compile_options(onnxruntime_training_mnist PUBLIC "-Wno-maybe-uninitialized") diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index fb96fd1cad39d..ed71e7a57a500 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -583,10 +583,6 @@ if(onnxruntime_USE_ARMNN) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_armnn) endif() -if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS) - set(ONNXRUNTIME_INTEROP_TEST_LIBS PRIVATE onnxruntime_language_interop onnxruntime_pyop) -endif() - set(ONNXRUNTIME_TEST_LIBS onnxruntime_session ${ONNXRUNTIME_INTEROP_TEST_LIBS} @@ -916,10 +912,6 @@ endif() if (onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS) target_compile_definitions(onnxruntime_test_all PRIVATE DEBUG_NODE_INPUTS_OUTPUTS) endif() - -if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS) - target_link_libraries(onnxruntime_test_all PRIVATE onnxruntime_language_interop onnxruntime_pyop) -endif() if (onnxruntime_USE_ROCM) if (onnxruntime_USE_COMPOSABLE_KERNEL) target_compile_definitions(onnxruntime_test_all PRIVATE USE_COMPOSABLE_KERNEL) @@ -1057,10 +1049,6 @@ set(onnx_test_libs onnx_test_data_proto ${onnxruntime_EXTERNAL_LIBRARIES}) -if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS) - list(APPEND onnx_test_libs onnxruntime_language_interop onnxruntime_pyop) -endif() - if (NOT IOS) onnxruntime_add_executable(onnx_test_runner ${onnx_test_runner_src_dir}/main.cc) if(MSVC) @@ -1241,10 +1229,6 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) endif() set_target_properties(onnxruntime_perf_test PROPERTIES FOLDER "ONNXRuntimeTest") - if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS AND NOT onnxruntime_BUILD_SHARED_LIB) - target_link_libraries(onnxruntime_perf_test PRIVATE onnxruntime_language_interop onnxruntime_pyop) - endif() - if (onnxruntime_USE_TVM) if (WIN32) target_link_options(onnxruntime_perf_test PRIVATE "/STACK:4000000") @@ -1474,10 +1458,6 @@ endif() onnxruntime_flatbuffers ) - if (onnxruntime_ENABLE_LANGUAGE_INTEROP_OPS) - list(APPEND ONNXRUNTIME_TEST_LIBS onnxruntime_language_interop onnxruntime_pyop) - endif() - target_link_libraries(onnxruntime_test_trainer PRIVATE ${ONNXRUNTIME_TEST_LIBS} ${onnxruntime_EXTERNAL_LIBRARIES} diff --git a/onnxruntime/core/language_interop_ops/language_interop_ops.cc b/onnxruntime/core/language_interop_ops/language_interop_ops.cc deleted file mode 100644 index b40ee08479055..0000000000000 --- a/onnxruntime/core/language_interop_ops/language_interop_ops.cc +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "language_interop_ops.h" -#include "core/framework/tensorprotoutils.h" -#include "core/platform/env.h" -#include "core/session/inference_session.h" -#include "pyop/pyop.h" -#include - -namespace onnxruntime { - -void LoadInterOp(const std::basic_string& model_uri, InterOpDomains& domains, const InterOpLogFunc& log_func) { - int fd; - - // match the error message from model.cc to keep the nodejs tests happy. - // as this is deprecated just cut-and-paste equivalent code for now. - auto status = Env::Default().FileOpenRd(model_uri, fd); - if (!status.IsOK()) { - if (status.Category() == common::SYSTEM) { - switch (status.Code()) { - case ENOENT: - status = ORT_MAKE_STATUS(ONNXRUNTIME, NO_SUCHFILE, "Load model ", ToUTF8String(model_uri), - " failed. File doesn't exist"); - break; - case EINVAL: - status = ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Load model ", ToUTF8String(model_uri), " failed"); - break; - default: - status = ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "system error number ", status.Code()); - } - } - } - - ORT_ENFORCE(status.IsOK(), status.ErrorMessage()); - - google::protobuf::io::FileInputStream f(fd); - f.SetCloseOnDelete(true); - ONNX_NAMESPACE::ModelProto model_proto; - ORT_ENFORCE(model_proto.ParseFromZeroCopyStream(&f), "Failed to parse model proto"); - LoadInterOp(model_proto, domains, log_func); -} - -void LoadInterOp(const ONNX_NAMESPACE::ModelProto& model_proto, InterOpDomains& domains, const InterOpLogFunc& log_func) { - LoadInterOp(model_proto.graph(), domains, log_func); -} - -void LoadInterOp(const ONNX_NAMESPACE::GraphProto& graph_proto, InterOpDomains& domains, const InterOpLogFunc& log_func) { - for (int i = 0; i < graph_proto.node_size(); ++i) { - const auto& node_proto = graph_proto.node(i); - if (node_proto.op_type() == "PyOp") { - auto pyop_domain = Ort::CustomOpDomain(node_proto.domain().c_str()); - pyop_domain.Add(LoadPyOp(node_proto, log_func)); - domains.push_back(std::move(pyop_domain)); - } else { - for (int j = 0, limit = node_proto.attribute_size(); j < limit; ++j) { - const auto& attr = node_proto.attribute(j); - if (utils::HasGraph(attr)) { - LoadInterOp(attr.g(), domains, log_func); // load pyop in subgraph - } - } // for - } // else - } // for -} -} // namespace onnxruntime diff --git a/onnxruntime/core/language_interop_ops/language_interop_ops.h b/onnxruntime/core/language_interop_ops/language_interop_ops.h deleted file mode 100644 index 2ab5945b17bc2..0000000000000 --- a/onnxruntime/core/language_interop_ops/language_interop_ops.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -#pragma once -#include -#include -#include -#include "core/graph/graph.h" -#include "core/session/onnxruntime_cxx_api.h" - -namespace onnxruntime { -using InterOpLogFunc = std::function; -using InterOpDomains = std::vector; -void LoadInterOp(const std::basic_string& model_uri, InterOpDomains& domains, const InterOpLogFunc& log_func); -void LoadInterOp(const ONNX_NAMESPACE::ModelProto& model_proto, InterOpDomains& domains, const InterOpLogFunc& log_func); -void LoadInterOp(const ONNX_NAMESPACE::GraphProto& graph_proto, InterOpDomains& domains, const InterOpLogFunc& log_func); -} // namespace onnxruntime diff --git a/onnxruntime/core/language_interop_ops/pyop/pyop.cc b/onnxruntime/core/language_interop_ops/pyop/pyop.cc deleted file mode 100644 index ccbe4c0d83006..0000000000000 --- a/onnxruntime/core/language_interop_ops/pyop/pyop.cc +++ /dev/null @@ -1,399 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pyop.h" - -#ifdef _WIN32 -#define LIB_PYOP "onnxruntime_pywrapper.dll" -#define LOAD_PYOP_LIB(n, v, m) ORT_ENFORCE((v = LoadLibraryA(n)) != nullptr, m) -#else -#ifdef __APPLE__ -#define LIB_PYOP "./libonnxruntime_pywrapper.dylib" -#else -#define LIB_PYOP "./libonnxruntime_pywrapper.so" -#endif -#define LOAD_PYOP_LIB(n, v, m) ORT_ENFORCE((v = dlopen(n, RTLD_NOW | RTLD_GLOBAL)) != nullptr, m) -#include "dlfcn.h" -#endif - -#include "core/framework/tensorprotoutils.h" -#include "core/platform/env.h" -#ifdef _DEBUG -#undef _DEBUG -#include -#define _DEBUG -#else -#include -#endif - -#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#include "numpy/arrayobject.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace onnxruntime { - -PyOpLibProxy& PyOpLibProxy::GetInstance() { - static PyOpLibProxy proxy; - return proxy; -} - -class Scope { - public: - Scope(const std::vector& objs = {}) : objs_(objs) { - mtx_.lock(); - } - ~Scope() { - for (auto obj : objs_) { - Py_XDECREF(obj); - } - mtx_.unlock(); - } - void Add(PyObject* obj) { - objs_.push_back(obj); - } - - private: - static std::mutex mtx_; - std::vector objs_; -}; - -PyOpLibProxy::PyOpLibProxy() { - Scope scope; - Py_Initialize(); - if (_import_array() < 0) { - return; - } - auto path_list = PySys_GetObject("path"); // do not release it - if (nullptr == path_list || !PyList_Check(path_list) || - PyList_Append(path_list, PyUnicode_FromString(".")) != 0) { - return; - } - initialized_ = true; -} - -PyOpLibProxy::~PyOpLibProxy() { - if (initialized_) { - Py_Finalize(); - } -} - -std::mutex Scope::mtx_; - -const char* PyOpLibProxy::GetLastErrorMessage(std::string& err) { - Scope scope; - if (PyErr_Occurred()) { - PyObject *type, *value, *trace; - PyErr_Fetch(&type, &value, &trace); - if (nullptr != value) { - auto pyVal = PyObject_Repr(value); - scope.Add(pyVal); - auto pyStr = PyUnicode_AsEncodedString(pyVal, "utf-8", "Error ~"); - scope.Add(pyStr); - err = PyBytes_AS_STRING(pyStr); - } - PyErr_Restore(type, value, trace); - } - return err.c_str(); -} - -int32_t PyOpLibProxy::GetGil() const { - return PyGILState_Ensure(); -} - -void PyOpLibProxy::PutGil(int32_t state) const { - PyGILState_Release((PyGILState_STATE)state); -} - -PyObject* MakePyObj(const void* data, int32_t type, const std::vector& dim) { - std::vector np_dim; - for (auto d : dim) { - np_dim.push_back(static_cast(d)); - } - auto pyObj = static_cast(PyArray_EMPTY(static_cast(np_dim.size()), np_dim.data(), type, 0)); - auto data_len = std::accumulate(begin(np_dim), end(np_dim), - static_cast(PyArray_DescrFromType(type)->elsize), - std::multiplies()); - auto np_array = reinterpret_cast(pyObj); - memcpy(PyArray_DATA(np_array), data, data_len); - return pyObj; -} - -bool ExtractOutput(PyObject* pyObj, - std::vector>& outputs, - std::vector& outputs_elem_size, - std::vector>& outputs_dim) { - if (!PyArray_Check(pyObj)) { - return false; - } - - outputs_dim.push_back({}); - auto np_array = reinterpret_cast(pyObj); - outputs_elem_size.push_back(static_cast(PyArray_ITEMSIZE(np_array))); - - for (int i = 0; i < PyArray_NDIM(np_array); ++i) { - outputs_dim.back().push_back(PyArray_SHAPE(np_array)[i]); - } - - auto data_len = std::accumulate(begin(outputs_dim.back()), - end(outputs_dim.back()), - static_cast(outputs_elem_size.back()), - std::multiplies()); - - outputs.push_back(std::unique_ptr(new char[data_len])); - memcpy(static_cast(outputs.back().get()), PyArray_DATA(np_array), data_len); - return true; -} - -void* PyOpLibProxy::NewInstance(const char* module, const char* class_name, - const std::unordered_map& args) { - Scope scope; - auto pyModule = PyImport_ImportModule(module); - if (nullptr == pyModule) { - return nullptr; - } - - scope.Add(pyModule); - auto pyClass = PyObject_GetAttrString(pyModule, class_name); - if (nullptr == pyClass) { - return nullptr; - } - - scope.Add(pyClass); - auto empty_args = PyTuple_New(0); - scope.Add(empty_args); - auto named_args = PyDict_New(); - scope.Add(named_args); - for (const auto& iter : args) { - PyDict_SetItemString(named_args, iter.first.c_str(), PyUnicode_FromString(iter.second.c_str())); - } - - return PyObject_Call(pyClass, empty_args, named_args); -} - -void PyOpLibProxy::ReleaseInstance(void* instance) { - Scope scope({static_cast(instance)}); -} - -bool PyOpLibProxy::InvokePythonFunc(void* raw_inst, - const char* function, - const std::vector& inputs, - const std::vector& inputs_type, - const std::vector>& inputs_dim, - std::vector>& outputs, - std::vector& outputs_elem_size, - std::vector>& outputs_dim, - std::function logging_func) { - Scope scope; - auto instance = static_cast(raw_inst); - if (nullptr == instance || nullptr == function) { - logging_func("InvokePythonFunc: found invalid instance or function"); - return false; - } - - auto pyFunc = PyObject_GetAttrString(instance, function); - if (nullptr == pyFunc) { - logging_func("InvokePythonFunc: failed to create function object"); - return false; - } - - scope.Add(pyFunc); - auto pyArgs = PyTuple_New(inputs.size()); - for (size_t i = 0; i < inputs.size(); ++i) { - PyTuple_SetItem(pyArgs, i, MakePyObj(inputs[i], inputs_type[i], inputs_dim[i])); - } - - scope.Add(pyArgs); - auto pyResult = PyObject_CallObject(pyFunc, pyArgs); - if (nullptr == pyResult) { - logging_func("InvokePythonFunc: no result"); - return false; - } - - scope.Add(pyResult); - if (PyArray_Check(pyResult)) { - ExtractOutput(pyResult, outputs, outputs_elem_size, outputs_dim); - } else if (PyTuple_Check(pyResult)) { - for (int32_t i = 0; i < PyTuple_Size(pyResult); ++i) { - if (!ExtractOutput(PyTuple_GetItem(pyResult, i), outputs, outputs_elem_size, outputs_dim)) { - logging_func("InvokePythonFunc: failed to extract output"); - return false; - } - } - } else { - logging_func("InvokePythonFunc: returned value must be numpy(s)"); - return false; - } - return true; -} // bool InvokePythonFunc - -PyCustomKernel::PyCustomKernel(const OnnxAttrs& attrs, - const std::string& module, - const std::string& class_name, - const std::string& compute, - PyOpLogFunc logging_func) : attrs_(attrs), module_(module), class_name_(class_name), compute_(compute), logging_func_(logging_func) { - std::string err; - auto state = PyOpLibProxy::GetInstance().GetGil(); - ORT_ENFORCE(PyOpLibProxy::GetInstance().Initialized(), "Py library not properly initialized."); - instance_ = PyOpLibProxy::GetInstance().NewInstance(module.c_str(), class_name_.c_str(), attrs_); - PyOpLibProxy::GetInstance().PutGil(state); - ORT_ENFORCE(nullptr != instance_, PyOpLibProxy::GetInstance().GetLastErrorMessage(err)); -} - -PyCustomKernel::~PyCustomKernel() { - if (nullptr != instance_) { - auto state = PyOpLibProxy::GetInstance().GetGil(); - PyOpLibProxy::GetInstance().ReleaseInstance(instance_); - PyOpLibProxy::GetInstance().PutGil(state); - instance_ = nullptr; - } -} - -// Do nothing since Custom Op does not trigger shape inference -void PyCustomKernel::GetOutputShape(OrtKernelContext*, size_t, OrtTensorTypeAndShapeInfo*) {} - -void PyCustomKernel::Compute(OrtKernelContext* context) { - ORT_ENFORCE(nullptr != context); - - Ort::KernelContext ctx(context); - const auto inputs_count = ctx.GetInputCount(); - - std::vector inputs; - std::vector> outputs; - std::vector inputs_type, outputs_elem_size; - std::vector> inputs_dim, outputs_dim; - - inputs.reserve(inputs_count); - inputs_dim.reserve(inputs_count); - for (size_t i = 0; i < inputs_count; ++i) { - auto value = ctx.GetInput(i); - ORT_ENFORCE(value.IsTensor(), "input must be a tensor"); - - inputs.push_back(value.GetTensorRawData()); - - auto type_and_shape = value.GetTensorTypeAndShapeInfo(); - inputs_type.push_back(GetNumpyType(type_and_shape.GetElementType())); - auto shape = type_and_shape.GetShape(); - inputs_dim.push_back(std::move(shape)); - } - - std::string err; - auto state = PyOpLibProxy::GetInstance().GetGil(); - ORT_ENFORCE(PyOpLibProxy::GetInstance().InvokePythonFunc(instance_, compute_.c_str(), inputs, inputs_type, - inputs_dim, outputs, outputs_elem_size, - outputs_dim, logging_func_), - PyOpLibProxy::GetInstance().GetLastErrorMessage(err)); // ORT_ENFORCE - PyOpLibProxy::GetInstance().PutGil(state); - - for (size_t i = 0; i < outputs.size(); ++i) { - auto ort_output = ctx.GetOutput(i, outputs_dim[i].data(), outputs_dim[i].size()); - auto output_mem_addr = ort_output.GetTensorMutableData(); - auto output_len = std::accumulate(begin(outputs_dim[i]), end(outputs_dim[i]), static_cast(outputs_elem_size[i]), std::multiplies()); - memcpy(output_mem_addr, outputs[i].get(), output_len); - } -} - -int32_t PyCustomKernel::GetNumpyType(int32_t elem_type) const { - int32_t numpy_type; - namespace on = ONNX_NAMESPACE; - switch (elem_type) { - case on::TensorProto_DataType_BOOL: - numpy_type = 0; - break; - case on::TensorProto_DataType_INT8: - numpy_type = 1; - break; - case on::TensorProto_DataType_UINT8: - numpy_type = 2; - break; - case on::TensorProto_DataType_INT16: - numpy_type = 3; - break; - case on::TensorProto_DataType_UINT16: - numpy_type = 4; - break; - case on::TensorProto_DataType_INT32: - numpy_type = 5; - break; - case on::TensorProto_DataType_UINT32: - numpy_type = 6; - break; - case on::TensorProto_DataType_INT64: - numpy_type = 9; - break; - case on::TensorProto_DataType_UINT64: - numpy_type = 10; - break; - case on::TensorProto_DataType_FLOAT: - numpy_type = 11; - break; - case on::TensorProto_DataType_DOUBLE: - numpy_type = 12; - break; - default: - ORT_THROW("Input primitive type not supported: ", elem_type); - } - return numpy_type; -} - -PyCustomOp::PyCustomOp(const OnnxAttrs& attrs, - const OnnxTypes& inputs_type, - const OnnxTypes& outputs_type, - const std::string& module, - const std::string& class_name, - const std::string& compute, - PyOpLogFunc logging_func) : attrs_(attrs), inputs_type_(inputs_type), outputs_type_(outputs_type), module_(module), class_name_(class_name), compute_(compute), logging_func_(logging_func) { OrtCustomOp::version = ORT_API_VERSION; } - -void* PyCustomOp::CreateKernel(const OrtApi&, const OrtKernelInfo*) const { - return new PyCustomKernel(attrs_, module_, class_name_, compute_, logging_func_); -} - -const char* PyCustomOp::GetName() const { return "PyOp"; } - -size_t PyCustomOp::GetInputTypeCount() const { return inputs_type_.size(); } -ONNXTensorElementDataType PyCustomOp::GetInputType(size_t index) const { return inputs_type_[index]; } - -size_t PyCustomOp::GetOutputTypeCount() const { return outputs_type_.size(); } -ONNXTensorElementDataType PyCustomOp::GetOutputType(size_t index) const { return outputs_type_[index]; } - -PyCustomOp* LoadPyOp(const ONNX_NAMESPACE::NodeProto& node_proto, PyOpLogFunc log_func) { - OnnxAttrs onnx_attrs; - OnnxTypes input_types, output_types; - std::string module, class_name, compute = "compute"; - for (int j = 0; j < node_proto.attribute_size(); ++j) { - const auto& attr = node_proto.attribute(j); - if (utils::HasString(attr)) { - if (attr.name() == "module") - module = attr.s(); - else if (attr.name() == "class_name") - class_name = attr.s(); - else if (attr.name() == "compute") - compute = attr.s(); - else - onnx_attrs[attr.name()] = attr.s(); - } else if (attr.ints_size() > 0) { - if (attr.name() == "input_types") { - for (int k = 0; k < attr.ints_size(); ++k) { - input_types.push_back(static_cast(attr.ints(k))); - } - } else if (attr.name() == "output_types") { - for (int k = 0; k < attr.ints_size(); ++k) { - output_types.push_back(static_cast(attr.ints(k))); - } - } - } - } // for - ORT_ENFORCE(module != "", "PyOp module not specified"); - ORT_ENFORCE(class_name != "", "PyOp class name not specified"); - ORT_ENFORCE(!input_types.empty(), "PyOp node inputs not specified"); - ORT_ENFORCE(!output_types.empty(), "PyOp node outputs not specified"); - return new PyCustomOp(onnx_attrs, input_types, output_types, module, class_name, compute, log_func); -} -} // namespace onnxruntime diff --git a/onnxruntime/core/language_interop_ops/pyop/pyop.h b/onnxruntime/core/language_interop_ops/pyop/pyop.h deleted file mode 100644 index 049a247aec469..0000000000000 --- a/onnxruntime/core/language_interop_ops/pyop/pyop.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "core/platform/env.h" -#define LOAD_PYOP_SYM(n, v, m) ORT_ENFORCE(Env::Default().GetSymbolFromLibrary(handle_, n, reinterpret_cast(&v)) == Status::OK(), m) - -#include "core/session/onnxruntime_cxx_api.h" -#include -#include -#include -#ifdef _WIN32 -#include -#else -#define HMODULE void* -#endif - -namespace ONNX_NAMESPACE { -class NodeProto; -} - -namespace onnxruntime { - -using OnnxTypes = std::vector; -using OnnxAttrs = std::unordered_map; -using PyOpLogFunc = std::function; - -class PyOpLibProxy { - public: - static PyOpLibProxy& GetInstance(); - void ReleaseInstance(void*); - bool InvokePythonFunc(void*, - const char*, - const std::vector&, - const std::vector&, - const std::vector>&, - std::vector>&, - std::vector&, - std::vector>&, - std::function); - const char* GetLastErrorMessage(std::string&); - void* NewInstance(const char*, const char*, const OnnxAttrs&); - bool Initialized() const { return initialized_; } - int32_t GetGil() const; - void PutGil(int32_t) const; - - private: - PyOpLibProxy(); - ~PyOpLibProxy(); - bool initialized_ = false; -}; - -struct PyCustomKernel { - PyCustomKernel(const OnnxAttrs& attrs, - const std::string& module, - const std::string& class_name, - const std::string& compute, - PyOpLogFunc logging_func); - ~PyCustomKernel(); - void GetOutputShape(OrtKernelContext*, size_t, OrtTensorTypeAndShapeInfo*); - void Compute(OrtKernelContext* context); - int32_t GetNumpyType(int32_t elem_type) const; - - private: - OnnxAttrs attrs_; - std::string module_; - std::string class_name_; - std::string compute_; - void* instance_ = nullptr; - PyOpLogFunc logging_func_; -}; - -struct PyCustomOp : Ort::CustomOpBase { - PyCustomOp( - const OnnxAttrs& attrs, - const OnnxTypes& inputs_type, - const OnnxTypes& outputs_type, - const std::string& module, - const std::string& class_name, - const std::string& compute = "compute", - PyOpLogFunc logging_func = [](const char*) {}); - void* CreateKernel(const OrtApi&, const OrtKernelInfo*) const; - const char* GetName() const; - size_t GetInputTypeCount() const; - ONNXTensorElementDataType GetInputType(size_t index) const; - size_t GetOutputTypeCount() const; - ONNXTensorElementDataType GetOutputType(size_t index) const; - - private: - OnnxAttrs attrs_; - OnnxTypes inputs_type_; - OnnxTypes outputs_type_; - std::string module_; - std::string class_name_; - std::string compute_; - PyOpLogFunc logging_func_; -}; // struct PyCustomOp - -PyCustomOp* LoadPyOp(const ONNX_NAMESPACE::NodeProto& node_proto, PyOpLogFunc log_func); -} // namespace onnxruntime diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 1145509eef261..3e587e9b56e2e 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -605,11 +605,6 @@ def convert_arg_line_to_args(self, arg_line): parser.add_argument( "--enable_msvc_static_runtime", action="store_true", help="Enable static linking of MSVC runtimes." ) - parser.add_argument( - "--enable_language_interop_ops", - action="store_true", - help="Enable operator implemented in language other than cpp", - ) parser.add_argument( "--cmake_generator", choices=[ @@ -1053,7 +1048,6 @@ def generate_build_tree( else "OFF" ), "-Donnxruntime_REDUCED_OPS_BUILD=" + ("ON" if is_reduced_ops_build(args) else "OFF"), - "-Donnxruntime_ENABLE_LANGUAGE_INTEROP_OPS=" + ("ON" if args.enable_language_interop_ops else "OFF"), "-Donnxruntime_USE_DML=" + ("ON" if args.use_dml else "OFF"), "-Donnxruntime_USE_WINML=" + ("ON" if args.use_winml else "OFF"), "-Donnxruntime_BUILD_MS_EXPERIMENTAL_OPS=" + ("ON" if args.ms_experimental else "OFF"), diff --git a/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml index 5894631739ac8..8fa2b805dadc9 100644 --- a/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml @@ -32,5 +32,5 @@ stages: parameters: AllowReleasedOpsetOnly: 0 BuildForAllArchs: false - AdditionalBuildFlags: --build_objc --enable_language_interop_ops --build_wheel --use_xnnpack + AdditionalBuildFlags: --build_objc --build_wheel --use_xnnpack WithCache: true