Delete pyop (#21094)

### Description
Remove the "--enable_language_interop_ops" build flag, because the code
is incompatible with the latest numpy, and the build flag is not used
anywhere except a macOS CI pipeline. It does not seem to have a ship
plan.


### Motivation and Context
The build error was:
```
onnxruntime/core/language_interop_ops/pyop/pyop.cc:122:85: error: no member named 'elsize' in '_PyArray_Descr'
                                  static_cast<int64_t>(PyArray_DescrFromType(type)->elsize),
                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~  ^
```
This commit is contained in:
Changming Sun 2024-06-19 16:21:33 -07:00 committed by GitHub
parent 8ab8e649a7
commit be423747b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 2 additions and 655 deletions

View file

@ -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)

View file

@ -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

View file

@ -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})

View file

@ -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()

View file

@ -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()

View file

@ -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")

View file

@ -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}

View file

@ -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 <google/protobuf/io/zero_copy_stream_impl.h>
namespace onnxruntime {
void LoadInterOp(const std::basic_string<ORTCHAR_T>& 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

View file

@ -1,16 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include <string>
#include <vector>
#include <memory>
#include "core/graph/graph.h"
#include "core/session/onnxruntime_cxx_api.h"
namespace onnxruntime {
using InterOpLogFunc = std::function<void(const char*)>;
using InterOpDomains = std::vector<Ort::CustomOpDomain>;
void LoadInterOp(const std::basic_string<ORTCHAR_T>& 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

View file

@ -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 <Python.h>
#define _DEBUG
#else
#include <Python.h>
#endif
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "numpy/arrayobject.h"
#include <functional>
#include <iostream>
#include <sstream>
#include <numeric>
#include <vector>
#include <memory>
#include <mutex>
#include <functional>
#include <unordered_map>
namespace onnxruntime {
PyOpLibProxy& PyOpLibProxy::GetInstance() {
static PyOpLibProxy proxy;
return proxy;
}
class Scope {
public:
Scope(const std::vector<PyObject*>& 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<PyObject*> 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<int64_t>& dim) {
std::vector<npy_intp> np_dim;
for (auto d : dim) {
np_dim.push_back(static_cast<npy_intp>(d));
}
auto pyObj = static_cast<PyObject*>(PyArray_EMPTY(static_cast<int>(np_dim.size()), np_dim.data(), type, 0));
auto data_len = std::accumulate(begin(np_dim), end(np_dim),
static_cast<int64_t>(PyArray_DescrFromType(type)->elsize),
std::multiplies<int64_t>());
auto np_array = reinterpret_cast<PyArrayObject*>(pyObj);
memcpy(PyArray_DATA(np_array), data, data_len);
return pyObj;
}
bool ExtractOutput(PyObject* pyObj,
std::vector<std::unique_ptr<char[]>>& outputs,
std::vector<int32_t>& outputs_elem_size,
std::vector<std::vector<int64_t>>& outputs_dim) {
if (!PyArray_Check(pyObj)) {
return false;
}
outputs_dim.push_back({});
auto np_array = reinterpret_cast<PyArrayObject*>(pyObj);
outputs_elem_size.push_back(static_cast<int32_t>(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<int64_t>(outputs_elem_size.back()),
std::multiplies<int64_t>());
outputs.push_back(std::unique_ptr<char[]>(new char[data_len]));
memcpy(static_cast<void*>(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<std::string, std::string>& 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<PyObject*>(instance)});
}
bool PyOpLibProxy::InvokePythonFunc(void* raw_inst,
const char* function,
const std::vector<const void*>& inputs,
const std::vector<int32_t>& inputs_type,
const std::vector<std::vector<int64_t>>& inputs_dim,
std::vector<std::unique_ptr<char[]>>& outputs,
std::vector<int32_t>& outputs_elem_size,
std::vector<std::vector<int64_t>>& outputs_dim,
std::function<void(const char*)> logging_func) {
Scope scope;
auto instance = static_cast<PyObject*>(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<const void*> inputs;
std::vector<std::unique_ptr<char[]>> outputs;
std::vector<int32_t> inputs_type, outputs_elem_size;
std::vector<std::vector<int64_t>> 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<char>();
auto output_len = std::accumulate(begin(outputs_dim[i]), end(outputs_dim[i]), static_cast<int64_t>(outputs_elem_size[i]), std::multiplies<int64_t>());
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<ONNXTensorElementDataType>(attr.ints(k)));
}
} else if (attr.name() == "output_types") {
for (int k = 0; k < attr.ints_size(); ++k) {
output_types.push_back(static_cast<ONNXTensorElementDataType>(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

View file

@ -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<void**>(&v)) == Status::OK(), m)
#include "core/session/onnxruntime_cxx_api.h"
#include <iostream>
#include <vector>
#include <unordered_map>
#ifdef _WIN32
#include <Windows.h>
#else
#define HMODULE void*
#endif
namespace ONNX_NAMESPACE {
class NodeProto;
}
namespace onnxruntime {
using OnnxTypes = std::vector<ONNXTensorElementDataType>;
using OnnxAttrs = std::unordered_map<std::string, std::string>;
using PyOpLogFunc = std::function<void(const char*)>;
class PyOpLibProxy {
public:
static PyOpLibProxy& GetInstance();
void ReleaseInstance(void*);
bool InvokePythonFunc(void*,
const char*,
const std::vector<const void*>&,
const std::vector<int32_t>&,
const std::vector<std::vector<int64_t>>&,
std::vector<std::unique_ptr<char[]>>&,
std::vector<int32_t>&,
std::vector<std::vector<int64_t>>&,
std::function<void(const char*)>);
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, PyCustomKernel> {
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

View file

@ -605,11 +605,6 @@ def parse_arguments():
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"),

View file

@ -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