mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-30 20:18:08 +00:00
Enhance compatibility with proto3 and replace or abstract has_*() methods. (#1778)
Enhance proto3 compatibility. Replace has_*() method to corresponding enum handling so we can deal with proto3 generated stream from proto2 code. Add utility wrappers for remaining has_*() methods so we can easily deal with them if/when we switch to proto3.
This commit is contained in:
parent
6a5b11756b
commit
75f241d02c
26 changed files with 428 additions and 270 deletions
|
|
@ -227,14 +227,14 @@ bool ShapeHasValue(const NodeArg* def, int i) {
|
|||
ORT_ENFORCE_DEBUG(nullptr != def);
|
||||
ORT_ENFORCE_DEBUG(i >= 0);
|
||||
ORT_ENFORCE_DEBUG(i < def->Shape()->dim_size());
|
||||
return def->Shape()->dim(i).has_dim_value();
|
||||
return utils::HasDimValue(def->Shape()->dim(i));
|
||||
}
|
||||
|
||||
bool ShapeHasSymbol(const NodeArg* def, int i) {
|
||||
ORT_ENFORCE_DEBUG(nullptr != def);
|
||||
ORT_ENFORCE_DEBUG(i >= 0);
|
||||
ORT_ENFORCE_DEBUG(i < def->Shape()->dim_size());
|
||||
return def->Shape()->dim(i).has_dim_param();
|
||||
return utils::HasDimParam(def->Shape()->dim(i));
|
||||
}
|
||||
|
||||
int64_t ShapeValue(const NodeArg* def, int i) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "core/codegen/mti/mti_tvm_utils.h"
|
||||
#include "core/codegen/mti/tensor/slice.h"
|
||||
#include "core/framework/op_kernel_info.h"
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
|
||||
#include <tvm/ir_pass.h>
|
||||
|
||||
|
|
@ -42,7 +43,7 @@ Status SliceCommon(const tvm::Array<tvm::Tensor>& inputs,
|
|||
bool found_in_axes = (axes_iter != axes.end());
|
||||
if (!found_in_axes) {
|
||||
tvm_starts.push_back(0);
|
||||
if (proto_dim.has_dim_value()) {
|
||||
if (utils::HasDimValue(proto_dim)) {
|
||||
tvm_ends.push_back(proto_dim.dim_value());
|
||||
} else {
|
||||
tvm_ends.push_back(max_range);
|
||||
|
|
@ -51,7 +52,7 @@ Status SliceCommon(const tvm::Array<tvm::Tensor>& inputs,
|
|||
auto axes_index = axes_iter - axes.begin();
|
||||
int64_t start = starts[axes_index];
|
||||
int64_t end = ends[axes_index];
|
||||
if (proto_dim.has_dim_value()) {
|
||||
if (utils::HasDimValue(proto_dim)) {
|
||||
int64_t dim_max = proto_dim.dim_value();
|
||||
if (start < 0) start += dim_max;
|
||||
if (end < 0) end += dim_max;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "core/codegen/common/profile.h"
|
||||
#include "core/codegen/passes/utils/codegen_context.h"
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/providers/common.h"
|
||||
#include "gsl/gsl_util"
|
||||
|
||||
|
|
@ -89,9 +90,9 @@ tvm::Array<tvm::Expr> ShapeToTvmArray(const NodeArg* def, CodeGenContext& ctx) {
|
|||
}
|
||||
|
||||
tvm::Expr ShapeDimToTvmDim(const ONNX_NAMESPACE::TensorShapeProto_Dimension& dim, CodeGenContext& ctx) {
|
||||
if (dim.has_dim_param()) {
|
||||
if (utils::HasDimParam(dim)) {
|
||||
return ctx.GetOrCreateDynamicDim(dim.dim_param());
|
||||
} else if (dim.has_dim_value()) {
|
||||
} else if (utils::HasDimValue(dim)) {
|
||||
return tvm::Expr(gsl::narrow_cast<int32_t>(dim.dim_value()));
|
||||
}
|
||||
return ctx.GetOrCreateDynamicDim(ctx.CreateUnnamedSymbol());
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "core/framework/mldata_type_utils.h"
|
||||
#include "core/framework/op_kernel.h"
|
||||
#include "core/framework/session_state.h"
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/framework/utils.h"
|
||||
|
||||
using namespace onnxruntime::common;
|
||||
|
|
@ -250,14 +251,16 @@ class PlannerImpl {
|
|||
|
||||
static bool SameShape(const TensorShapeProto& shape1, const TensorShapeProto& shape2) {
|
||||
// TODO: This should probably be defined to be the equality operator on TensorShapeProto.
|
||||
namespace on = ONNX_NAMESPACE;
|
||||
int rank1 = shape1.dim_size();
|
||||
if (shape2.dim_size() != rank1) return false;
|
||||
for (int i = 0; i < rank1; i++) {
|
||||
const auto& val1 = shape1.dim(i);
|
||||
const auto& val2 = shape2.dim(i);
|
||||
if (val1.has_dim_value() && val2.has_dim_value() && (val1.dim_value() == val2.dim_value()))
|
||||
if (utils::HasDimValue(val1) && utils::HasDimValue(val2) &&
|
||||
(val1.dim_value() == val2.dim_value()))
|
||||
continue; // same known dimension
|
||||
if (val1.has_dim_param() && val2.has_dim_param()) {
|
||||
if (utils::HasDimParam(val1) && utils::HasDimParam(val2)) {
|
||||
const auto& val1_param = val1.dim_param();
|
||||
if (val1_param == val2.dim_param() && !val1_param.empty())
|
||||
continue; // same unknown dimension
|
||||
|
|
@ -675,7 +678,7 @@ class PlannerImpl {
|
|||
// TODO: unclear why we should go through a string-representation of type
|
||||
auto ptype = nodearg.Type();
|
||||
auto& type_proto = ONNX_NAMESPACE::Utils::DataTypeUtils::ToTypeProto(ptype);
|
||||
return !type_proto.has_tensor_type();
|
||||
return !utils::HasTensorType(type_proto);
|
||||
}
|
||||
}; // namespace onnxruntime
|
||||
|
||||
|
|
|
|||
|
|
@ -23,12 +23,17 @@
|
|||
using namespace ONNX_NAMESPACE;
|
||||
|
||||
namespace onnxruntime {
|
||||
|
||||
// Return the MLDataType used for a generic Tensor
|
||||
template <>
|
||||
MLDataType DataTypeImpl::GetType<Tensor>() {
|
||||
return TensorTypeBase::Type();
|
||||
}
|
||||
} // namespace onnxruntime
|
||||
|
||||
// This conflics with the above GetType<>() specialization
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
|
||||
namespace onnxruntime {
|
||||
|
||||
// Return the MLDataType used for a generic SparseTensor
|
||||
template <>
|
||||
|
|
@ -180,8 +185,7 @@ bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Opaque& opaque_proto,
|
|||
|
||||
bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Tensor& tensor_proto,
|
||||
const ONNX_NAMESPACE::TypeProto_Tensor& type_proto) {
|
||||
return type_proto.has_elem_type() &&
|
||||
type_proto.elem_type() == tensor_proto.elem_type();
|
||||
return type_proto.elem_type() == tensor_proto.elem_type();
|
||||
/* Currently all Tensors with all kinds of shapes
|
||||
are mapped into the same MLDataType (same element type)
|
||||
so we omit shape from IsCompatible consideration
|
||||
|
|
@ -190,10 +194,6 @@ bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Tensor& tensor_proto,
|
|||
|
||||
bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Map& map_proto,
|
||||
const ONNX_NAMESPACE::TypeProto_Map& type_proto) {
|
||||
if (!(type_proto.has_key_type() &&
|
||||
type_proto.key_type() == map_proto.key_type())) {
|
||||
return false;
|
||||
}
|
||||
const auto& lhs = map_proto;
|
||||
const auto& rhs = type_proto;
|
||||
bool result = true;
|
||||
|
|
@ -230,8 +230,7 @@ bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Sequence& sequence_proto,
|
|||
bool result = true;
|
||||
const auto& lhs = sequence_proto;
|
||||
const auto& rhs = type_proto;
|
||||
if (rhs.has_elem_type() &&
|
||||
lhs.elem_type().value_case() == rhs.elem_type().value_case()) {
|
||||
if (lhs.elem_type().value_case() == rhs.elem_type().value_case()) {
|
||||
switch (lhs.elem_type().value_case()) {
|
||||
case TypeProto::ValueCase::kTensorType:
|
||||
result = IsCompatible(lhs.elem_type().tensor_type(), rhs.elem_type().tensor_type());
|
||||
|
|
@ -260,16 +259,16 @@ bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Sequence& sequence_proto,
|
|||
bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Opaque& opaque_proto, const ONNX_NAMESPACE::TypeProto_Opaque& type_proto) {
|
||||
const auto& lhs = opaque_proto;
|
||||
const auto& rhs = type_proto;
|
||||
bool lhs_domain = lhs.has_domain() && !lhs.domain().empty();
|
||||
bool rhs_domain = rhs.has_domain() && !rhs.domain().empty();
|
||||
bool lhs_domain = utils::HasDomain(lhs);
|
||||
bool rhs_domain = utils::HasDomain(rhs);
|
||||
|
||||
if ((lhs_domain != rhs_domain) ||
|
||||
(lhs_domain && rhs_domain && lhs.domain() != lhs.domain())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lhs_name = lhs.has_name() && !lhs.name().empty();
|
||||
bool rhs_name = rhs.has_name() && !rhs.name().empty();
|
||||
bool lhs_name = utils::HasName(lhs);
|
||||
bool rhs_name = utils::HasName(rhs);
|
||||
|
||||
return !((lhs_name != rhs_name) ||
|
||||
(lhs_name && rhs_name && lhs.name() != rhs.name()));
|
||||
|
|
@ -277,9 +276,7 @@ bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Opaque& opaque_proto, const ON
|
|||
|
||||
bool IsCompatible(const ONNX_NAMESPACE::TypeProto_SparseTensor& tensor_proto,
|
||||
const ONNX_NAMESPACE::TypeProto_SparseTensor& type_proto) {
|
||||
return type_proto.has_elem_type() &&
|
||||
type_proto.elem_type() == tensor_proto.elem_type();
|
||||
// XXX: Ignoring shape for now
|
||||
return type_proto.elem_type() == tensor_proto.elem_type();
|
||||
}
|
||||
|
||||
void RegisterAllProtos(const std::function<void(MLDataType)>& /*reg_fn*/);
|
||||
|
|
@ -370,16 +367,17 @@ ONNX_NAMESPACE::TypeProto& TensorTypeBase::mutable_type_proto() {
|
|||
|
||||
bool TensorTypeBase::IsCompatible(const ONNX_NAMESPACE::TypeProto& type_proto) const {
|
||||
const auto* thisProto = GetTypeProto();
|
||||
ORT_ENFORCE(thisProto->value_case() == TypeProto::ValueCase::kTensorType);
|
||||
ORT_ENFORCE(utils::HasElemType(thisProto->tensor_type()));
|
||||
|
||||
if (&type_proto == thisProto) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type_proto.value_case() != TypeProto::ValueCase::kTensorType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ORT_ENFORCE(thisProto->value_case() == TypeProto::ValueCase::kTensorType);
|
||||
ORT_ENFORCE(thisProto->tensor_type().has_elem_type());
|
||||
|
||||
return data_types_internal::IsCompatible(thisProto->tensor_type(), type_proto.tensor_type());
|
||||
}
|
||||
|
||||
|
|
@ -408,7 +406,7 @@ bool SparseTensorTypeBase::IsCompatible(const ONNX_NAMESPACE::TypeProto& type_pr
|
|||
}
|
||||
|
||||
ORT_ENFORCE(thisProto->value_case() == TypeProto::ValueCase::kSparseTensorType);
|
||||
ORT_ENFORCE(thisProto->sparse_tensor_type().has_elem_type());
|
||||
ORT_ENFORCE(utils::HasElemType(thisProto->sparse_tensor_type()));
|
||||
|
||||
return data_types_internal::IsCompatible(thisProto->sparse_tensor_type(), type_proto.sparse_tensor_type());
|
||||
}
|
||||
|
|
@ -461,8 +459,8 @@ bool NonTensorTypeBase::IsMapCompatible(const ONNX_NAMESPACE::TypeProto& type_pr
|
|||
return false;
|
||||
}
|
||||
ORT_ENFORCE(thisProto->value_case() == TypeProto::ValueCase::kMapType);
|
||||
ORT_ENFORCE(thisProto->map_type().has_key_type());
|
||||
ORT_ENFORCE(thisProto->map_type().has_value_type());
|
||||
ORT_ENFORCE(utils::HasKeyType(thisProto->map_type()));
|
||||
ORT_ENFORCE(utils::HasKeyType(thisProto->map_type()));
|
||||
return data_types_internal::IsCompatible(thisProto->map_type(), type_proto.map_type());
|
||||
}
|
||||
|
||||
|
|
@ -475,7 +473,7 @@ bool NonTensorTypeBase::IsSequenceCompatible(const ONNX_NAMESPACE::TypeProto& ty
|
|||
return false;
|
||||
}
|
||||
ORT_ENFORCE(thisProto->value_case() == TypeProto::ValueCase::kSequenceType);
|
||||
ORT_ENFORCE(thisProto->sequence_type().has_elem_type());
|
||||
ORT_ENFORCE(utils::HasElemType(thisProto->sequence_type()));
|
||||
return data_types_internal::IsCompatible(thisProto->sequence_type(), type_proto.sequence_type());
|
||||
}
|
||||
|
||||
|
|
@ -488,8 +486,6 @@ bool NonTensorTypeBase::IsOpaqueCompatible(const ONNX_NAMESPACE::TypeProto& type
|
|||
return false;
|
||||
}
|
||||
ORT_ENFORCE(thisProto->value_case() == TypeProto::ValueCase::kOpaqueType);
|
||||
ORT_ENFORCE(thisProto->opaque_type().has_domain());
|
||||
ORT_ENFORCE(thisProto->opaque_type().has_name());
|
||||
return data_types_internal::IsCompatible(thisProto->opaque_type(), type_proto.opaque_type());
|
||||
}
|
||||
|
||||
|
|
@ -743,12 +739,12 @@ MLDataType DataTypeImpl::TypeFromProto(const ONNX_NAMESPACE::TypeProto& proto) {
|
|||
switch (proto.value_case()) {
|
||||
case TypeProto::ValueCase::kTensorType: {
|
||||
const auto& tensor_type = proto.tensor_type();
|
||||
ORT_ENFORCE(tensor_type.has_elem_type());
|
||||
ORT_ENFORCE(utils::HasElemType(tensor_type));
|
||||
return TensorTypeFromONNXEnum(tensor_type.elem_type());
|
||||
} break; // kTensorType
|
||||
case TypeProto::ValueCase::kSparseTensorType: {
|
||||
const auto& sparse_tensor_type = proto.sparse_tensor_type();
|
||||
ORT_ENFORCE(sparse_tensor_type.has_elem_type());
|
||||
ORT_ENFORCE(utils::HasElemType(sparse_tensor_type));
|
||||
return SparseTensorTypeFromONNXEnum(sparse_tensor_type.elem_type());
|
||||
} break; // kSparseTensorType
|
||||
case TypeProto::ValueCase::kMapType: {
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ common::Status SaveInitializedTensors(const Env& env, const std::basic_string<PA
|
|||
//3. create weight tensors based on weights buffer
|
||||
for (const auto& entry : id_to_initialized_tensor) {
|
||||
int ort_value_index = entry.first;
|
||||
const char* name = entry.second->has_name() ? entry.second->name().c_str() : "";
|
||||
const char* name = (entry.second->name().empty()) ? "" : entry.second->name().c_str();
|
||||
const ONNX_NAMESPACE::TensorProto& tensor_proto = *(entry.second);
|
||||
|
||||
std::unique_ptr<MemBuffer> m;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/framework/tensor_shape.h"
|
||||
#include <iostream>
|
||||
#include "core/common/common.h"
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/graph/onnx_protobuf.h"
|
||||
|
||||
namespace onnxruntime {
|
||||
|
|
@ -104,9 +105,9 @@ std::ostream& operator<<(std::ostream& out, const ONNX_NAMESPACE::TensorShapePro
|
|||
result.append(",");
|
||||
}
|
||||
|
||||
if (dim.has_dim_value())
|
||||
if (utils::HasDimValue(dim))
|
||||
result.append(std::to_string(dim.dim_value()));
|
||||
else if (dim.has_dim_param())
|
||||
else if (utils::HasDimParam(dim))
|
||||
result.append(dim.dim_param());
|
||||
|
||||
first = false;
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ TensorShape GetTensorShapeFromTensorShapeProto(const ONNX_NAMESPACE::TensorShape
|
|||
const auto& dims = tensor_shape_proto.dim();
|
||||
std::vector<int64_t> tensor_shape_vec(static_cast<size_t>(dims.size()));
|
||||
for (int i = 0; i < dims.size(); ++i) {
|
||||
tensor_shape_vec[i] = dims[i].has_dim_value() ? dims[i].dim_value()
|
||||
tensor_shape_vec[i] = HasDimValue(dims[i]) ? dims[i].dim_value()
|
||||
: -1; /* symbolic dimensions are represented as -1 in onnxruntime*/
|
||||
}
|
||||
return TensorShape(std::move(tensor_shape_vec));
|
||||
|
|
@ -394,7 +394,7 @@ Status TensorProtoToMLValue(const Env& env, const ORTCHAR_T* tensor_proto_path,
|
|||
file_data, raw_data_len, deleter_for_file_data.d));
|
||||
raw_data = file_data;
|
||||
}
|
||||
} else if (tensor_proto.has_raw_data()) {
|
||||
} else if (utils::HasRawData(tensor_proto)) {
|
||||
if (ele_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING)
|
||||
return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT, "string tensor can not have raw data");
|
||||
raw_data = tensor_proto.raw_data().data();
|
||||
|
|
|
|||
|
|
@ -62,5 +62,145 @@ template <typename T>
|
|||
Status UnpackTensor(const ONNX_NAMESPACE::TensorProto& tensor, const void* raw_data, size_t raw_data_len,
|
||||
/*out*/ T* p_data, int64_t expected_size);
|
||||
|
||||
inline bool HasDimValue(const ONNX_NAMESPACE::TensorShapeProto_Dimension& dim) {
|
||||
return dim.value_case() == ONNX_NAMESPACE::TensorShapeProto_Dimension::kDimValue;
|
||||
}
|
||||
|
||||
inline bool HasDimParam(const ONNX_NAMESPACE::TensorShapeProto_Dimension& dim) {
|
||||
return dim.value_case() == ONNX_NAMESPACE::TensorShapeProto_Dimension::kDimParam;
|
||||
}
|
||||
|
||||
inline bool HasTensorType(const ONNX_NAMESPACE::TypeProto& type_proto) {
|
||||
return type_proto.value_case() == ONNX_NAMESPACE::TypeProto::kTensorType;
|
||||
}
|
||||
|
||||
inline bool HasElemType(const ONNX_NAMESPACE::TypeProto_Tensor& ten_proto) {
|
||||
return ten_proto.elem_type() != ONNX_NAMESPACE::TensorProto::UNDEFINED;
|
||||
;
|
||||
}
|
||||
|
||||
inline bool HasShape(const ONNX_NAMESPACE::TypeProto_Tensor& ten_proto) {
|
||||
// XXX: Figure out how do in proto3
|
||||
return ten_proto.has_shape();
|
||||
}
|
||||
|
||||
inline bool HasShape(const ONNX_NAMESPACE::TypeProto_SparseTensor& ten_proto) {
|
||||
// XXX: Figure out how do in proto3
|
||||
return ten_proto.has_shape();
|
||||
}
|
||||
|
||||
inline bool HasRawData(const ONNX_NAMESPACE::TensorProto& ten_proto) {
|
||||
// Can not be UNDEFINED and can not be STRING but test for STRING is usually performed separately
|
||||
// to return an error
|
||||
return ten_proto.data_type() != ONNX_NAMESPACE::TensorProto::UNDEFINED &&
|
||||
ten_proto.has_raw_data(); // XXX: Figure out how to do in proto3
|
||||
}
|
||||
|
||||
inline bool HasDataType(const ONNX_NAMESPACE::TensorProto& ten_proto) {
|
||||
return ten_proto.data_type() != ONNX_NAMESPACE::TensorProto::UNDEFINED;
|
||||
}
|
||||
|
||||
inline bool HasName(const ONNX_NAMESPACE::TensorProto& ten_proto) {
|
||||
return ten_proto.has_name(); // XXX
|
||||
}
|
||||
|
||||
inline bool HasElemType(const ONNX_NAMESPACE::TypeProto_Sequence& seq_proto) {
|
||||
return seq_proto.elem_type().value_case() != ONNX_NAMESPACE::TypeProto::VALUE_NOT_SET;
|
||||
}
|
||||
|
||||
inline bool HasElemType(const ONNX_NAMESPACE::TypeProto_SparseTensor& ten_proto) {
|
||||
return ten_proto.elem_type() != ONNX_NAMESPACE::TensorProto::UNDEFINED;
|
||||
}
|
||||
|
||||
inline bool HasKeyType(const ONNX_NAMESPACE::TypeProto_Map& map_proto) {
|
||||
return map_proto.key_type() != ONNX_NAMESPACE::TensorProto::UNDEFINED;
|
||||
}
|
||||
|
||||
inline bool HasValueType(const ONNX_NAMESPACE::TypeProto_Map& map_proto) {
|
||||
return map_proto.value_type().value_case() != ONNX_NAMESPACE::TypeProto::VALUE_NOT_SET;
|
||||
}
|
||||
|
||||
inline bool HasType(const ONNX_NAMESPACE::ValueInfoProto& vi_proto) {
|
||||
return vi_proto.type().value_case() != ONNX_NAMESPACE::TypeProto::VALUE_NOT_SET;
|
||||
}
|
||||
|
||||
inline bool HasName(const ONNX_NAMESPACE::ValueInfoProto& vi_proto) {
|
||||
return vi_proto.has_name(); // XXX: Figure out proto3 way
|
||||
}
|
||||
|
||||
inline bool HasDomain(const ONNX_NAMESPACE::TypeProto_Opaque& op_proto) {
|
||||
return !op_proto.domain().empty();
|
||||
}
|
||||
|
||||
inline bool HasName(const ONNX_NAMESPACE::TypeProto_Opaque& op_proto) {
|
||||
return !op_proto.name().empty();
|
||||
}
|
||||
|
||||
inline bool HasType(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() != ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_UNDEFINED;
|
||||
}
|
||||
|
||||
inline bool HasFloat(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() == ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_FLOAT;
|
||||
}
|
||||
|
||||
inline bool HasFloats(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() == ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_FLOATS;
|
||||
}
|
||||
|
||||
inline bool HasInt(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() == ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_INT;
|
||||
}
|
||||
|
||||
inline bool HasInts(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() == ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_INTS;
|
||||
}
|
||||
|
||||
inline bool HasString(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() == ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_STRING;
|
||||
}
|
||||
|
||||
inline bool HasStrings(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() == ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_STRINGS;
|
||||
}
|
||||
|
||||
inline bool HasTensor(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() == ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_TENSOR;
|
||||
}
|
||||
|
||||
inline bool HasTensors(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() == ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_TENSORS;
|
||||
}
|
||||
|
||||
inline bool HasGraph(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() == ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_GRAPH;
|
||||
}
|
||||
|
||||
inline bool HasGraphs(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.type() == ONNX_NAMESPACE::AttributeProto::AttributeType::AttributeProto_AttributeType_GRAPHS;
|
||||
}
|
||||
|
||||
inline bool HasName(const ONNX_NAMESPACE::AttributeProto& at_proto) {
|
||||
return at_proto.has_name(); // XXX: Fugure out proto3
|
||||
}
|
||||
|
||||
inline bool HasGraph (const ONNX_NAMESPACE::ModelProto& m_proto) {
|
||||
return m_proto.has_graph(); // XXX proto3
|
||||
}
|
||||
|
||||
inline bool HasIrVersion(const ONNX_NAMESPACE::ModelProto& m_proto) {
|
||||
return m_proto.has_ir_version(); // XXX proto3
|
||||
}
|
||||
|
||||
inline bool HasModelVersion(const ONNX_NAMESPACE::ModelProto& m_proto) {
|
||||
return m_proto.has_model_version(); // XXX proto3
|
||||
}
|
||||
|
||||
|
||||
inline bool HasName(const ONNX_NAMESPACE::NodeProto& node_proto) {
|
||||
//XXX: Figure out proto3 style
|
||||
return node_proto.has_name();
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/graph/constants.h"
|
||||
#include "core/graph/contrib_ops/attn_lstm_schema_defs.h"
|
||||
#include "core/graph/contrib_ops/contrib_defs.h"
|
||||
|
|
@ -643,8 +644,8 @@ and op)DOC";
|
|||
*output_shape->mutable_dim(static_cast<int>(1)) = input_shape.dim(static_cast<int>(1));
|
||||
|
||||
// process 'H' and 'W'
|
||||
if (!input_shape.dim(static_cast<int>(2)).has_dim_value() ||
|
||||
!input_shape.dim(static_cast<int>(3)).has_dim_value()) {
|
||||
if (!utils::HasDimValue(input_shape.dim(static_cast<int>(2))) ||
|
||||
!utils::HasDimValue(input_shape.dim(static_cast<int>(3)))) {
|
||||
// either height and width input has symbolic dims, so can't proceed further
|
||||
// add two dims as placeholders for output_H and output_W and return
|
||||
output_shape->add_dim();
|
||||
|
|
@ -1254,7 +1255,7 @@ of [N, 0] then [N, 0].
|
|||
|
||||
int64_t size = 1;
|
||||
for (auto& dim : dims) {
|
||||
if (dim.has_dim_value()) {
|
||||
if (utils::HasDimValue(dim)) {
|
||||
size *= dim.dim_value();
|
||||
}
|
||||
}
|
||||
|
|
@ -1530,7 +1531,7 @@ Example 4:
|
|||
// make a copy of the returned const vector - may have to resize
|
||||
// this in next step
|
||||
std::vector<int64_t> pads_data;
|
||||
if (pads_initializer->has_raw_data())
|
||||
if (utils::HasRawData(*pads_initializer))
|
||||
return;
|
||||
else
|
||||
pads_data.insert(
|
||||
|
|
@ -1547,7 +1548,7 @@ Example 4:
|
|||
for (size_t i = 0; static_cast<int64_t>(i) < input_rank; ++i) {
|
||||
const auto& input_dim = input_shape.dim(static_cast<int>(i));
|
||||
auto* output_dim = output_shape->add_dim();
|
||||
if (input_dim.has_dim_value()) {
|
||||
if (utils::HasDimValue(input_dim)) {
|
||||
output_dim->set_dim_value(
|
||||
input_dim.dim_value() + pads_data[i] + pads_data[i + input_rank]);
|
||||
} else if (pads_data[i] + pads_data[i + input_rank] == 0) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "range_schema_defs.h"
|
||||
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/graph/constants.h"
|
||||
#include "core/graph/op.h"
|
||||
#include <cmath>
|
||||
|
|
@ -57,7 +58,7 @@ template <typename T>
|
|||
static T GetFirstElement(const TensorProto* shapeInitializer) {
|
||||
if (shapeInitializer == nullptr) return T{1};
|
||||
|
||||
if (shapeInitializer->has_raw_data()) {
|
||||
if (utils::HasRawData(*shapeInitializer)) {
|
||||
const std::string& bytes = shapeInitializer->raw_data();
|
||||
return *reinterpret_cast<const T*>(bytes.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/graph/function_impl.h"
|
||||
#include "core/graph/graph_viewer.h"
|
||||
#include "core/graph/model.h"
|
||||
|
|
@ -56,7 +57,7 @@ void IOTypeConstraintHelper(const ONNX_NAMESPACE::FunctionProto* onnx_func_proto
|
|||
// type attribute, we add its referenced attribute
|
||||
// into the op's schema
|
||||
for (auto& attr : node.attribute()) {
|
||||
if (attr.has_ref_attr_name() && attr.has_type())
|
||||
if (!attr.ref_attr_name().empty() && utils::HasType(attr))
|
||||
attribute_type_map[attr.ref_attr_name()] = attr.type();
|
||||
}
|
||||
}
|
||||
|
|
@ -230,7 +231,7 @@ FunctionImpl::FunctionImpl(const onnxruntime::Graph& graph,
|
|||
std::vector<onnxruntime::NodeArg*> inputs;
|
||||
std::vector<onnxruntime::NodeArg*> outputs;
|
||||
std::string uniq_identifier = node.name();
|
||||
if (!node.has_name()) {
|
||||
if (!utils::HasName(node)) {
|
||||
std::stringstream ss;
|
||||
ss << static_cast<const void*>(&node);
|
||||
uniq_identifier = ss.str();
|
||||
|
|
@ -273,7 +274,7 @@ FunctionImpl::FunctionImpl(const onnxruntime::Graph& graph,
|
|||
|
||||
onnxruntime::NodeAttributes new_attr_map;
|
||||
for (auto& attr : node.attribute()) {
|
||||
if (attr.has_ref_attr_name()) {
|
||||
if (!attr.ref_attr_name().empty()) {
|
||||
auto entry = attr_map.find(attr.ref_attr_name());
|
||||
if (entry != attr_map.cend()) {
|
||||
new_attr_map[attr.name()] = entry->second;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <stack>
|
||||
|
||||
#include "gsl/pointers"
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/graph/function.h"
|
||||
#include "core/graph/function_impl.h"
|
||||
#include "core/graph/graph_viewer.h"
|
||||
|
|
@ -54,15 +55,15 @@ static bool GraphLoadedFromModelFile(const GraphProto* graph_proto) {
|
|||
// there are some known invalid usages of dim_param and dim_value. remove them from the TypeProto so that
|
||||
// they don't affect shape inferencing or the allocation planner
|
||||
static void RemoveInvalidValues(ONNX_NAMESPACE::TypeProto& type) {
|
||||
if (type.has_tensor_type() && type.tensor_type().has_shape()) {
|
||||
if (utils::HasTensorType(type) && utils::HasShape(type.tensor_type())) {
|
||||
auto* shape = type.mutable_tensor_type()->mutable_shape();
|
||||
for (int i = 0, end = shape->dim_size(); i < end; ++i) {
|
||||
auto& dim = *shape->mutable_dim(i);
|
||||
if (dim.has_dim_param()) {
|
||||
if (utils::HasDimParam(dim)) {
|
||||
if (dim.dim_param().empty()) {
|
||||
dim.clear_dim_param();
|
||||
}
|
||||
} else if (dim.has_dim_value()) {
|
||||
} else if (utils::HasDimValue(dim)) {
|
||||
if (dim.dim_value() < 0) {
|
||||
dim.clear_dim_value();
|
||||
}
|
||||
|
|
@ -93,7 +94,7 @@ DataType NodeArg::Type() const noexcept {
|
|||
}
|
||||
|
||||
const TypeProto* NodeArg::TypeAsProto() const noexcept {
|
||||
if (node_arg_info_.has_type())
|
||||
if (utils::HasType(node_arg_info_))
|
||||
return &node_arg_info_.type();
|
||||
|
||||
return nullptr;
|
||||
|
|
@ -105,13 +106,13 @@ const TensorShapeProto* NodeArg::Shape() const {
|
|||
const auto typeCase = type->value_case();
|
||||
switch (typeCase) {
|
||||
case TypeProto::kTensorType: {
|
||||
if (type->tensor_type().has_shape()) {
|
||||
if (utils::HasShape(type->tensor_type())) {
|
||||
return &(type->tensor_type().shape());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
case TypeProto::kSparseTensorType: {
|
||||
if (type->sparse_tensor_type().has_shape()) {
|
||||
if (utils::HasShape(type->sparse_tensor_type())) {
|
||||
return &(type->sparse_tensor_type().shape());
|
||||
}
|
||||
return nullptr;
|
||||
|
|
@ -126,9 +127,6 @@ const TensorShapeProto* NodeArg::Shape() const {
|
|||
}
|
||||
|
||||
void NodeArg::SetShape(const TensorShapeProto& shape) {
|
||||
if (!node_arg_info_.has_type()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto type_case = node_arg_info_.type().value_case();
|
||||
switch (type_case) {
|
||||
|
|
@ -148,7 +146,7 @@ void NodeArg::SetShape(const TensorShapeProto& shape) {
|
|||
}
|
||||
|
||||
common::Status NodeArg::UpdateTypeAndShape(const ONNX_NAMESPACE::TypeProto& input_type) {
|
||||
if (!node_arg_info_.has_type()) {
|
||||
if (!utils::HasType(node_arg_info_)) {
|
||||
*node_arg_info_.mutable_type() = input_type;
|
||||
type_ = DataTypeUtils::ToType(node_arg_info_.type());
|
||||
return Status::OK();
|
||||
|
|
@ -173,9 +171,9 @@ common::Status NodeArg::UpdateTypeAndShape(const ONNX_NAMESPACE::TypeProto& inpu
|
|||
static_cast<TensorProto_DataType>(input_tensor_elem_type), " != ",
|
||||
static_cast<TensorProto_DataType>(current_tensor_elem_type));
|
||||
|
||||
if (input_tensor_type.has_shape()) {
|
||||
if (utils::HasShape(input_tensor_type)) {
|
||||
auto& current_tensor_type = *current_type.mutable_tensor_type();
|
||||
if (current_tensor_type.has_shape()) {
|
||||
if (utils::HasShape(current_tensor_type)) {
|
||||
ORT_RETURN_IF_ERROR(MergeShapeInfo(Name(), input_tensor_type, current_tensor_type));
|
||||
} else {
|
||||
current_tensor_type = input_tensor_type;
|
||||
|
|
@ -193,9 +191,9 @@ common::Status NodeArg::UpdateTypeAndShape(const ONNX_NAMESPACE::TypeProto& inpu
|
|||
static_cast<TensorProto_DataType>(input_tensor_elem_type), " != ",
|
||||
static_cast<TensorProto_DataType>(current_tensor_elem_type));
|
||||
}
|
||||
if (input_tensor_type.has_shape()) {
|
||||
if (utils::HasShape(input_tensor_type)) {
|
||||
auto& current_tensor_type = *current_type.mutable_sparse_tensor_type();
|
||||
if (current_tensor_type.has_shape()) {
|
||||
if (utils::HasShape(current_tensor_type)) {
|
||||
// TODO: Check if we need to merge shape here
|
||||
// if so we'd need to provide merging routine ONNX
|
||||
// mergeInShapeInfo(input_tensor_type, current_tensor_type);
|
||||
|
|
@ -217,7 +215,7 @@ common::Status NodeArg::UpdateTypeAndShape(const ONNX_NAMESPACE::TypeProto& inpu
|
|||
common::Status NodeArg::UpdateTypeAndShape(const NodeArg& node_arg) {
|
||||
auto status = Status::OK();
|
||||
|
||||
if (node_arg.node_arg_info_.has_type())
|
||||
if (utils::HasType(node_arg.node_arg_info_))
|
||||
status = UpdateTypeAndShape(node_arg.node_arg_info_.type());
|
||||
|
||||
return status;
|
||||
|
|
@ -392,7 +390,7 @@ void Node::Init(const std::string& name,
|
|||
attributes_ = *attributes;
|
||||
|
||||
for (auto& name_to_attr : attributes_) {
|
||||
if (name_to_attr.second.has_g()) {
|
||||
if (utils::HasGraph(name_to_attr.second)) {
|
||||
CreateSubgraph(name_to_attr.first);
|
||||
}
|
||||
}
|
||||
|
|
@ -416,7 +414,7 @@ Node::Relationships& Node::MutableRelationships() noexcept {
|
|||
void Node::CreateSubgraph(const std::string& attr_name) {
|
||||
auto attr = attributes_.find(attr_name);
|
||||
|
||||
if (attr != attributes_.cend() && attr->second.has_g()) {
|
||||
if (attr != attributes_.cend() && utils::HasGraph(attr->second)) {
|
||||
GraphProto& mutable_graph = *attr->second.mutable_g();
|
||||
std::unique_ptr<Graph> subgraph{new Graph(*graph_, mutable_graph)};
|
||||
attr_to_subgraph_map_.insert({std::string{attr_name}, gsl::not_null<Graph*>{subgraph.get()}});
|
||||
|
|
@ -685,7 +683,7 @@ Graph::Graph(GraphProto* graph_proto, const std::unordered_map<std::string, int>
|
|||
// type/shape information will be assigned to each node arg when going
|
||||
// thru all nodes later.
|
||||
for (auto& graph_input : graph_proto_->input()) {
|
||||
if (graph_input.has_name() && graph_input.has_type()) {
|
||||
if (utils::HasName(graph_input) && utils::HasType(graph_input)) {
|
||||
name_to_type_map[graph_input.name()] = graph_input.type();
|
||||
// always create a NodeArg for graph input in case its from an initializer
|
||||
GetOrCreateNodeArg(graph_input.name(), &graph_input.type());
|
||||
|
|
@ -693,7 +691,7 @@ Graph::Graph(GraphProto* graph_proto, const std::unordered_map<std::string, int>
|
|||
}
|
||||
|
||||
for (auto& graph_output : graph_proto_->output()) {
|
||||
if (graph_output.has_name() && graph_output.has_type()) {
|
||||
if (utils::HasName(graph_output) && utils::HasType(graph_output)) {
|
||||
auto& name = graph_output.name();
|
||||
name_to_type_map[name] = graph_output.type();
|
||||
// always create NodeArg for graph output, in case it's from initializer
|
||||
|
|
@ -702,7 +700,7 @@ Graph::Graph(GraphProto* graph_proto, const std::unordered_map<std::string, int>
|
|||
}
|
||||
|
||||
for (auto& node_arg : graph_proto_->value_info()) {
|
||||
if (node_arg.has_name() && node_arg.has_type()) {
|
||||
if (utils::HasName(node_arg) && utils::HasType(node_arg)) {
|
||||
name_to_type_map[node_arg.name()] = node_arg.type();
|
||||
}
|
||||
}
|
||||
|
|
@ -1181,21 +1179,20 @@ bool FullyDefinedType(const TypeProto& type_proto) {
|
|||
switch (type_proto.value_case()) {
|
||||
case TypeProto::kTensorType: {
|
||||
auto& tensor_type = type_proto.tensor_type();
|
||||
return tensor_type.has_elem_type() && (tensor_type.elem_type() != TensorProto::UNDEFINED);
|
||||
return utils::HasElemType(tensor_type);
|
||||
}
|
||||
case TypeProto::kSparseTensorType: {
|
||||
auto& tensor_type = type_proto.sparse_tensor_type();
|
||||
return tensor_type.has_elem_type() && (tensor_type.elem_type() != TensorProto::UNDEFINED);
|
||||
return utils::HasElemType(tensor_type);
|
||||
}
|
||||
case TypeProto::kSequenceType: {
|
||||
auto& seq_type = type_proto.sequence_type();
|
||||
return seq_type.has_elem_type() && FullyDefinedType(seq_type.elem_type());
|
||||
return utils::HasElemType(seq_type) && FullyDefinedType(seq_type.elem_type());
|
||||
}
|
||||
case TypeProto::kMapType: {
|
||||
auto& map_type = type_proto.map_type();
|
||||
return map_type.has_key_type() &&
|
||||
(map_type.key_type() != TensorProto::UNDEFINED) &&
|
||||
map_type.has_value_type() &&
|
||||
return utils::HasKeyType(map_type) &&
|
||||
utils::HasValueType(map_type) &&
|
||||
FullyDefinedType(map_type.value_type());
|
||||
}
|
||||
case TypeProto::kOpaqueType:
|
||||
|
|
@ -1567,9 +1564,9 @@ Status Graph::InferAndVerifyTypeMatch(Node& node, const OpSchema& op) {
|
|||
output_def->SetType(inferred_type);
|
||||
|
||||
// Update output-shape if it was inferred:
|
||||
if (onnx_inferred_type.has_tensor_type()) {
|
||||
if (utils::HasTensorType(onnx_inferred_type)) {
|
||||
auto& tensor_type = onnx_inferred_type.tensor_type();
|
||||
if (tensor_type.has_shape()) {
|
||||
if (utils::HasShape(tensor_type)) {
|
||||
if (output_def->Shape() == nullptr) {
|
||||
output_def->SetShape(tensor_type.shape());
|
||||
} else {
|
||||
|
|
@ -1639,7 +1636,7 @@ common::Status Graph::TypeCheckInputsAndInitializers() {
|
|||
"Type Error: Shape of initializer " + name + " does not match its type.");
|
||||
for (int i = 0; i < p_existing_shape->dim_size(); ++i) {
|
||||
auto& d = p_existing_shape->dim(i);
|
||||
if (d.has_dim_value() && (d.dim_value() != tensor_proto->dims(i)))
|
||||
if (utils::HasDimValue(d) && (d.dim_value() != tensor_proto->dims(i)))
|
||||
return Status(ONNXRUNTIME, FAIL,
|
||||
"Type Error: Shape of initializer " + initializer_pair.first + " does not match its type.");
|
||||
}
|
||||
|
|
@ -1729,7 +1726,7 @@ Status Graph::VerifyNodeAndOpMatch() {
|
|||
if (node_attributes.end() == node_attr_iter) {
|
||||
// The attribute was not specified in the node.
|
||||
if (!attr_def.second.required) {
|
||||
if (attr_def.second.default_value.has_name()) {
|
||||
if (utils::HasName(attr_def.second.default_value)) {
|
||||
// Set default value to the node attributes.
|
||||
node.AddAttribute(attr_def.first, attr_def.second.default_value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/graph/model.h"
|
||||
#include <memory>
|
||||
#include "core/common/logging/logging.h"
|
||||
|
|
@ -81,7 +82,7 @@ Model::Model(std::unique_ptr<ModelProto> model_proto, const IOnnxRuntimeOpSchema
|
|||
throw std::invalid_argument("ModelProto was null.");
|
||||
}
|
||||
|
||||
if (!model_proto->has_graph()) {
|
||||
if (!utils::HasGraph(*model_proto)) {
|
||||
throw std::invalid_argument("ModelProto does not have a graph.");
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +151,7 @@ Model::Model(std::unique_ptr<ModelProto> model_proto, const IOnnxRuntimeOpSchema
|
|||
}
|
||||
|
||||
Version Model::IrVersion() const {
|
||||
if (model_proto_->has_ir_version()) {
|
||||
if (utils::HasIrVersion(*model_proto_)) {
|
||||
return model_proto_->ir_version();
|
||||
}
|
||||
return kNoVersion;
|
||||
|
|
@ -181,7 +182,7 @@ void Model::SetDomain(const std::string& domain) {
|
|||
}
|
||||
|
||||
Version Model::ModelVersion() const {
|
||||
if (model_proto_->has_model_version()) {
|
||||
if (utils::HasModelVersion(*model_proto_)) {
|
||||
return model_proto_->model_version();
|
||||
}
|
||||
return kNoVersion;
|
||||
|
|
@ -239,7 +240,7 @@ Status Model::Load(std::istream& model_istream, ModelProto* p_model_proto) {
|
|||
|
||||
Status Model::Load(const ModelProto& model_proto, std::shared_ptr<Model>& model, const IOnnxRuntimeOpSchemaRegistryList* local_registries) {
|
||||
// we expect a graph to be present
|
||||
if (!model_proto.has_graph()) {
|
||||
if (!utils::HasGraph(model_proto)) {
|
||||
return Status(ONNXRUNTIME, INVALID_ARGUMENT, "No graph was found in the protobuf.");
|
||||
}
|
||||
|
||||
|
|
@ -258,7 +259,7 @@ Status Model::Load(const ModelProto& model_proto, std::shared_ptr<Model>& model,
|
|||
|
||||
Status Model::Load(std::unique_ptr<ModelProto> p_model_proto, std::shared_ptr<Model>& model, const IOnnxRuntimeOpSchemaRegistryList* local_registries) {
|
||||
// we expect a graph to be present
|
||||
if (!p_model_proto->has_graph()) {
|
||||
if (!utils::HasGraph(*p_model_proto)) {
|
||||
return Status(ONNXRUNTIME, INVALID_ARGUMENT, "No graph was found in the protobuf.");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
// 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"
|
||||
|
|
@ -7,47 +11,45 @@
|
|||
namespace onnxruntime {
|
||||
|
||||
void InterOpDomainDeleter(OrtCustomOpDomain* domain) {
|
||||
if (nullptr != domain) {
|
||||
for (auto op: domain->custom_ops_) {
|
||||
delete op;
|
||||
}
|
||||
delete domain;
|
||||
if (nullptr != domain) {
|
||||
for (auto op : domain->custom_ops_) {
|
||||
delete op;
|
||||
}
|
||||
delete domain;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadInterOp(const std::basic_string<ORTCHAR_T>& model_uri, InterOpDomains& domains, const InterOpLogFunc& log_func)
|
||||
{
|
||||
int fd;
|
||||
ORT_ENFORCE(Env::Default().FileOpenRd(model_uri, fd).IsOK(), "Failed to read model file");
|
||||
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 std::basic_string<ORTCHAR_T>& model_uri, InterOpDomains& domains, const InterOpLogFunc& log_func) {
|
||||
int fd;
|
||||
ORT_ENFORCE(Env::Default().FileOpenRd(model_uri, fd).IsOK(), "Failed to read model file");
|
||||
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::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") {
|
||||
OrtCustomOpDomain* pyop_domain = nullptr;
|
||||
ORT_THROW_ON_ERROR(OrtCreateCustomOpDomain(node_proto.domain().c_str(), &pyop_domain));
|
||||
ORT_THROW_ON_ERROR(OrtCustomOpDomain_Add(pyop_domain, LoadPyOp(node_proto, log_func)));
|
||||
auto ort_domain = std::unique_ptr<OrtCustomOpDomain,decltype(&InterOpDomainDeleter)>(pyop_domain, &InterOpDomainDeleter);
|
||||
domains.push_back(std::move(ort_domain));
|
||||
} else {
|
||||
for (int j = 0; j < node_proto.attribute_size(); ++j) {
|
||||
const auto& attr = node_proto.attribute(j);
|
||||
if (attr.has_g()) {
|
||||
LoadInterOp(attr.g(), domains, log_func); //load pyop in subgraph
|
||||
}
|
||||
}//for
|
||||
}//else
|
||||
}//for
|
||||
}
|
||||
for (int i = 0; i < graph_proto.node_size(); ++i) {
|
||||
const auto& node_proto = graph_proto.node(i);
|
||||
if (node_proto.op_type() == "PyOp") {
|
||||
OrtCustomOpDomain* pyop_domain = nullptr;
|
||||
ORT_THROW_ON_ERROR(OrtCreateCustomOpDomain(node_proto.domain().c_str(), &pyop_domain));
|
||||
ORT_THROW_ON_ERROR(OrtCustomOpDomain_Add(pyop_domain, LoadPyOp(node_proto, log_func)));
|
||||
auto ort_domain = std::unique_ptr<OrtCustomOpDomain, decltype(&InterOpDomainDeleter)>(pyop_domain, &InterOpDomainDeleter);
|
||||
domains.push_back(std::move(ort_domain));
|
||||
} else {
|
||||
for (int j = 0; j < node_proto.attribute_size(); ++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
|
||||
|
|
|
|||
|
|
@ -1,139 +1,137 @@
|
|||
// 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)
|
||||
#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)
|
||||
#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"
|
||||
#define LOAD_PYOP_SYM(n,v,m) ORT_ENFORCE(Env::Default().GetSymbolFromLibrary(handle_,n,reinterpret_cast<void**>(&v))==Status::OK(),m)
|
||||
// #define LOAD_PYOP_SYM(n, v, m) ORT_ENFORCE(Env::Default().GetSymbolFromLibrary(handle_, n, reinterpret_cast<void**>(&v)) == Status::OK(), m)
|
||||
|
||||
namespace onnxruntime {
|
||||
|
||||
const PyOpLibProxy& PyOpLibProxy::GetInstance() {
|
||||
static PyOpLibProxy proxy;
|
||||
return proxy;
|
||||
static PyOpLibProxy proxy;
|
||||
return proxy;
|
||||
}
|
||||
|
||||
PyOpLibProxy:: PyOpLibProxy() {
|
||||
std::string err;
|
||||
LOAD_PYOP_LIB(LIB_PYOP, handle_, "Failed to load pyop library");
|
||||
LOAD_PYOP_SYM("Initialize", initialize_, "Failed to import function: Initialize");
|
||||
LOAD_PYOP_SYM("NewInstance", new_instance_, "Failed to import function: NewInstance");
|
||||
LOAD_PYOP_SYM("InvokePythonFunc", invoke_python_func_, "Failed to import function: InvokePythonFunc");
|
||||
LOAD_PYOP_SYM("ReleaseInstance", release_instance_, "Failed to import function: ReleaseInstance");
|
||||
LOAD_PYOP_SYM("GetLastErrorMessage", get_last_error_message_, "Failed to import function: GetLastErrorMessage");
|
||||
ORT_ENFORCE (initialize_(), get_last_error_message_(err));
|
||||
PyOpLibProxy::PyOpLibProxy() {
|
||||
std::string err;
|
||||
LOAD_PYOP_LIB(LIB_PYOP, handle_, "Failed to load pyop library");
|
||||
LOAD_PYOP_SYM("Initialize", initialize_, "Failed to import function: Initialize");
|
||||
LOAD_PYOP_SYM("NewInstance", new_instance_, "Failed to import function: NewInstance");
|
||||
LOAD_PYOP_SYM("InvokePythonFunc", invoke_python_func_, "Failed to import function: InvokePythonFunc");
|
||||
LOAD_PYOP_SYM("ReleaseInstance", release_instance_, "Failed to import function: ReleaseInstance");
|
||||
LOAD_PYOP_SYM("GetLastErrorMessage", get_last_error_message_, "Failed to import function: GetLastErrorMessage");
|
||||
ORT_ENFORCE(initialize_(), get_last_error_message_(err));
|
||||
}
|
||||
|
||||
PyOpLibProxy::~PyOpLibProxy() {
|
||||
Env::Default().UnloadDynamicLibrary(handle_);
|
||||
Env::Default().UnloadDynamicLibrary(handle_);
|
||||
}
|
||||
|
||||
PyCustomKernel::PyCustomKernel(Ort::CustomOpApi ort,
|
||||
const OnnxAttrs& attrs,
|
||||
PyCustomKernel::PyCustomKernel(Ort::CustomOpApi ort,
|
||||
const OnnxAttrs& attrs,
|
||||
const std::string& module,
|
||||
const std::string& class_name,
|
||||
const std::string& compute,
|
||||
PyOpLogFunc logging_func):
|
||||
ort_(ort), attrs_(attrs), module_(module), class_name_(class_name),
|
||||
compute_(compute), logging_func_(logging_func) {
|
||||
std::string err;
|
||||
instance_ = PyOpLibProxy::GetInstance().new_instance_(module.c_str(), class_name_.c_str(), attrs_);
|
||||
ORT_ENFORCE(nullptr != instance_, PyOpLibProxy::GetInstance().get_last_error_message_(err));
|
||||
PyOpLogFunc logging_func) : ort_(ort), attrs_(attrs), module_(module), class_name_(class_name), compute_(compute), logging_func_(logging_func) {
|
||||
std::string err;
|
||||
instance_ = PyOpLibProxy::GetInstance().new_instance_(module.c_str(), class_name_.c_str(), attrs_);
|
||||
ORT_ENFORCE(nullptr != instance_, PyOpLibProxy::GetInstance().get_last_error_message_(err));
|
||||
}
|
||||
|
||||
PyCustomKernel::~PyCustomKernel() {
|
||||
if (nullptr != instance_) {
|
||||
PyOpLibProxy::GetInstance().release_instance_(instance_);
|
||||
instance_ = nullptr;
|
||||
}
|
||||
if (nullptr != instance_) {
|
||||
PyOpLibProxy::GetInstance().release_instance_(instance_);
|
||||
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);
|
||||
auto inputs_count = (size_t) reinterpret_cast<onnxruntime::OpKernelContextInternal*>(context)->InputCount();
|
||||
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;
|
||||
|
||||
ORT_ENFORCE (nullptr != context);
|
||||
auto inputs_count = (size_t)reinterpret_cast<onnxruntime::OpKernelContextInternal*>(context)->InputCount();
|
||||
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;
|
||||
for (size_t i = 0; i < inputs_count; ++i) {
|
||||
auto ort_value = ort_.KernelContext_GetInput(context, i);
|
||||
inputs.push_back(const_cast<MLValue*>(ort_value)->Get<Tensor>().DataRaw());
|
||||
inputs_type.push_back(GetType(ort_value));
|
||||
inputs_dim.push_back(const_cast<MLValue*>(ort_value)->Get<Tensor>().Shape().GetDims());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < inputs_count; ++i) {
|
||||
auto ort_value = ort_.KernelContext_GetInput(context, i);
|
||||
inputs.push_back(const_cast<MLValue*>(ort_value)->Get<Tensor>().DataRaw());
|
||||
inputs_type.push_back(GetType(ort_value));
|
||||
inputs_dim.push_back(const_cast<MLValue*>(ort_value)->Get<Tensor>().Shape().GetDims());
|
||||
}
|
||||
std::string err;
|
||||
ORT_ENFORCE(PyOpLibProxy::GetInstance().invoke_python_func_(instance_, compute_.c_str(), inputs, inputs_type,
|
||||
inputs_dim, outputs, outputs_elem_size,
|
||||
outputs_dim, logging_func_),
|
||||
PyOpLibProxy::GetInstance().get_last_error_message_(err)); //ORT_ENFORCE
|
||||
|
||||
std::string err;
|
||||
ORT_ENFORCE(PyOpLibProxy::GetInstance().invoke_python_func_(instance_, compute_.c_str(), inputs, inputs_type,
|
||||
inputs_dim, outputs, outputs_elem_size,
|
||||
outputs_dim, logging_func_),
|
||||
PyOpLibProxy::GetInstance().get_last_error_message_(err));//ORT_ENFORCE
|
||||
|
||||
for (size_t i = 0; i < outputs.size(); ++i) {
|
||||
auto ort_output = ort_.KernelContext_GetOutput(context, i, outputs_dim[i].data(), outputs_dim[i].size());
|
||||
auto output_mem_addr = ort_.GetTensorMutableData<char>(ort_output);
|
||||
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);
|
||||
}
|
||||
for (size_t i = 0; i < outputs.size(); ++i) {
|
||||
auto ort_output = ort_.KernelContext_GetOutput(context, i, outputs_dim[i].data(), outputs_dim[i].size());
|
||||
auto output_mem_addr = ort_.GetTensorMutableData<char>(ort_output);
|
||||
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::GetType(const OrtValue* input) const {
|
||||
int32_t numpy_type;
|
||||
ORT_ENFORCE (nullptr != input);
|
||||
ORT_ENFORCE(const_cast<MLValue*>(input)->IsTensor(), "input must be a tensor");
|
||||
auto data_type = const_cast<MLValue*>(input)->Get<Tensor>().DataType();
|
||||
if (data_type == DataTypeImpl::GetType<bool>()) {
|
||||
numpy_type = 0;
|
||||
} else if (data_type == DataTypeImpl::GetType<int8_t>()) {
|
||||
numpy_type = 1;
|
||||
} else if (data_type == DataTypeImpl::GetType<uint8_t>()) {
|
||||
numpy_type = 2;
|
||||
} else if (data_type == DataTypeImpl::GetType<int16_t>()) {
|
||||
numpy_type = 3;
|
||||
} else if (data_type == DataTypeImpl::GetType<uint16_t>()) {
|
||||
numpy_type = 4;
|
||||
} else if (data_type == DataTypeImpl::GetType<int32_t>()) {
|
||||
numpy_type = 5;
|
||||
} else if (data_type == DataTypeImpl::GetType<uint32_t>()) {
|
||||
numpy_type = 6;
|
||||
} else if (data_type == DataTypeImpl::GetType<int64_t>()) {
|
||||
numpy_type = 9;
|
||||
} else if (data_type == DataTypeImpl::GetType<uint64_t>()) {
|
||||
numpy_type = 10;
|
||||
} else if (data_type == DataTypeImpl::GetType<float>()) {
|
||||
numpy_type = 11;
|
||||
} else if (data_type == DataTypeImpl::GetType<double>()) {
|
||||
numpy_type = 12;
|
||||
} else ORT_ENFORCE(false, "Input type not supported");
|
||||
return numpy_type;
|
||||
int32_t numpy_type;
|
||||
ORT_ENFORCE(nullptr != input);
|
||||
ORT_ENFORCE(const_cast<MLValue*>(input)->IsTensor(), "input must be a tensor");
|
||||
auto data_type = const_cast<MLValue*>(input)->Get<Tensor>().DataType();
|
||||
if (data_type == DataTypeImpl::GetType<bool>()) {
|
||||
numpy_type = 0;
|
||||
} else if (data_type == DataTypeImpl::GetType<int8_t>()) {
|
||||
numpy_type = 1;
|
||||
} else if (data_type == DataTypeImpl::GetType<uint8_t>()) {
|
||||
numpy_type = 2;
|
||||
} else if (data_type == DataTypeImpl::GetType<int16_t>()) {
|
||||
numpy_type = 3;
|
||||
} else if (data_type == DataTypeImpl::GetType<uint16_t>()) {
|
||||
numpy_type = 4;
|
||||
} else if (data_type == DataTypeImpl::GetType<int32_t>()) {
|
||||
numpy_type = 5;
|
||||
} else if (data_type == DataTypeImpl::GetType<uint32_t>()) {
|
||||
numpy_type = 6;
|
||||
} else if (data_type == DataTypeImpl::GetType<int64_t>()) {
|
||||
numpy_type = 9;
|
||||
} else if (data_type == DataTypeImpl::GetType<uint64_t>()) {
|
||||
numpy_type = 10;
|
||||
} else if (data_type == DataTypeImpl::GetType<float>()) {
|
||||
numpy_type = 11;
|
||||
} else if (data_type == DataTypeImpl::GetType<double>()) {
|
||||
numpy_type = 12;
|
||||
} else
|
||||
ORT_ENFORCE(false, "Input type not supported");
|
||||
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; }
|
||||
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(Ort::CustomOpApi api, const OrtKernelInfo*) {
|
||||
return new PyCustomKernel(api, attrs_, module_, class_name_, compute_, logging_func_);
|
||||
return new PyCustomKernel(api, attrs_, module_, class_name_, compute_, logging_func_);
|
||||
}
|
||||
|
||||
const char* PyCustomOp::GetName() const { return "PyOp"; }
|
||||
|
|
@ -144,35 +142,37 @@ ONNXTensorElementDataType PyCustomOp::GetInputType(size_t index) const { return
|
|||
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 (attr.has_s()) {
|
||||
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);
|
||||
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
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <cmath>
|
||||
|
||||
#include "core/common/common.h"
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/graph/onnx_protobuf.h"
|
||||
#include "core/util/math.h"
|
||||
|
||||
|
|
@ -52,7 +53,7 @@ class Initializer final {
|
|||
|
||||
Initializer(const ONNX_NAMESPACE::TensorProto* tensor_proto) : size_(0) {
|
||||
data_type_ = tensor_proto->data_type();
|
||||
if (tensor_proto->has_name()) {
|
||||
if (utils::HasName(*tensor_proto)) {
|
||||
name_ = tensor_proto->name();
|
||||
}
|
||||
dims_.reserve(tensor_proto->dims_size());
|
||||
|
|
@ -62,7 +63,7 @@ class Initializer final {
|
|||
|
||||
size_ = std::accumulate(dims_.begin(), dims_.end(), static_cast<int64_t>(1), std::multiplies<int64_t>{});
|
||||
|
||||
if (tensor_proto->has_raw_data()) {
|
||||
if (utils::HasRawData(*tensor_proto)) {
|
||||
raw_data_ = tensor_proto->raw_data();
|
||||
} else {
|
||||
switch (data_type_) {
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ void NchwcTransformerImpl::ConvPoolShapeInference(const Node& node,
|
|||
|
||||
auto* auto_pad_attr = graph_utils::GetNodeAttribute(node, "auto_pad");
|
||||
bool auto_pad_same_shape = false;
|
||||
if (auto_pad_attr != nullptr && auto_pad_attr->has_s()) {
|
||||
if (auto_pad_attr != nullptr && utils::HasString(*auto_pad_attr)) {
|
||||
auto& auto_pad = auto_pad_attr->s();
|
||||
if (auto_pad != "NOTSET") {
|
||||
if (auto_pad == "SAME_UPPER" || auto_pad == "SAME_LOWER") {
|
||||
|
|
@ -303,7 +303,7 @@ void NchwcTransformerImpl::TransformConv(Node& node) {
|
|||
|
||||
int64_t group_count;
|
||||
auto* group_attr = graph_utils::GetNodeAttribute(node, "group");
|
||||
if (group_attr != nullptr && group_attr->has_i()) {
|
||||
if (group_attr != nullptr && utils::HasInt(*group_attr)) {
|
||||
group_count = group_attr->i();
|
||||
} else {
|
||||
group_count = 1;
|
||||
|
|
@ -471,7 +471,7 @@ void NchwcTransformerImpl::TransformPool(Node& node) {
|
|||
return;
|
||||
}
|
||||
auto& channels_dim = input_shape->dim(1);
|
||||
if (!channels_dim.has_dim_value()) {
|
||||
if (!utils::HasDimValue(channels_dim)) {
|
||||
return;
|
||||
}
|
||||
const int64_t channels = channels_dim.dim_value();
|
||||
|
|
@ -539,8 +539,8 @@ void NchwcTransformerImpl::TransformAdd(Node& node) {
|
|||
}
|
||||
auto& nchwc_input_0_dim = nchwc_input_0_shape->dim(i);
|
||||
auto& nchwc_input_n_dim = nchwc_input_n_shape->dim(i);
|
||||
if (!nchwc_input_0_dim.has_dim_value() ||
|
||||
!nchwc_input_n_dim.has_dim_value() ||
|
||||
if (!utils::HasDimValue(nchwc_input_0_dim) ||
|
||||
!utils::HasDimValue(nchwc_input_n_dim) ||
|
||||
(nchwc_input_0_dim.dim_value() <= 0) ||
|
||||
(nchwc_input_0_dim.dim_value() != nchwc_input_n_dim.dim_value())) {
|
||||
return;
|
||||
|
|
@ -594,7 +594,7 @@ void NchwcTransformerImpl::TransformConcat(Node& node) {
|
|||
|
||||
// Verify that this is a concatenation along the channel axis.
|
||||
auto* axis_attr = graph_utils::GetNodeAttribute(node, "axis");
|
||||
if (axis_attr == nullptr || !axis_attr->has_i() || axis_attr->i() != 1) {
|
||||
if (axis_attr == nullptr || !utils::HasInt(*axis_attr) || axis_attr->i() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ bool ShapeToInitializer::SatisfyCondition(const Graph& graph, const Node& node)
|
|||
|
||||
for (int i = 0, num_dims = input_shape->dim_size(); i < num_dims; i++) {
|
||||
const auto& input_dim = input_shape->dim(i);
|
||||
if (!input_dim.has_dim_value() || input_dim.dim_value() < 0) {
|
||||
if (!utils::HasDimValue(input_dim) || input_dim.dim_value() < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@ ONNX_CPU_OPERATOR_KERNEL(
|
|||
|
||||
void onnxruntime::ConstantOfShapeBase::SetValueFromTensorProto(const ONNX_NAMESPACE::TensorProto& t_proto) {
|
||||
using namespace utils;
|
||||
ORT_ENFORCE(t_proto.has_data_type());
|
||||
ORT_ENFORCE(utils::HasDataType(t_proto));
|
||||
ORT_ENFORCE(TensorProto::DataType_IsValid(t_proto.data_type()));
|
||||
const auto tensor_type = static_cast<TensorProto_DataType>(t_proto.data_type());
|
||||
const void* const raw_data = t_proto.has_raw_data() ? t_proto.raw_data().data() : nullptr;
|
||||
const size_t raw_data_len = t_proto.has_raw_data() ? t_proto.raw_data().size() : 0;
|
||||
const void* const raw_data = utils::HasRawData(t_proto) ? t_proto.raw_data().data() : nullptr;
|
||||
const size_t raw_data_len = utils::HasRawData(t_proto) ? t_proto.raw_data().size() : 0;
|
||||
switch (tensor_type) {
|
||||
case TensorProto::BOOL:
|
||||
FETCH_VALUE_DATA(bool);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ bool NodeArgShapeUnknownOnAxis(const NodeArg* def, int64_t axis) {
|
|||
axis = HandleNegativeAxis(axis, shape->dim_size());
|
||||
ORT_ENFORCE(axis < shape->dim_size());
|
||||
auto dim = shape->dim(axis);
|
||||
return dim.has_dim_param() || (!dim.has_dim_param() && !dim.has_dim_value());
|
||||
return utils::HasDimParam(dim) || (!utils::HasDimParam(dim) && !utils::HasDimValue(dim));
|
||||
}
|
||||
|
||||
bool HasUnknownShapeOnAxis(const ConstPointerContainer<std::vector<NodeArg*>>& defs, int64_t axis) {
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ static bool CreateInput(const NodeArg* def,
|
|||
input = ShapeExpr(rank);
|
||||
for (int i = 0; i < rank; ++i) {
|
||||
const auto& dim = def_shape->dim()[i];
|
||||
if (dim.has_dim_value())
|
||||
if (utils::HasDimValue(dim))
|
||||
input[i] = DimExpr(dim.dim_value());
|
||||
else if (dim.has_dim_param())
|
||||
else if (utils::HasDimParam(dim))
|
||||
input[i] = DimExpr(dim.dim_param());
|
||||
else {
|
||||
input[i] = DimExpr(NormalizeNodeArgName(def) + "_dim" + std::to_string(i));
|
||||
|
|
@ -56,7 +56,7 @@ static Status CreateOutputs(
|
|||
if (shape[d] > 0) {
|
||||
output_shape[d] = DimExpr(shape[d]);
|
||||
} else {
|
||||
ORT_RETURN_IF_NOT(shape_proto->dim_size() > d && shape_proto->dim(d).has_dim_param());
|
||||
ORT_RETURN_IF_NOT(shape_proto->dim_size() > d && utils::HasDimParam(shape_proto->dim(d)));
|
||||
output_shape[d] = DimExpr(shape_proto->dim(d).dim_param());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ NupharExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_vie
|
|||
all_shape_defined = false;
|
||||
} else {
|
||||
for (const auto& dim : def.Shape()->dim()) {
|
||||
if (!((dim.has_dim_value() && dim.dim_value() > 0) || dim.has_dim_param()))
|
||||
if (!((utils::HasDimValue(dim) && dim.dim_value() > 0) || utils::HasDimParam(dim)))
|
||||
all_shape_defined = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "core/codegen/common/common.h"
|
||||
#include "core/common/logging/logging.h"
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/providers/nuphar/common/analysis/subgraph_partition_stats.h"
|
||||
#include "core/providers/nuphar/common/nuphar_settings.h"
|
||||
#include "core/providers/nuphar/common/utils.h"
|
||||
|
|
@ -41,10 +42,10 @@ bool GraphPartitioner::IsNodeSupported(const Node& node) const {
|
|||
node.ForEachDef([&](const NodeArg& def, bool is_input) {
|
||||
if (is_input == check_input && def.Shape() != nullptr) {
|
||||
for (const auto& dim : def.Shape()->dim()) {
|
||||
if (dim.has_dim_param())
|
||||
if (utils::HasDimParam(dim))
|
||||
symbolic_dimensions.insert(dim.dim_param());
|
||||
else
|
||||
ORT_ENFORCE(dim.has_dim_value() && dim.dim_value() > 0);
|
||||
ORT_ENFORCE(utils::HasDimValue(dim) && dim.dim_value() > 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define PY_ARRAY_UNIQUE_SYMBOL onnxruntime_python_ARRAY_API
|
||||
#include <numpy/arrayobject.h>
|
||||
|
||||
#include "core/framework/tensorprotoutils.h"
|
||||
#include "core/graph/graph_viewer.h"
|
||||
#include "core/common/logging/logging.h"
|
||||
#include "core/common/logging/severity.h"
|
||||
|
|
@ -581,9 +582,9 @@ including arg name, arg type (contains both type and shape).)pbdoc")
|
|||
} else {
|
||||
res << "[";
|
||||
for (int i = 0; i < shape->dim_size(); ++i) {
|
||||
if (shape->dim(i).has_dim_value()) {
|
||||
if (utils::HasDimValue(shape->dim(i))) {
|
||||
res << shape->dim(i).dim_value();
|
||||
} else if (shape->dim(i).has_dim_param()) {
|
||||
} else if (utils::HasDimParam(shape->dim(i))) {
|
||||
res << "'" << shape->dim(i).dim_param() << "'";
|
||||
} else {
|
||||
res << "None";
|
||||
|
|
@ -609,9 +610,9 @@ including arg name, arg type (contains both type and shape).)pbdoc")
|
|||
|
||||
arr.resize(shape->dim_size());
|
||||
for (int i = 0; i < shape->dim_size(); ++i) {
|
||||
if (shape->dim(i).has_dim_value()) {
|
||||
if (utils::HasDimValue(shape->dim(i))) {
|
||||
arr[i] = py::cast(shape->dim(i).dim_value());
|
||||
} else if (shape->dim(i).has_dim_param()) {
|
||||
} else if (utils::HasDimParam(shape->dim(i))) {
|
||||
arr[i] = py::cast(shape->dim(i).dim_param());
|
||||
} else {
|
||||
arr[i] = py::none();
|
||||
|
|
|
|||
|
|
@ -284,12 +284,22 @@ bool AreShapesEqual(const std::vector<int64_t>& real_shape, const ::ONNX_NAMESPA
|
|||
if (len < 0) return false;
|
||||
if (real_shape.size() != static_cast<size_t>(len)) return false;
|
||||
for (int i = 0; i != len; ++i) {
|
||||
if (!expected_shape.dim(i).has_dim_value()) {
|
||||
// symbolic shape, cannot validate it right now, assume it matches every thing
|
||||
continue;
|
||||
const auto& dim = expected_shape.dim(i);
|
||||
switch (dim.value_case()) {
|
||||
case ONNX_NAMESPACE::TensorShapeProto::Dimension::kDimValue:
|
||||
if (dim.dim_value() != real_shape[i]) return false;
|
||||
break;
|
||||
case ONNX_NAMESPACE::TensorShapeProto::Dimension::kDimParam:
|
||||
// symbolic shape, cannot validate it right now, assume it matches every thing
|
||||
// fall through
|
||||
case ONNX_NAMESPACE::TensorShapeProto::Dimension::VALUE_NOT_SET:
|
||||
// Value not set is treated as can not be validated
|
||||
continue;
|
||||
break;
|
||||
// This is for unlikely case when we add new oneof value
|
||||
default : assert(false);
|
||||
break;
|
||||
}
|
||||
::google::protobuf::int64 d = expected_shape.dim(i).dim_value();
|
||||
if (d != real_shape[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue