mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-29 20:14:01 +00:00
Support disabling support for the optional type in ORT builds (#9745)
This commit is contained in:
parent
9fb3fac5a0
commit
e23892ddbe
34 changed files with 1548 additions and 1213 deletions
|
|
@ -108,6 +108,7 @@ option(onnxruntime_USE_ROCM "Build with AMD GPU support" OFF)
|
|||
option(onnxruntime_DISABLE_CONTRIB_OPS "Disable contrib ops" OFF)
|
||||
option(onnxruntime_DISABLE_ML_OPS "Disable traditional ML ops" OFF)
|
||||
option(onnxruntime_DISABLE_SPARSE_TENSORS "Disable sparse tensors data types" OFF)
|
||||
option(onnxruntime_DISABLE_OPTIONAL_TYPE "Disable optional type" OFF)
|
||||
option(onnxruntime_MINIMAL_BUILD "Exclude as much as possible from the build. Support ORT format models. No support for ONNX format models." OFF)
|
||||
cmake_dependent_option(onnxruntime_DISABLE_RTTI "Disable RTTI" ON "NOT onnxruntime_ENABLE_PYTHON" OFF)
|
||||
# For now onnxruntime_DISABLE_EXCEPTIONS will only work with onnxruntime_MINIMAL_BUILD, more changes (ONNX, non-CPU EP, ...) are required to run this standalone
|
||||
|
|
@ -817,6 +818,10 @@ if (onnxruntime_DISABLE_SPARSE_TENSORS)
|
|||
add_compile_definitions(DISABLE_SPARSE_TENSORS)
|
||||
endif()
|
||||
|
||||
if (onnxruntime_DISABLE_OPTIONAL_TYPE)
|
||||
add_compile_definitions(DISABLE_OPTIONAL_TYPE)
|
||||
endif()
|
||||
|
||||
if (onnxruntime_USE_CUDA AND "${onnxruntime_CUDNN_HOME}" STREQUAL "")
|
||||
message(FATAL_ERROR "onnxruntime_CUDNN_HOME required for onnxruntime_USE_CUDA")
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -60,7 +60,9 @@ class SparseTensorTypeBase;
|
|||
#endif
|
||||
class SequenceTensorTypeBase;
|
||||
class NonTensorTypeBase;
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
class OptionalTypeBase;
|
||||
#endif
|
||||
class PrimitiveDataTypeBase;
|
||||
class Tensor;
|
||||
class TensorSeq;
|
||||
|
|
@ -132,9 +134,11 @@ class DataTypeImpl {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
virtual const OptionalTypeBase* AsOptionalType() const {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual const NonTensorTypeBase* AsNonTensorType() const {
|
||||
return nullptr;
|
||||
|
|
@ -319,11 +323,13 @@ struct IsSparseTensorContainedType : public IsAnyOf<T, float, uint8_t, int8_t, u
|
|||
};
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
/// Tells if the specified type is one of ORT types
|
||||
/// that can be contained within an optional struct.
|
||||
template <typename T>
|
||||
struct IsOptionalOrtType : public IsAnyOf<T, Tensor, TensorSeq> {
|
||||
};
|
||||
#endif
|
||||
|
||||
/// This template's Get() returns a corresponding MLDataType
|
||||
/// It dispatches the call to either GetTensorType<>() or
|
||||
|
|
@ -505,6 +511,49 @@ class TensorType : public TensorTypeBase {
|
|||
}
|
||||
};
|
||||
|
||||
#if defined(DISABLE_OPTIONAL_TYPE)
|
||||
|
||||
/// Common base-class for all disabled types. We need DataTypeImpl::ToString to work in a minimal build
|
||||
/// with disabled types to keep the ORT format model kernel hashes stable.
|
||||
class DisabledTypeBase : public DataTypeImpl {
|
||||
public:
|
||||
static MLDataType Type();
|
||||
|
||||
bool IsCompatible(const ONNX_NAMESPACE::TypeProto&) const override {
|
||||
// We always want to return false for the IsCompatible() for a disabled type
|
||||
// because this will ensure that no kernel supporting the disabled type will
|
||||
// be matched to a model node requiring that type and the model load will
|
||||
// result in failure.
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t Size() const override {
|
||||
ORT_THROW("Type is disabled in this build.");
|
||||
}
|
||||
|
||||
DeleteFunc GetDeleteFunc() const override {
|
||||
ORT_THROW("Type is disabled in this build.");
|
||||
}
|
||||
|
||||
// This must work
|
||||
const ONNX_NAMESPACE::TypeProto* GetTypeProto() const override;
|
||||
|
||||
ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(DisabledTypeBase);
|
||||
|
||||
protected:
|
||||
// This must work
|
||||
ONNX_NAMESPACE::TypeProto& MutableTypeProto();
|
||||
|
||||
DisabledTypeBase();
|
||||
~DisabledTypeBase() override;
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
Impl* impl_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
/// Common base-class for all sparse-tensors (with different element types).
|
||||
class SparseTensorTypeBase : public DataTypeImpl {
|
||||
|
|
@ -569,6 +618,8 @@ class SparseTensorType : public SparseTensorTypeBase {
|
|||
#endif // !defined(DISABLE_SPARSE_TENSORS)
|
||||
|
||||
/// Common base-class for all optional types.
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
class OptionalTypeBase : public DataTypeImpl {
|
||||
public:
|
||||
static MLDataType Type();
|
||||
|
|
@ -613,18 +664,28 @@ class OptionalTypeBase : public DataTypeImpl {
|
|||
struct Impl;
|
||||
Impl* impl_;
|
||||
};
|
||||
#endif
|
||||
|
||||
// Derive from OptionalTypeBase if the Optional type support is enabled,
|
||||
// else derive from DisabledTypeBase
|
||||
template <typename T, typename elemT>
|
||||
class OptionalType : public OptionalTypeBase {
|
||||
class OptionalType :
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
public OptionalTypeBase
|
||||
#else
|
||||
public DisabledTypeBase
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
static MLDataType Type();
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
static_assert(data_types_internal::IsOptionalOrtType<T>::value,
|
||||
"Requires one of the supported types: Tensor or TensorSeq");
|
||||
|
||||
static_assert(data_types_internal::IsTensorContainedType<elemT>::value,
|
||||
"Requires one of the tensor fundamental types");
|
||||
|
||||
static MLDataType Type();
|
||||
|
||||
MLDataType GetElementType() const override {
|
||||
if (std::is_same<T, Tensor>::value) {
|
||||
return DataTypeImpl::GetTensorType<elemT>();
|
||||
|
|
@ -635,6 +696,7 @@ class OptionalType : public OptionalTypeBase {
|
|||
ORT_ENFORCE(false, "Unsupported optional type");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
OptionalType() {
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ class OpKernelContext {
|
|||
SparseTensor* OutputSparse(int index, const TensorShape& shape);
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// Use this API to output a "None" of a specific type (e.g. Tensor) at specified index
|
||||
template <typename T>
|
||||
void OutputOptionalWithoutData(int index) {
|
||||
|
|
@ -92,6 +93,7 @@ class OpKernelContext {
|
|||
type,
|
||||
type->GetDeleteFunc());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Retrieve indexed shape obtained from memory planning before actual
|
||||
// computation. If the indexed shape cannot be inferred, this function returns
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ struct OrtValue {
|
|||
template <typename T>
|
||||
const T& Get() const {
|
||||
ORT_ENFORCE(onnxruntime::DataTypeImpl::GetType<T>() == type_, onnxruntime::DataTypeImpl::GetType<T>(), " != ", type_);
|
||||
ORT_ENFORCE(IsAllocated(), "OrtValue contains no data");
|
||||
return *static_cast<T*>(data_.get());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -447,12 +447,16 @@ class PlannerImpl {
|
|||
// TODO this should be an error case, needs more investigation
|
||||
continue;
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// Make sure optional types are not up for re-use as we aren't quite
|
||||
// sure if the re-used tensor will be a None or otherwise. This cannot
|
||||
// be determined statically.
|
||||
if (IsOptionalType(*p_node_arg)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto& available_memory_info = AllocPlan(p_node_arg->Name()).location;
|
||||
if (!(available_memory_info == required_memory_info)) continue;
|
||||
auto p_available_buffer_shape = context_.GetShape(*p_node_arg);
|
||||
|
|
@ -1142,10 +1146,12 @@ class PlannerImpl {
|
|||
return !utils::HasTensorType(type_proto);
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
static bool IsOptionalType(const onnxruntime::NodeArg& nodearg) {
|
||||
const auto* type_proto = nodearg.TypeAsProto();
|
||||
return type_proto->value_case() == ONNX_NAMESPACE::TypeProto::kOptionalType;
|
||||
}
|
||||
#endif
|
||||
|
||||
//For in-place reuse tensors, the lifetime is the union of all the tensors that tensors that use that buffer
|
||||
#if !defined(ORT_MINIMAL_BUILD) && defined(ORT_MEMORY_PROFILE)
|
||||
|
|
|
|||
|
|
@ -151,6 +151,11 @@ bool IsCompatible(const ONNX_NAMESPACE::TypeProto_SparseTensor& tensor_proto,
|
|||
const ONNX_NAMESPACE::TypeProto_SparseTensor& type_proto);
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Optional& optional_proto,
|
||||
const ONNX_NAMESPACE::TypeProto_Optional& type_proto);
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_ML_OPS)
|
||||
bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Map& map_proto,
|
||||
const ONNX_NAMESPACE::TypeProto_Map& type_proto);
|
||||
|
|
@ -196,6 +201,11 @@ bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Map& map_proto,
|
|||
case TypeProto::ValueCase::kSparseTensorType:
|
||||
result = IsCompatible(lhs.value_type().sparse_tensor_type(), rhs.value_type().sparse_tensor_type());
|
||||
break;
|
||||
#endif
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
case TypeProto::ValueCase::kOptionalType:
|
||||
result = IsCompatible(lhs.value_type().optional_type(), rhs.value_type().optional_type());
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ORT_ENFORCE(false);
|
||||
|
|
@ -231,6 +241,11 @@ static bool IsCompatible(const ONNX_NAMESPACE::TypeProto& type_proto_1,
|
|||
case TypeProto::ValueCase::kSparseTensorType:
|
||||
result = IsCompatible(type_proto_1.sparse_tensor_type(), type_proto_2.sparse_tensor_type());
|
||||
break;
|
||||
#endif
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
case TypeProto::ValueCase::kOptionalType:
|
||||
result = IsCompatible(type_proto_1.optional_type(), type_proto_2.optional_type());
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ORT_ENFORCE(false);
|
||||
|
|
@ -247,10 +262,12 @@ bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Sequence& sequence_proto,
|
|||
return IsCompatible(sequence_proto.elem_type(), type_proto.elem_type());
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Optional& optional_proto,
|
||||
const ONNX_NAMESPACE::TypeProto_Optional& type_proto) {
|
||||
return IsCompatible(optional_proto.elem_type(), type_proto.elem_type());
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IsCompatible(const ONNX_NAMESPACE::TypeProto_Opaque& opaque_proto,
|
||||
const ONNX_NAMESPACE::TypeProto_Opaque& type_proto) {
|
||||
|
|
@ -493,6 +510,7 @@ MLDataType SequenceTensorTypeBase::Type() {
|
|||
return &sequence_tensor_base;
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
///// OptionalTypeBase
|
||||
|
||||
struct OptionalTypeBase::Impl : public data_types_internal::TypeProtoImpl {
|
||||
|
|
@ -531,6 +549,33 @@ MLDataType OptionalTypeBase::Type() {
|
|||
static OptionalTypeBase optional_type_base;
|
||||
return &optional_type_base;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// DisabledTypeBase
|
||||
|
||||
#if defined(DISABLE_OPTIONAL_TYPE)
|
||||
struct DisabledTypeBase::Impl : public data_types_internal::TypeProtoImpl {
|
||||
};
|
||||
|
||||
DisabledTypeBase::DisabledTypeBase() : impl_(new Impl()) {}
|
||||
|
||||
DisabledTypeBase::~DisabledTypeBase() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
const ONNX_NAMESPACE::TypeProto* DisabledTypeBase::GetTypeProto() const {
|
||||
return impl_->GetProto();
|
||||
}
|
||||
|
||||
ONNX_NAMESPACE::TypeProto& DisabledTypeBase::MutableTypeProto() {
|
||||
return impl_->MutableTypeProto();
|
||||
}
|
||||
|
||||
MLDataType DisabledTypeBase::Type() {
|
||||
static DisabledTypeBase disabled_base;
|
||||
return &disabled_base;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// NoTensorTypeBase
|
||||
struct NonTensorTypeBase::Impl : public data_types_internal::TypeProtoImpl {};
|
||||
|
|
@ -695,11 +740,13 @@ ORT_REGISTER_OPTIONAL_ORT_TYPE(TensorSeq)
|
|||
reg_fn(mltype); \
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
#define REGISTER_OPTIONAL_PROTO(ORT_TYPE, TYPE, reg_fn) \
|
||||
{ \
|
||||
MLDataType mltype = DataTypeImpl::GetOptionalType<ORT_TYPE, TYPE>(); \
|
||||
reg_fn(mltype); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
#define REGISTER_SPARSE_TENSOR_PROTO(TYPE, reg_fn) \
|
||||
|
|
@ -781,6 +828,7 @@ void RegisterAllProtos(const std::function<void(MLDataType)>& reg_fn) {
|
|||
REGISTER_ONNX_PROTO(VectorMapInt64ToFloat, reg_fn);
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
#define REGISTER_OPTIONAL_PROTO_ORT_TYPE(ORT_TYPE, reg_fn) \
|
||||
REGISTER_OPTIONAL_PROTO(ORT_TYPE, int32_t, reg_fn); \
|
||||
REGISTER_OPTIONAL_PROTO(ORT_TYPE, float, reg_fn); \
|
||||
|
|
@ -799,6 +847,7 @@ void RegisterAllProtos(const std::function<void(MLDataType)>& reg_fn) {
|
|||
|
||||
REGISTER_OPTIONAL_PROTO_ORT_TYPE(Tensor, reg_fn);
|
||||
REGISTER_OPTIONAL_PROTO_ORT_TYPE(TensorSeq, reg_fn);
|
||||
#endif
|
||||
}
|
||||
} // namespace data_types_internal
|
||||
|
||||
|
|
@ -1030,18 +1079,6 @@ std::vector<MLDataType> GetOptionalTensorTypesFromTypeList() {
|
|||
return boost::mp11::mp_apply<GetOptionalTensorTypesImpl, L>{}();
|
||||
}
|
||||
|
||||
template <typename... ElementTypes>
|
||||
struct GetSequenceTensorTypesImpl {
|
||||
std::vector<MLDataType> operator()() const {
|
||||
return {DataTypeImpl::GetSequenceTensorType<ElementTypes>()...};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename L>
|
||||
std::vector<MLDataType> GetSequenceTensorTypesFromTypeList() {
|
||||
return boost::mp11::mp_apply<GetSequenceTensorTypesImpl, L>{}();
|
||||
}
|
||||
|
||||
template <typename... ElementTypes>
|
||||
struct GetOptionalSequenceTensorTypesImpl {
|
||||
std::vector<MLDataType> operator()() const {
|
||||
|
|
@ -1054,6 +1091,18 @@ std::vector<MLDataType> GetOptionalSequenceTensorTypesFromTypeList() {
|
|||
return boost::mp11::mp_apply<GetOptionalSequenceTensorTypesImpl, L>{}();
|
||||
}
|
||||
|
||||
template <typename... ElementTypes>
|
||||
struct GetSequenceTensorTypesImpl {
|
||||
std::vector<MLDataType> operator()() const {
|
||||
return {DataTypeImpl::GetSequenceTensorType<ElementTypes>()...};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename L>
|
||||
std::vector<MLDataType> GetSequenceTensorTypesFromTypeList() {
|
||||
return boost::mp11::mp_apply<GetSequenceTensorTypesImpl, L>{}();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const std::vector<MLDataType>& DataTypeImpl::AllFixedSizeTensorExceptHalfTypes() {
|
||||
|
|
@ -1200,10 +1249,12 @@ ContainerChecker::ContainerChecker(MLDataType ml_type) {
|
|||
types_.emplace_back(ContainerType::kSequence, TensorProto_DataType_UNDEFINED);
|
||||
type_proto = &type_proto->sequence_type().elem_type();
|
||||
break;
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
case TypeProto::ValueCase::kOptionalType:
|
||||
types_.emplace_back(ContainerType::kOptional, TensorProto_DataType_UNDEFINED);
|
||||
type_proto = &type_proto->optional_type().elem_type();
|
||||
break;
|
||||
#endif
|
||||
case TypeProto::ValueCase::kOpaqueType:
|
||||
// We do not handle this and terminate here
|
||||
types_.emplace_back(ContainerType::kOpaque,
|
||||
|
|
|
|||
|
|
@ -687,13 +687,21 @@ Status ExecutionFrame::AllocateAsPerAllocationPlan(OrtValue& ort_value, int ort_
|
|||
return status;
|
||||
}
|
||||
|
||||
if (ml_type->IsTensorType() || utils::IsOptionalTensor(ml_type)) {
|
||||
if (ml_type->IsTensorType()
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|| utils::IsOptionalTensor(ml_type)
|
||||
#endif
|
||||
) {
|
||||
ORT_ENFORCE(shape, "Allocation of tensor types requires a shape.");
|
||||
|
||||
// tensors / optional tensors
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
const auto* ml_data_type = ml_type->IsTensorType()
|
||||
? static_cast<const TensorTypeBase*>(ml_type)->GetElementType()
|
||||
: utils::GetElementTypeFromOptionalTensor(ml_type);
|
||||
#else
|
||||
const auto* ml_data_type = static_cast<const TensorTypeBase*>(ml_type)->GetElementType();
|
||||
#endif
|
||||
|
||||
AllocKind alloc_kind = per_alloc_plan.alloc_kind;
|
||||
switch (alloc_kind) {
|
||||
|
|
@ -741,7 +749,11 @@ Status ExecutionFrame::AllocateAsPerAllocationPlan(OrtValue& ort_value, int ort_
|
|||
// Model load should have failed so this should be unreachable
|
||||
ORT_THROW("SparseTensor is not supported in this build.");
|
||||
#endif
|
||||
} else if (ml_type->IsTensorSequenceType() || utils::IsOptionalSeqTensor(ml_type)) {
|
||||
} else if (ml_type->IsTensorSequenceType()
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|| utils::IsOptionalSeqTensor(ml_type)
|
||||
#endif
|
||||
) {
|
||||
AllocKind alloc_kind = per_alloc_plan.alloc_kind;
|
||||
|
||||
if (alloc_kind == AllocKind::kReuse) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ namespace onnxruntime {
|
|||
namespace utils {
|
||||
MLDataType GetMLDataType(const onnxruntime::NodeArg& arg);
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
inline bool IsOptionalTensor(MLDataType type) {
|
||||
return type->IsOptionalType() &&
|
||||
type->AsOptionalType()->GetElementType()->IsTensorType();
|
||||
|
|
@ -40,5 +41,7 @@ inline MLDataType GetElementTypeFromOptionalSeqTensor(MLDataType type) {
|
|||
->AsSequenceTensorType()
|
||||
->GetElementType();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace utils
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ inline bool HasTensorType(const ONNX_NAMESPACE::TypeProto& type_proto) {
|
|||
return type_proto.value_case() == ONNX_NAMESPACE::TypeProto::kTensorType;
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
inline bool HasOptionalTensorType(const ONNX_NAMESPACE::TypeProto& type_proto) {
|
||||
return type_proto.value_case() == ONNX_NAMESPACE::TypeProto::kOptionalType &&
|
||||
type_proto.optional_type().elem_type().value_case() == ONNX_NAMESPACE::TypeProto::kTensorType;
|
||||
|
|
@ -155,6 +156,7 @@ inline ONNX_NAMESPACE::TypeProto* GetMutableOptionalTypeProto(ONNX_NAMESPACE::Ty
|
|||
inline bool HasElemType(const ONNX_NAMESPACE::TypeProto_Optional& opt_proto) {
|
||||
return opt_proto.elem_type().value_case() != ONNX_NAMESPACE::TypeProto::VALUE_NOT_SET;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool HasElemType(const ONNX_NAMESPACE::TypeProto_Tensor& ten_proto) {
|
||||
return ten_proto.elem_type() != ONNX_NAMESPACE::TensorProto::UNDEFINED;
|
||||
|
|
@ -191,10 +193,12 @@ inline bool HasElementType(const ONNX_NAMESPACE::TypeProto& type_proto) {
|
|||
}
|
||||
#endif // !defined(DISABLE_SPARSE_TENSORS)
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
if (HasOptionalTensorType(type_proto) &&
|
||||
HasShape(GetOptionalTypeProto(type_proto).tensor_type())) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -222,9 +226,11 @@ inline const ONNX_NAMESPACE::TensorShapeProto& GetShape(const ONNX_NAMESPACE::Ty
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
if (HasOptionalTensorType(type_proto) && HasShape(GetOptionalTypeProto(type_proto).tensor_type())) {
|
||||
return GetOptionalTypeProto(type_proto).tensor_type().shape();
|
||||
}
|
||||
#endif
|
||||
|
||||
ORT_THROW("TypeProto must have shape for this to run");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,30 +69,42 @@ static bool UsingLatestOnnxOpset(const DomainToVersionMap& opset_versions) {
|
|||
static Status MergeShapeInfo(const std::string& output_name,
|
||||
const TypeProto& source, TypeProto& target,
|
||||
bool strict, const logging::Logger& logger) {
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
if (!(utils::HasTensorType(source) && utils::HasTensorType(target)) &&
|
||||
!(utils::HasOptionalTensorType(source) && utils::HasOptionalTensorType(target)) &&
|
||||
!(utils::HasSparseTensorType(source) && utils::HasSparseTensorType(target))) {
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL,
|
||||
"Source and target must both be either tensors, "
|
||||
"optional tensors, or sparse tensors");
|
||||
}
|
||||
#else
|
||||
if (!(utils::HasTensorType(source) && utils::HasTensorType(target))) {
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL,
|
||||
"Source and target must both be tensors");
|
||||
}
|
||||
if (!(utils::HasTensorType(source) && utils::HasTensorType(target))
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
&& !(utils::HasOptionalTensorType(source) && utils::HasOptionalTensorType(target))
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
&& !(utils::HasSparseTensorType(source) && utils::HasSparseTensorType(target))
|
||||
#endif
|
||||
) {
|
||||
std::ostringstream ss;
|
||||
ss << "Source and target must both be tensors";
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
ss << " , or optional typed entities";
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
ss << " , or sparse tensors";
|
||||
#endif
|
||||
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, ss.str());
|
||||
}
|
||||
|
||||
auto status = Status::OK();
|
||||
|
||||
ORT_TRY {
|
||||
if (utils::HasTensorType(source)) {
|
||||
ONNX_NAMESPACE::mergeInShapeInfo(source.tensor_type(), *target.mutable_tensor_type());
|
||||
} else if (utils::HasOptionalTensorType(source)) {
|
||||
}
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
else if (utils::HasOptionalTensorType(source)) {
|
||||
ONNX_NAMESPACE::mergeInShapeInfo(utils::GetOptionalTypeProto(source).tensor_type(),
|
||||
*utils::GetMutableOptionalTypeProto(target)->mutable_tensor_type());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
else {
|
||||
ONNX_NAMESPACE::mergeInShapeInfo(source.sparse_tensor_type(), *target.mutable_sparse_tensor_type());
|
||||
|
|
@ -112,9 +124,13 @@ static Status MergeShapeInfo(const std::string& output_name,
|
|||
<< ". Falling back to lenient merge.";
|
||||
if (utils::HasTensorType(source)) {
|
||||
ONNX_NAMESPACE::UnionShapeInfo(utils::GetShape(source), *target.mutable_tensor_type());
|
||||
} else if (utils::HasOptionalTensorType(source)) {
|
||||
}
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
else if (utils::HasOptionalTensorType(source)) {
|
||||
ONNX_NAMESPACE::UnionShapeInfo(utils::GetShape(source), *utils::GetMutableOptionalTypeProto(target)->mutable_tensor_type());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
else {
|
||||
ONNX_NAMESPACE::UnionShapeInfo(utils::GetShape(source), *target.mutable_sparse_tensor_type());
|
||||
|
|
@ -233,6 +249,8 @@ const TensorShapeProto* NodeArg::Shape() const {
|
|||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
case TypeProto::kOptionalType: {
|
||||
// Shape is applicable only for optional tensor type
|
||||
if (utils::HasOptionalTensorType(*type) &&
|
||||
|
|
@ -241,6 +259,8 @@ const TensorShapeProto* NodeArg::Shape() const {
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
case TypeProto::kSequenceType:
|
||||
case TypeProto::kMapType:
|
||||
case TypeProto::kOpaqueType:
|
||||
|
|
@ -285,6 +305,8 @@ void NodeArg::SetShape(const TensorShapeProto& shape) {
|
|||
*(node_arg_info_.mutable_type()->mutable_sparse_tensor_type()->mutable_shape()) = shape;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
case TypeProto::kOptionalType:
|
||||
// Set shape only for optional tensors
|
||||
if (utils::HasOptionalTensorType(node_arg_info_.type())) {
|
||||
|
|
@ -293,6 +315,7 @@ void NodeArg::SetShape(const TensorShapeProto& shape) {
|
|||
->mutable_shape()) = shape;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case TypeProto::kSequenceType:
|
||||
case TypeProto::kMapType:
|
||||
case TypeProto::kOpaqueType:
|
||||
|
|
@ -313,6 +336,8 @@ void NodeArg::ClearShape() {
|
|||
node_arg_info_.mutable_type()->mutable_sparse_tensor_type()->clear_shape();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
case TypeProto::kOptionalType:
|
||||
// Clear shape only for optional tensors
|
||||
if (utils::HasOptionalTensorType(node_arg_info_.type())) {
|
||||
|
|
@ -321,6 +346,8 @@ void NodeArg::ClearShape() {
|
|||
->clear_shape();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TypeProto::kSequenceType:
|
||||
case TypeProto::kMapType:
|
||||
case TypeProto::kOpaqueType:
|
||||
|
|
@ -410,15 +437,19 @@ common::Status NodeArg::UpdateTypeAndShape(const ONNX_NAMESPACE::TypeProto& inpu
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
case TypeProto::kOptionalType: {
|
||||
if ((utils::HasOptionalTensorType(input_type) && !utils::HasOptionalTensorType(current_type)) ||
|
||||
(!utils::HasOptionalTensorType(input_type) && utils::HasOptionalTensorType(current_type))) {
|
||||
bool is_input_type_optional_tensor_type = utils::HasOptionalTensorType(input_type);
|
||||
bool is_current_type_optional_tensor_type = utils::HasOptionalTensorType(current_type);
|
||||
|
||||
// Check for homogeneity within optional type
|
||||
if (is_input_type_optional_tensor_type != is_current_type_optional_tensor_type) {
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Optional Type mismatch. Expected: ", ONNX_NAMESPACE::Utils::DataTypeUtils::ToType(current_type),
|
||||
" . Got: ", ONNX_NAMESPACE::Utils::DataTypeUtils::ToType(input_type));
|
||||
}
|
||||
|
||||
// Updating element type and shape is only applicable for optional tensors
|
||||
if (utils::HasOptionalTensorType(input_type)) {
|
||||
if (is_input_type_optional_tensor_type) {
|
||||
const auto& optional_input_type = utils::GetOptionalTypeProto(input_type);
|
||||
auto& optional_current_type = *utils::GetMutableOptionalTypeProto(current_type);
|
||||
|
||||
|
|
@ -444,6 +475,7 @@ common::Status NodeArg::UpdateTypeAndShape(const ONNX_NAMESPACE::TypeProto& inpu
|
|||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case TypeProto::kSequenceType:
|
||||
case TypeProto::kMapType:
|
||||
|
|
@ -1906,10 +1938,12 @@ bool FullyDefinedType(const TypeProto& type_proto) {
|
|||
auto& seq_type = type_proto.sequence_type();
|
||||
return utils::HasElemType(seq_type) && FullyDefinedType(seq_type.elem_type());
|
||||
}
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
case TypeProto::kOptionalType: {
|
||||
auto& optional_type = type_proto.optional_type();
|
||||
return utils::HasElemType(optional_type) && FullyDefinedType(optional_type.elem_type());
|
||||
}
|
||||
#endif
|
||||
case TypeProto::kMapType: {
|
||||
auto& map_type = type_proto.map_type();
|
||||
return utils::HasKeyType(map_type) &&
|
||||
|
|
@ -2346,11 +2380,15 @@ Status Graph::InferAndVerifyTypeMatch(Node& node, const OpSchema& op, const Reso
|
|||
TypeProto merge_target;
|
||||
if (utils::HasTensorType(onnx_inferred_type)) {
|
||||
*merge_target.mutable_tensor_type()->mutable_shape() = *output_def->Shape();
|
||||
} else if (utils::HasOptionalTensorType(onnx_inferred_type)) {
|
||||
}
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
else if (utils::HasOptionalTensorType(onnx_inferred_type)) {
|
||||
*utils::GetMutableOptionalTypeProto(merge_target)
|
||||
->mutable_tensor_type()
|
||||
->mutable_shape() = *output_def->Shape();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
else if (utils::HasSparseTensorType(onnx_inferred_type)) {
|
||||
*merge_target.mutable_sparse_tensor_type()->mutable_shape() = *output_def->Shape();
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ ONNX_CPU_OPERATOR_KERNEL(If,
|
|||
.TypeConstraint("B", DataTypeImpl::GetTensorType<bool>())
|
||||
.TypeConstraint("V", DataTypeImpl::AllTensorAndSequenceTensorAndOptionalTypes()),
|
||||
If);
|
||||
|
||||
If::Info::Info(const onnxruntime::Node& node, const GraphViewer& subgraph_in) : subgraph(subgraph_in) {
|
||||
num_implicit_inputs = static_cast<int>(node.ImplicitInputDefs().size());
|
||||
used_implicit_inputs = std::vector<bool>(num_implicit_inputs, true);
|
||||
|
|
@ -151,11 +152,13 @@ class IfImpl {
|
|||
// track where the fetches provided to subgraph execution were allocated.
|
||||
std::vector<std::pair<AllocationType, OrtValue>> outputs_;
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// track which outputs are optional tensor types
|
||||
std::vector<int> optional_tensor_type_subgraph_outputs_;
|
||||
|
||||
// track which outputs are optional tensor sequence types
|
||||
std::vector<int> optional_tensor_sequence_type_subgraph_outputs_;
|
||||
#endif
|
||||
};
|
||||
|
||||
void If::Init(const OpKernelInfo& info) {
|
||||
|
|
@ -280,18 +283,26 @@ Status IfImpl::AllocateOutputTensors() {
|
|||
|
||||
const auto& graph_outputs = info_.subgraph.GetOutputs();
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// The number of optional type outputs can be atmost the total
|
||||
// number of subgraph outputs (it is okay to over-allocate)
|
||||
optional_tensor_type_subgraph_outputs_.reserve(graph_outputs.size());
|
||||
optional_tensor_sequence_type_subgraph_outputs_.reserve(graph_outputs.size());
|
||||
#endif
|
||||
|
||||
for (auto& graph_output : graph_outputs) {
|
||||
const auto* graph_output_type = graph_output->TypeAsProto();
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
bool is_optional_tensor = utils::HasOptionalTensorType(*graph_output_type);
|
||||
bool is_optional_tensor_sequence = utils::HasOptionalTensorSequenceType(*graph_output_type);
|
||||
#endif
|
||||
|
||||
if (graph_output_type->has_tensor_type() || is_optional_tensor) {
|
||||
if (graph_output_type->has_tensor_type()
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|| is_optional_tensor
|
||||
#endif
|
||||
) {
|
||||
auto* graph_output_shape = graph_output->Shape();
|
||||
bool symbolic_dim_in_shape = false;
|
||||
|
||||
|
|
@ -315,22 +326,29 @@ Status IfImpl::AllocateOutputTensors() {
|
|||
// we still need a value to put in the feeds we give to the execution frame, so just use an empty MLValue
|
||||
outputs_.push_back({AllocationType::Delayed, {}});
|
||||
}
|
||||
} else if (graph_output_type->has_sequence_type() || is_optional_tensor_sequence) {
|
||||
} else if (graph_output_type->has_sequence_type()
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|| is_optional_tensor_sequence
|
||||
#endif
|
||||
) {
|
||||
auto* seq_tensor = context_.Output<TensorSeq>(index);
|
||||
if (!seq_tensor)
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Failed to create output tensor for ", graph_output->Name());
|
||||
outputs_.push_back({AllocationType::IfOutput, *context_.GetOutputMLValue(index)});
|
||||
} else {
|
||||
// Shouldn't hit this
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Only tensors or sequence of tensors are supported");
|
||||
// Shouldn't hit this as the kernel assignment logic should check for the types before assigning this kernel
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
|
||||
"Only tensors, tensor sequence, optional tensor, and optional tensor sequence types are supported");
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// track optional type outputs - we will use them later
|
||||
if (is_optional_tensor) {
|
||||
optional_tensor_type_subgraph_outputs_.push_back(index);
|
||||
} else if (is_optional_tensor_sequence) {
|
||||
optional_tensor_sequence_type_subgraph_outputs_.push_back(index);
|
||||
}
|
||||
#endif
|
||||
|
||||
++index;
|
||||
}
|
||||
|
|
@ -399,6 +417,7 @@ Status IfImpl::Execute(const FeedsFetchesManager& ffm) {
|
|||
|
||||
ORT_RETURN_IF_ERROR(status);
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// Deal with Nones in fetches
|
||||
for (auto& output_index : optional_tensor_type_subgraph_outputs_) {
|
||||
// "None" - reflect Nones in the output of If
|
||||
|
|
@ -415,6 +434,7 @@ Status IfImpl::Execute(const FeedsFetchesManager& ffm) {
|
|||
context_.OutputOptionalWithoutData<TensorSeq>(output_index);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ ONNX_CPU_OPERATOR_KERNEL(Loop,
|
|||
.TypeConstraint("B", DataTypeImpl::GetTensorType<bool>())
|
||||
.TypeConstraint("V", DataTypeImpl::AllTensorAndSequenceTensorAndOptionalTypes()),
|
||||
Loop);
|
||||
|
||||
Loop::Info::Info(const onnxruntime::Node& node, const GraphViewer& subgraph_in)
|
||||
: subgraph(subgraph_in) {
|
||||
num_loop_carried_vars = static_cast<int>(node.InputDefs().size()) - 2; // skip 'M' and 'cond'
|
||||
|
|
@ -509,6 +510,7 @@ Status LoopImpl::Execute(const FeedsFetchesManager& ffm) {
|
|||
// as we need the final shape.
|
||||
auto copy_mlvalue_to_output = [this](OrtValue& input, int output_idx,
|
||||
int64_t iter_num_value, const TypeProto& tp) {
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// Only Optional type can be None (i.e.) not have data
|
||||
if (tp.has_optional_type() && !input.IsAllocated()) {
|
||||
// We can't rely on the input OrtValue containing type information
|
||||
|
|
@ -519,6 +521,10 @@ Status LoopImpl::Execute(const FeedsFetchesManager& ffm) {
|
|||
static_cast<OpKernelContext*>(&context_),
|
||||
output_idx));
|
||||
} else if (input.IsTensor()) {
|
||||
#else
|
||||
ORT_UNUSED_PARAMETER(tp);
|
||||
if (input.IsTensor()) {
|
||||
#endif
|
||||
const auto& input_tensor = input.Get<Tensor>();
|
||||
Tensor* output = context_.Output(output_idx, input_tensor.Shape());
|
||||
// Safely use the IDataTransfer abstraction as we only allow using
|
||||
|
|
@ -556,6 +562,7 @@ Status LoopImpl::Execute(const FeedsFetchesManager& ffm) {
|
|||
output->SetElements(std::move(tensors));
|
||||
}
|
||||
}
|
||||
|
||||
return Status::OK();
|
||||
};
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|
||||
#include "optional_ops.h"
|
||||
#include "core/framework/ort_value.h"
|
||||
#include "core/providers/cpu/tensor/utils.h"
|
||||
|
|
@ -155,3 +157,5 @@ Status OptionalGetElement::Compute(OpKernelContext* ctx) const {
|
|||
}
|
||||
|
||||
} // namespace onnxruntime
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/common/common.h"
|
||||
|
|
@ -40,3 +42,5 @@ class OptionalGetElement final : public OpKernel {
|
|||
};
|
||||
|
||||
} // namespace onnxruntime
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -51,4 +51,5 @@ ONNX_CPU_OPERATOR_KERNEL(
|
|||
16,
|
||||
KernelDefBuilder().TypeConstraint("V", DataTypeImpl::AllTensorAndSequenceTensorAndOptionalTypes()).Alias(0, 0),
|
||||
IdentityOp<false>);
|
||||
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class IdentityOp final : public OpKernel {
|
|||
|
||||
const auto* input_ort_value = context->GetInputOrtValue(0);
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// Only Optional type can be None (i.e.) not have data
|
||||
if (input_type_proto->has_optional_type() && !input_ort_value->IsAllocated()) {
|
||||
// We can't rely on the input OrtValue containing type information
|
||||
|
|
@ -38,6 +39,9 @@ class IdentityOp final : public OpKernel {
|
|||
ORT_RETURN_IF_ERROR(utils::OutputOptionalWithoutDataHelper(*input_type_proto, context, 0));
|
||||
return Status::OK();
|
||||
}
|
||||
#else
|
||||
ORT_UNUSED_PARAMETER(input_type_proto);
|
||||
#endif
|
||||
|
||||
if (input_ort_value->IsTensor()) {
|
||||
const auto* X = &input_ort_value->Get<Tensor>();
|
||||
|
|
|
|||
|
|
@ -252,9 +252,11 @@ struct ProviderHost {
|
|||
virtual int int64s__size(const ONNX_NAMESPACE::int64s* p) = 0;
|
||||
virtual const int64_t& int64s__Get(const ONNX_NAMESPACE::int64s* p, int index) = 0;
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// TypeProto_Optional
|
||||
virtual const ONNX_NAMESPACE::TypeProto& TypeProto_Optional__elem_type(const ONNX_NAMESPACE::TypeProto_Optional* p) = 0;
|
||||
virtual ONNX_NAMESPACE::TypeProto* TypeProto_Optional__mutable_elem_type(ONNX_NAMESPACE::TypeProto_Optional* p) = 0;
|
||||
#endif
|
||||
|
||||
// TypeProto_Sequence
|
||||
virtual const ONNX_NAMESPACE::TypeProto& TypeProto_Sequence__elem_type(const ONNX_NAMESPACE::TypeProto_Sequence* p) = 0;
|
||||
|
|
@ -283,8 +285,10 @@ struct ProviderHost {
|
|||
virtual ONNX_NAMESPACE::TypeProto_SparseTensor* TypeProto__mutable_sparse_tensor_type(ONNX_NAMESPACE::TypeProto* p) = 0;
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
virtual const ONNX_NAMESPACE::TypeProto_Optional& TypeProto__optional_type(const ONNX_NAMESPACE::TypeProto* p) = 0;
|
||||
virtual ONNX_NAMESPACE::TypeProto_Optional* TypeProto__mutable_optional_type(ONNX_NAMESPACE::TypeProto* p) = 0;
|
||||
#endif
|
||||
|
||||
virtual const ONNX_NAMESPACE::TypeProto_Sequence& TypeProto__sequence_type(const ONNX_NAMESPACE::TypeProto* p) = 0;
|
||||
virtual ONNX_NAMESPACE::TypeProto_Sequence* TypeProto__mutable_sequence_type(ONNX_NAMESPACE::TypeProto* p) = 0;
|
||||
|
|
|
|||
|
|
@ -225,11 +225,13 @@ struct TypeProto_SparseTensor final {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
struct TypeProto_Optional final {
|
||||
const TypeProto& elem_type() const { return g_host->TypeProto_Optional__elem_type(this); }
|
||||
TypeProto* mutable_elem_type() { return g_host->TypeProto_Optional__mutable_elem_type(this); }
|
||||
PROVIDER_DISALLOW_ALL(TypeProto_Optional)
|
||||
};
|
||||
#endif
|
||||
|
||||
struct TypeProto_Sequence final {
|
||||
const TypeProto& elem_type() const { return g_host->TypeProto_Sequence__elem_type(this); }
|
||||
|
|
@ -246,8 +248,10 @@ struct TypeProto final {
|
|||
TypeProto_SparseTensor* mutable_sparse_tensor_type() { return g_host->TypeProto__mutable_sparse_tensor_type(this); }
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
const TypeProto_Optional& optional_type() const { return g_host->TypeProto__optional_type(this); }
|
||||
TypeProto_Optional* mutable_optional_type() { return g_host->TypeProto__mutable_optional_type(this); }
|
||||
#endif
|
||||
|
||||
const TypeProto_Sequence& sequence_type() const { return g_host->TypeProto__sequence_type(this); }
|
||||
TypeProto_Sequence* mutable_sequence_type() { return g_host->TypeProto__mutable_sequence_type(this); }
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
namespace onnxruntime {
|
||||
namespace utils {
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
common::Status OutputOptionalWithoutDataHelper(const ONNX_NAMESPACE::TypeProto& input_type_proto,
|
||||
OpKernelContext* context, int output_index) {
|
||||
if (utils::HasOptionalTensorType(input_type_proto)) {
|
||||
|
|
@ -21,6 +22,7 @@ common::Status OutputOptionalWithoutDataHelper(const ONNX_NAMESPACE::TypeProto&
|
|||
|
||||
return Status::OK();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace utils
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@
|
|||
namespace onnxruntime {
|
||||
namespace utils {
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
common::Status OutputOptionalWithoutDataHelper(const ONNX_NAMESPACE::TypeProto& input_type_proto,
|
||||
OpKernelContext* context, int output_index);
|
||||
#endif
|
||||
|
||||
} // namespace utils
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -1572,18 +1572,26 @@ common::Status InferenceSession::ValidateInputs(const std::vector<std::string>&
|
|||
auto expected_type = iter->second.ml_data_type;
|
||||
auto& input_ml_value = feeds.at(i);
|
||||
if (input_ml_value.IsTensor()) {
|
||||
if (!expected_type->IsTensorType() &&
|
||||
!utils::IsOptionalTensor(expected_type)) {
|
||||
if (!expected_type->IsTensorType()
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
&& !utils::IsOptionalTensor(expected_type)
|
||||
#endif
|
||||
) {
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input with name: ", feed_name,
|
||||
" is not expected to be of type tensor.");
|
||||
}
|
||||
|
||||
// check for type
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
auto expected_element_type = expected_type->IsTensorType()
|
||||
? expected_type
|
||||
->AsTensorType()
|
||||
->GetElementType()
|
||||
: utils::GetElementTypeFromOptionalTensor(expected_type);
|
||||
#else
|
||||
auto expected_element_type = expected_type->AsTensorType()->GetElementType();
|
||||
#endif
|
||||
|
||||
auto input_element_type = input_ml_value.Get<Tensor>().DataType();
|
||||
ORT_RETURN_IF_ERROR_SESSIONID_(CheckTypes(input_element_type, expected_element_type, "tensor"));
|
||||
|
||||
|
|
@ -1615,17 +1623,24 @@ common::Status InferenceSession::ValidateInputs(const std::vector<std::string>&
|
|||
#endif
|
||||
|
||||
} else if (input_ml_value.IsTensorSequence()) {
|
||||
if (!expected_type->IsTensorSequenceType() &&
|
||||
!utils::IsOptionalSeqTensor(expected_type)) {
|
||||
if (!expected_type->IsTensorSequenceType()
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
&& !utils::IsOptionalSeqTensor(expected_type)
|
||||
#endif
|
||||
) {
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input with name: ", feed_name,
|
||||
" is not expected to be of type tensor sequence.");
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
auto expected_element_type = expected_type->IsTensorSequenceType()
|
||||
? expected_type
|
||||
->AsSequenceTensorType()
|
||||
->GetElementType()
|
||||
: utils::GetElementTypeFromOptionalSeqTensor(expected_type);
|
||||
#else
|
||||
auto expected_element_type = expected_type->AsSequenceTensorType()->GetElementType();
|
||||
#endif
|
||||
|
||||
auto input_element_type = input_ml_value.Get<TensorSeq>().DataType();
|
||||
ORT_RETURN_IF_ERROR_SESSIONID_(CheckTypes(input_element_type, expected_element_type, "seq"));
|
||||
|
|
|
|||
|
|
@ -315,9 +315,11 @@ struct ProviderHostImpl : ProviderHost {
|
|||
int int64s__size(const ONNX_NAMESPACE::int64s* p) override { return p->size(); }
|
||||
const int64_t& int64s__Get(const ONNX_NAMESPACE::int64s* p, int index) override { return p->Get(index); }
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// TypeProto_Optional (wrapped)
|
||||
const ONNX_NAMESPACE::TypeProto& TypeProto_Optional__elem_type(const ONNX_NAMESPACE::TypeProto_Optional* p) override { return p->elem_type(); }
|
||||
ONNX_NAMESPACE::TypeProto* TypeProto_Optional__mutable_elem_type(ONNX_NAMESPACE::TypeProto_Optional* p) override { return p->mutable_elem_type(); }
|
||||
#endif
|
||||
|
||||
// TypeProto_Sequence (wrapped)
|
||||
const ONNX_NAMESPACE::TypeProto& TypeProto_Sequence__elem_type(const ONNX_NAMESPACE::TypeProto_Sequence* p) override { return p->elem_type(); }
|
||||
|
|
@ -356,8 +358,10 @@ struct ProviderHostImpl : ProviderHost {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
const ONNX_NAMESPACE::TypeProto_Optional& TypeProto__optional_type(const ONNX_NAMESPACE::TypeProto* p) override { return p->optional_type(); }
|
||||
ONNX_NAMESPACE::TypeProto_Optional* TypeProto__mutable_optional_type(ONNX_NAMESPACE::TypeProto* p) override { return p->mutable_optional_type(); }
|
||||
#endif
|
||||
|
||||
const ONNX_NAMESPACE::TypeProto_Sequence& TypeProto__sequence_type(const ONNX_NAMESPACE::TypeProto* p) override { return p->sequence_type(); }
|
||||
ONNX_NAMESPACE::TypeProto_Sequence* TypeProto__mutable_sequence_type(ONNX_NAMESPACE::TypeProto* p) override { return p->mutable_sequence_type(); }
|
||||
|
|
|
|||
|
|
@ -308,10 +308,12 @@ class OnnxTestCase : public ITestCase {
|
|||
bool is_input, size_t i,
|
||||
std::unordered_map<std::string, Ort::Value>& out) const;
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
void ConvertTestData(const ONNX_NAMESPACE::OptionalProto& test_data_pb,
|
||||
onnxruntime::test::HeapBuffer& b,
|
||||
bool is_input, size_t i,
|
||||
std::unordered_map<std::string, Ort::Value>& out) const;
|
||||
#endif
|
||||
|
||||
std::once_flag model_parsed_;
|
||||
std::once_flag config_parsed_;
|
||||
|
|
@ -445,6 +447,7 @@ static void LoadSequenceTensor(const PATH_STRING_TYPE& pb_file, ONNX_NAMESPACE::
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
template <typename PATH_STRING_TYPE>
|
||||
static void LoadOptional(const PATH_STRING_TYPE& pb_file,
|
||||
ONNX_NAMESPACE::OptionalProto& input_pb) {
|
||||
|
|
@ -459,6 +462,8 @@ static void LoadOptional(const PATH_STRING_TYPE& pb_file,
|
|||
ORT_THROW("parse file '", ToMBString(pb_file), "' failed");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void OnnxTestCase::LoadTestData(size_t id, onnxruntime::test::HeapBuffer& b,
|
||||
std::unordered_map<std::string, Ort::Value>& name_data_map,
|
||||
bool is_input) const {
|
||||
|
|
@ -528,11 +533,15 @@ void OnnxTestCase::LoadTestData(size_t id, onnxruntime::test::HeapBuffer& b,
|
|||
ONNX_NAMESPACE::SequenceProto test_pb;
|
||||
LoadSequenceTensor(test_data_pb_files[i], test_pb);
|
||||
ConvertTestData(test_pb, b, is_input, i, name_data_map);
|
||||
} else if (value_info_proto->type().has_optional_type()) {
|
||||
}
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
else if (value_info_proto->type().has_optional_type()) {
|
||||
ONNX_NAMESPACE::OptionalProto test_pb;
|
||||
LoadOptional(test_data_pb_files[i], test_pb);
|
||||
ConvertTestData(test_pb, b, is_input, i, name_data_map);
|
||||
} else {
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
ORT_THROW("Unsupported type for the ", is_input ? "input " : "output ", i, " in the test runner");
|
||||
}
|
||||
}
|
||||
|
|
@ -617,6 +626,7 @@ void OnnxTestCase::ConvertTestData(const ONNX_NAMESPACE::SequenceProto& test_dat
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
void OnnxTestCase::ConvertTestData(const ONNX_NAMESPACE::OptionalProto& test_data_pb,
|
||||
onnxruntime::test::HeapBuffer& b,
|
||||
bool is_input, size_t i,
|
||||
|
|
@ -673,6 +683,7 @@ void OnnxTestCase::ConvertTestData(const ONNX_NAMESPACE::OptionalProto& test_dat
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
OnnxTestCase::OnnxTestCase(const std::string& test_case_name, _In_ std::unique_ptr<TestModelInfo> model,
|
||||
double default_per_sample_tolerance, double default_relative_per_sample_tolerance)
|
||||
|
|
|
|||
|
|
@ -526,71 +526,82 @@ int real_main(int argc, char* argv[], Ort::Env& env) {
|
|||
};
|
||||
|
||||
std::set<BrokenTest> broken_tests = {
|
||||
{"BERT_Squad", "test data bug"},
|
||||
{"constantofshape_float_ones", "test data bug", {"onnx141", "onnx150"}},
|
||||
{"constantofshape_int_zeros", "test data bug", {"onnx141", "onnx150"}},
|
||||
{"convtranspose_autopad_same", "Implementation need to be adjusted for ONNX changes"},
|
||||
{"cast_STRING_to_FLOAT", "Linux CI has old ONNX python package with bad test data", {"onnx141"}},
|
||||
// Numpy float to string has unexpected rounding for some results given numpy default precision is meant to be 8.
|
||||
// "e.g. 0.296140194 -> '0.2961402' not '0.29614019'. ORT produces the latter with precision set to 8,
|
||||
// which doesn't match the expected output that was generated with numpy.
|
||||
{"cast_FLOAT_to_STRING", "Numpy float to string has unexpected rounding for some results."},
|
||||
{"tf_nasnet_large", "disable temporarily"},
|
||||
{"tf_nasnet_mobile", "disable temporarily"},
|
||||
{"tf_pnasnet_large", "disable temporarily"},
|
||||
{"shrink", "test case is wrong", {"onnx141"}},
|
||||
{"maxpool_with_argmax_2d_precomputed_strides", "ShapeInferenceError"},
|
||||
{"tf_inception_v2", "result mismatch"},
|
||||
{"tf_resnet_v1_50", "result mismatch when Conv BN Fusion is applied"},
|
||||
{"tf_resnet_v1_101", "result mismatch when Conv BN Fusion is applied"},
|
||||
{"tf_resnet_v1_152", "result mismatch when Conv BN Fusion is applied"},
|
||||
{"mxnet_arcface", "Model is an invalid ONNX model"},
|
||||
{"unique_not_sorted_without_axis", "Expected data for 'Y' is incorrect and in sorted order."},
|
||||
{"cumsum_1d_reverse_exclusive", "only failing linux GPU CI. Likely build error."},
|
||||
{"resize_downsample_scales_cubic_align_corners", "results mismatch with onnx tests"},
|
||||
{"resize_downsample_scales_linear_align_corners", "results mismatch with onnx tests"},
|
||||
{"resize_tf_crop_and_resize", "Bad onnx test output. Needs test fix."},
|
||||
{"resize_upsample_sizes_nearest_ceil_half_pixel", "Bad onnx test output. Needs test fix."},
|
||||
{"resize_upsample_sizes_nearest_floor_align_corners", "Bad onnx test output. Needs test fix."},
|
||||
{"resize_upsample_sizes_nearest_round_prefer_ceil_asymmetric", "Bad onnx test output. Needs test fix."},
|
||||
{"bitshift_right_uint16", "BitShift(11) uint16 support not enabled currently"},
|
||||
{"bitshift_left_uint16", "BitShift(11) uint16 support not enabled currently"},
|
||||
{"maxunpool_export_with_output_shape", "Invalid output in ONNX test. See https://github.com/onnx/onnx/issues/2398"},
|
||||
{"training_dropout", "result differs", {}}, // Temporary, subsequent PR will remove this.
|
||||
{"training_dropout_default", "result differs", {}}, // Temporary, subsequent PR will remove this.
|
||||
{"training_dropout_default_mask", "result differs", {}}, // Temporary, subsequent PR will remove this.
|
||||
{"training_dropout_mask", "result differs", {}}, // Temporary, subsequent PR will remove this.
|
||||
{"adagrad", "not a registered function/op", {}}, // Op not registered.
|
||||
{"adagrad_multiple", "not a registered function/op", {}}, // Op not registered.
|
||||
{"adam", "not a registered function/op", {}}, // Op not registered.
|
||||
{"adam_multiple", "not a registered function/op", {}}, // Op not registered.
|
||||
{"gradient_of_add", "not a registered function/op", {}}, // Op not registered.
|
||||
{"gradient_of_add_and_mul", "not a registered function/op", {}}, // Op not registered.
|
||||
{"momentum", "not a registered function/op", {}}, // Op not registered.
|
||||
{"momentum_multiple", "not a registered function/op", {}}, // Op not registered.
|
||||
{"nesterov_momentum", "not a registered function/op", {}}, // Op not registered.
|
||||
{"sequence_insert_at_back", "onnx currently not supporting loading segment", {}},
|
||||
{"sequence_insert_at_front", "onnx currently not supporting loading segment", {}},
|
||||
{"loop13_seq", "ORT api does not currently support creating empty sequences (needed for this test)", {}},
|
||||
{"cast_FLOAT_to_BFLOAT16", "onnx generate bfloat tensor as uint16 type", {}},
|
||||
{"cast_BFLOAT16_to_FLOAT", "onnx generate bfloat tensor as uint16 type", {}},
|
||||
{"castlike_FLOAT_to_BFLOAT16", "Depends on cast.", {}},
|
||||
{"castlike_BFLOAT16_to_FLOAT", "Depends on cast", {}},
|
||||
{"castlike_FLOAT_to_BFLOAT16_expanded", "Depends on cast.", {}},
|
||||
{"castlike_BFLOAT16_to_FLOAT_expanded", "Depends on cast", {}},
|
||||
{"castlike_FLOAT_to_STRING", "Numpy float to string has unexpected rounding for some results.", {}},
|
||||
{"castlike_FLOAT_to_STRING_expanded", "Numpy float to string has unexpected rounding for some results.", {}},
|
||||
{"bernoulli", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"bernoulli_double", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"bernoulli_double_expanded", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"bernoulli_seed", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"bernoulli_seed_expanded", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"bernoulli_expanded", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"test_roialign_aligned_true", "Opset 16 not supported yet."},
|
||||
{"test_roialign_aligned_false", "Opset 16 not supported yet."},
|
||||
{"test_scatternd_add", "Opset 16 not supported yet."},
|
||||
{"test_scatternd_multiply", "Opset 16 not supported yet."},
|
||||
{"test_scatter_elements_with_duplicate_indices", "Opset 16 not supported yet."},
|
||||
{"BERT_Squad", "test data bug"},
|
||||
{"constantofshape_float_ones", "test data bug", {"onnx141", "onnx150"}},
|
||||
{"constantofshape_int_zeros", "test data bug", {"onnx141", "onnx150"}},
|
||||
{"convtranspose_autopad_same", "Implementation need to be adjusted for ONNX changes"},
|
||||
{"cast_STRING_to_FLOAT", "Linux CI has old ONNX python package with bad test data", {"onnx141"}},
|
||||
// Numpy float to string has unexpected rounding for some results given numpy default precision is meant to be 8.
|
||||
// "e.g. 0.296140194 -> '0.2961402' not '0.29614019'. ORT produces the latter with precision set to 8,
|
||||
// which doesn't match the expected output that was generated with numpy.
|
||||
{"cast_FLOAT_to_STRING", "Numpy float to string has unexpected rounding for some results."},
|
||||
{"tf_nasnet_large", "disable temporarily"},
|
||||
{"tf_nasnet_mobile", "disable temporarily"},
|
||||
{"tf_pnasnet_large", "disable temporarily"},
|
||||
{"shrink", "test case is wrong", {"onnx141"}},
|
||||
{"maxpool_with_argmax_2d_precomputed_strides", "ShapeInferenceError"},
|
||||
{"tf_inception_v2", "result mismatch"},
|
||||
{"tf_resnet_v1_50", "result mismatch when Conv BN Fusion is applied"},
|
||||
{"tf_resnet_v1_101", "result mismatch when Conv BN Fusion is applied"},
|
||||
{"tf_resnet_v1_152", "result mismatch when Conv BN Fusion is applied"},
|
||||
{"mxnet_arcface", "Model is an invalid ONNX model"},
|
||||
{"unique_not_sorted_without_axis", "Expected data for 'Y' is incorrect and in sorted order."},
|
||||
{"cumsum_1d_reverse_exclusive", "only failing linux GPU CI. Likely build error."},
|
||||
{"resize_downsample_scales_cubic_align_corners", "results mismatch with onnx tests"},
|
||||
{"resize_downsample_scales_linear_align_corners", "results mismatch with onnx tests"},
|
||||
{"resize_tf_crop_and_resize", "Bad onnx test output. Needs test fix."},
|
||||
{"resize_upsample_sizes_nearest_ceil_half_pixel", "Bad onnx test output. Needs test fix."},
|
||||
{"resize_upsample_sizes_nearest_floor_align_corners", "Bad onnx test output. Needs test fix."},
|
||||
{"resize_upsample_sizes_nearest_round_prefer_ceil_asymmetric", "Bad onnx test output. Needs test fix."},
|
||||
{"bitshift_right_uint16", "BitShift(11) uint16 support not enabled currently"},
|
||||
{"bitshift_left_uint16", "BitShift(11) uint16 support not enabled currently"},
|
||||
{"maxunpool_export_with_output_shape", "Invalid output in ONNX test. See https://github.com/onnx/onnx/issues/2398"},
|
||||
{"training_dropout", "result differs", {}}, // Temporary, subsequent PR will remove this.
|
||||
{"training_dropout_default", "result differs", {}}, // Temporary, subsequent PR will remove this.
|
||||
{"training_dropout_default_mask", "result differs", {}}, // Temporary, subsequent PR will remove this.
|
||||
{"training_dropout_mask", "result differs", {}}, // Temporary, subsequent PR will remove this.
|
||||
{"adagrad", "not a registered function/op", {}}, // Op not registered.
|
||||
{"adagrad_multiple", "not a registered function/op", {}}, // Op not registered.
|
||||
{"adam", "not a registered function/op", {}}, // Op not registered.
|
||||
{"adam_multiple", "not a registered function/op", {}}, // Op not registered.
|
||||
{"gradient_of_add", "not a registered function/op", {}}, // Op not registered.
|
||||
{"gradient_of_add_and_mul", "not a registered function/op", {}}, // Op not registered.
|
||||
{"momentum", "not a registered function/op", {}}, // Op not registered.
|
||||
{"momentum_multiple", "not a registered function/op", {}}, // Op not registered.
|
||||
{"nesterov_momentum", "not a registered function/op", {}}, // Op not registered.
|
||||
{"sequence_insert_at_back", "onnx currently not supporting loading segment", {}},
|
||||
{"sequence_insert_at_front", "onnx currently not supporting loading segment", {}},
|
||||
{"loop13_seq", "ORT api does not currently support creating empty sequences (needed for this test)", {}},
|
||||
{"cast_FLOAT_to_BFLOAT16", "onnx generate bfloat tensor as uint16 type", {}},
|
||||
{"cast_BFLOAT16_to_FLOAT", "onnx generate bfloat tensor as uint16 type", {}},
|
||||
{"castlike_FLOAT_to_BFLOAT16", "Depends on cast.", {}},
|
||||
{"castlike_BFLOAT16_to_FLOAT", "Depends on cast", {}},
|
||||
{"castlike_FLOAT_to_BFLOAT16_expanded", "Depends on cast.", {}},
|
||||
{"castlike_BFLOAT16_to_FLOAT_expanded", "Depends on cast", {}},
|
||||
{"castlike_FLOAT_to_STRING", "Numpy float to string has unexpected rounding for some results.", {}},
|
||||
{"castlike_FLOAT_to_STRING_expanded", "Numpy float to string has unexpected rounding for some results.", {}},
|
||||
{"bernoulli", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"bernoulli_double", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"bernoulli_double_expanded", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"bernoulli_seed", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"bernoulli_seed_expanded", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"bernoulli_expanded", "By design. Test data is for informational purpose because the generator is non deterministic."},
|
||||
{"test_roialign_aligned_true", "Opset 16 not supported yet."},
|
||||
{"test_roialign_aligned_false", "Opset 16 not supported yet."},
|
||||
{"test_scatternd_add", "Opset 16 not supported yet."},
|
||||
{"test_scatternd_multiply", "Opset 16 not supported yet."},
|
||||
{"test_scatter_elements_with_duplicate_indices", "Opset 16 not supported yet."},
|
||||
|
||||
#if defined(DISABLE_OPTIONAL_TYPE)
|
||||
{"test_optional_get_element", "Optional type not supported in this build flavor."},
|
||||
{"test_optional_get_element_sequence", "Optional type not supported in this build flavor."},
|
||||
{"test_optional_has_element", "Optional type not supported in this build flavor."},
|
||||
{"test_optional_has_element_empty", "Optional type not supported in this build flavor."},
|
||||
{"test_if_opt", "Optional type not supported in this build flavor."},
|
||||
{"test_loop16_seq_none", "Optional type not supported in this build flavor."},
|
||||
{"test_identity_opt", "Optional type not supported in this build flavor."},
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#ifdef DISABLE_ML_OPS
|
||||
|
|
|
|||
|
|
@ -472,6 +472,7 @@ TEST(If, TestIfWithSequencesAsOutput) {
|
|||
test.Run();
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
// This is to test an "If" node with just an "Identity" node in the "then" and "else" conditional branches
|
||||
class IfOpTesterWithOptionalTypeAsOutput : public OpTester {
|
||||
public:
|
||||
|
|
@ -588,5 +589,7 @@ TEST(If, TestIfWithOptionalTypeTensorAsOutput) {
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace test
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -1162,6 +1162,8 @@ TEST(Loop, SequenceAsLoopCarriedDependency) {
|
|||
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|
||||
TEST(Loop, OptionalTypeAsLoopCarriedDependency) {
|
||||
auto create_subgraph = [](bool is_optional_tensor_type) {
|
||||
std::unordered_map<std::string, int> domain_to_version;
|
||||
|
|
@ -1334,5 +1336,7 @@ TEST(Loop, OptionalTypeAsLoopCarriedDependency) {
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace test
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/providers/provider_test_utils.h"
|
||||
|
||||
|
|
@ -244,3 +246,5 @@ TEST(OptionalOpTest, OptionalOpsValidateOrtValueReUseForOptionalTensorSequence)
|
|||
}
|
||||
} // namespace test
|
||||
} // namespace onnxruntime
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ TEST(Identity, SequenceType) {
|
|||
test.Run();
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|
||||
TEST(Identity, OptionalTensorType_NonNone) {
|
||||
OpTester test("Identity", 16, kOnnxDomain);
|
||||
// Since this test is being written at a time when only opset 15 has been released, we set
|
||||
|
|
@ -81,5 +83,8 @@ TEST(Identity, OptionalTensorSequenceType_None) {
|
|||
test.AddOptionalTypeSeqOutput<float>("Y", nullptr); // None
|
||||
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: opset 16 is not supported yet
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace test
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -174,6 +174,10 @@ TEST(KernelDefHashTest, ExpectedCpuKernelDefHashes) {
|
|||
#if defined(ENABLE_TRAINING_OPS)
|
||||
AppendKernelDefHashesFromFile(ORT_TSTR("testdata/kernel_def_hashes/training_ops.cpu.json"), result);
|
||||
#endif // ENABLE_TRAINING_OPS
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
AppendKernelDefHashesFromFile(ORT_TSTR("testdata/kernel_def_hashes/onnx.optional_type_ops.cpu.json"), result);
|
||||
#endif // !DISABLE_OPTIONAL_TYPE
|
||||
|
||||
// TODO also handle kernels enabled by these symbols: BUILD_MS_EXPERIMENTAL_OPS
|
||||
std::sort(result.begin(), result.end());
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -225,6 +225,8 @@ struct SequenceTensorType {
|
|||
template <typename ElemType>
|
||||
const SequenceTensorTypeProto<ElemType> SequenceTensorType<ElemType>::s_sequence_tensor_type_proto;
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|
||||
template <typename ElemType>
|
||||
struct OptionalTypeProto {
|
||||
OptionalTypeProto(const ONNX_NAMESPACE::TypeProto& type_proto) {
|
||||
|
|
@ -233,6 +235,8 @@ struct OptionalTypeProto {
|
|||
ONNX_NAMESPACE::TypeProto proto;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct CheckParams {
|
||||
bool sort_output_ = false;
|
||||
optional<float> absolute_error_;
|
||||
|
|
@ -442,6 +446,8 @@ class OpTester {
|
|||
AddSeqData<T>(output_data_, name, &seq_tensors);
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
|
||||
template <typename T>
|
||||
void AddOptionalTypeTensorInput(const char* name, const std::vector<int64_t>& dims,
|
||||
const std::initializer_list<T>* values = nullptr,
|
||||
|
|
@ -471,6 +477,8 @@ class OpTester {
|
|||
AddSeqData<T>(output_data_, name, seq_tensors, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename TKey, typename TVal>
|
||||
void AddInput(const char* name, const std::map<TKey, TVal>& val) {
|
||||
std::unique_ptr<std::map<TKey, TVal>> ptr = std::make_unique<std::map<TKey, TVal>>(val);
|
||||
|
|
@ -826,6 +834,12 @@ class OpTester {
|
|||
int64_t values_count, bool is_initializer = false, bool sort_output = false,
|
||||
const std::vector<std::string>* dim_params = nullptr,
|
||||
float rel_error = 0.0f, float abs_error = 0.0f, bool is_optional_type_tensor = false) {
|
||||
#if defined(DISABLE_OPTIONAL_TYPE)
|
||||
if (is_optional_type_tensor) {
|
||||
ORT_THROW("Optional type is not supported in this build");
|
||||
}
|
||||
#endif
|
||||
|
||||
ORT_TRY {
|
||||
TensorShape shape{dims};
|
||||
|
||||
|
|
@ -861,8 +875,13 @@ class OpTester {
|
|||
|
||||
std::vector<int64_t> dims_for_proto = GetDimsForProto(dims);
|
||||
TTypeProto<T> tensor_type_proto(add_shape_to_tensor_data_ ? &dims_for_proto : nullptr);
|
||||
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
OptionalTypeProto<T> optional_type_proto(tensor_type_proto.proto);
|
||||
auto node_arg = NodeArg(name, !is_optional_type_tensor ? &tensor_type_proto.proto : &optional_type_proto.proto);
|
||||
#else
|
||||
auto node_arg = NodeArg(name, &tensor_type_proto.proto);
|
||||
#endif
|
||||
|
||||
AddShapeToTensorData(node_arg, dims, dim_params);
|
||||
|
||||
|
|
@ -897,6 +916,12 @@ class OpTester {
|
|||
void AddSeqData(std::vector<Data>& data, const char* name,
|
||||
const SeqTensors<T>* seq_tensors,
|
||||
bool is_optional_sequence_tensor_type = false) {
|
||||
#if defined(DISABLE_OPTIONAL_TYPE)
|
||||
if (is_optional_sequence_tensor_type) {
|
||||
ORT_THROW("Optional type is not supported in this build");
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<TensorSeq> ptr;
|
||||
|
||||
if (seq_tensors) {
|
||||
|
|
@ -934,14 +959,16 @@ class OpTester {
|
|||
value.Init(ptr ? ptr.release() : nullptr, mltype, mltype->GetDeleteFunc());
|
||||
|
||||
SequenceTensorTypeProto<T> sequence_tensor_proto;
|
||||
#if !defined(DISABLE_OPTIONAL_TYPE)
|
||||
OptionalTypeProto<T> optional_type_proto(sequence_tensor_proto.proto);
|
||||
auto node_arg = NodeArg(name, !is_optional_sequence_tensor_type
|
||||
? &sequence_tensor_proto.proto
|
||||
: &optional_type_proto.proto);
|
||||
#else
|
||||
auto node_arg = NodeArg(name, &sequence_tensor_proto.proto);
|
||||
#endif
|
||||
|
||||
data.push_back(
|
||||
Data(NodeArg(name, !is_optional_sequence_tensor_type
|
||||
? &sequence_tensor_proto.proto
|
||||
: &optional_type_proto.proto),
|
||||
std::move(value),
|
||||
optional<float>(), optional<float>()));
|
||||
data.push_back(Data(std::move(node_arg), std::move(value), optional<float>(), optional<float>()));
|
||||
}
|
||||
|
||||
std::vector<int64_t> GetDimsForProto(gsl::span<const int64_t> dims);
|
||||
|
|
|
|||
|
|
@ -1475,18 +1475,6 @@
|
|||
"OneHot ai.onnx CPUExecutionProvider",
|
||||
15162687909384154912
|
||||
],
|
||||
[
|
||||
"Optional ai.onnx CPUExecutionProvider",
|
||||
4007199385789893408
|
||||
],
|
||||
[
|
||||
"OptionalGetElement ai.onnx CPUExecutionProvider",
|
||||
8727767224223660008
|
||||
],
|
||||
[
|
||||
"OptionalHasElement ai.onnx CPUExecutionProvider",
|
||||
103583056104706000
|
||||
],
|
||||
[
|
||||
"Or ai.onnx CPUExecutionProvider",
|
||||
18295541712828245416
|
||||
|
|
|
|||
14
onnxruntime/test/testdata/kernel_def_hashes/onnx.optional_type_ops.cpu.json
vendored
Normal file
14
onnxruntime/test/testdata/kernel_def_hashes/onnx.optional_type_ops.cpu.json
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[
|
||||
[
|
||||
"Optional ai.onnx CPUExecutionProvider",
|
||||
4007199385789893408
|
||||
],
|
||||
[
|
||||
"OptionalGetElement ai.onnx CPUExecutionProvider",
|
||||
8727767224223660008
|
||||
],
|
||||
[
|
||||
"OptionalHasElement ai.onnx CPUExecutionProvider",
|
||||
103583056104706000
|
||||
]
|
||||
]
|
||||
|
|
@ -72,10 +72,13 @@
|
|||
// Uncomment here once the ONNX backend test runner is able to handle
|
||||
// optional type test data.
|
||||
// https://github.com/onnx/onnx/issues/3608
|
||||
// TODO: Once ONNX #3608 is solved and these tests are removed from exclusion,
|
||||
// we need to figure out a way to keep these tests in the exclusion list for
|
||||
// builds that have disabled support for the optional type.
|
||||
"^test_optional_*",
|
||||
"^test_if_opt",
|
||||
"^test_loop16_seq_none",
|
||||
"^test_identity",
|
||||
"^test_identity_opt",
|
||||
// Following tests are for opset 16 ops and are not yet implemented in ORT
|
||||
"^test_roialign_aligned_*",
|
||||
"^test_scatternd_*",
|
||||
|
|
|
|||
Loading…
Reference in a new issue