From e00ad83f2b3181eb6e3901fcf78a0d00c0306a04 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Sat, 22 Aug 2020 07:14:53 +1000 Subject: [PATCH] Initial changes to disable code in a minimal build (#4872) * Initial set of changes to start disabling code in the minimal build. Breaking changes into multiple PRs so they're more easily reviewed. Focus on InferenceSession, Model and Graph here. SessionState will be next. Needs to be integrated with de/serialization code before being testable so changes are all off by default. Changes are limited to - #ifdef'ing out code - moving some things around so there are fewer #ifdef statements - moving definition of some one-line methods into the header so we don't need to #ifdef out in a .cc as well - exclude some things in the cmake setup * Update session state and a few other places. The core code builds if ORT_MINIMAL_BUILD is specified. --- cmake/CMakeLists.txt | 11 + cmake/onnxruntime_framework.cmake | 9 + cmake/onnxruntime_graph.cmake | 35 ++- cmake/onnxruntime_optimizer.cmake | 14 +- cmake/onnxruntime_unittests.cmake | 86 +++--- include/onnxruntime/core/graph/graph.h | 216 +++++++++------ include/onnxruntime/core/graph/node_arg.h | 5 + .../core/framework/sequential_executor.cc | 11 +- onnxruntime/core/framework/session_state.cc | 13 +- onnxruntime/core/framework/session_state.h | 8 + onnxruntime/core/graph/graph.cc | 253 ++++++++---------- onnxruntime/core/graph/model.cc | 10 + onnxruntime/core/graph/model.h | 41 +++ .../core/optimizer/graph_transformer.cc | 8 +- onnxruntime/core/session/environment.cc | 2 + onnxruntime/core/session/inference_session.cc | 55 +++- onnxruntime/core/session/inference_session.h | 100 ++++--- onnxruntime/core/session/onnxruntime_c_api.cc | 39 ++- .../test/common/tensor_op_test_utils.h | 1 - onnxruntime/test/common/utf8_util_test.cc | 1 - .../test/contrib_ops/tensor_op_test.cc | 3 +- .../providers/cpu/tensor/tensor_op_test.cc | 10 +- 22 files changed, 588 insertions(+), 343 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index c091064b8c..9bcf9943dc 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -108,6 +108,9 @@ option(onnxruntime_USE_TELEMETRY "Build with Telemetry" OFF) #It's default OFF because it's experimental now. option(onnxruntime_PREFER_SYSTEM_LIB "Experimental: Build with the preinstalled libraries in your system" OFF) +option(onnxruntime_MINIMAL_BUILD "Exclude as much as possible from the build. Support ORT format models. No support for ONNX format models." OFF) +option(onnxruntime_REDUCED_OPS_BUILD "Reduced set of kernels are registered in build via modification of the kernel registration source files." OFF) + # training options option(onnxruntime_ENABLE_NVTX_PROFILE "Enable NVTX profile." OFF) option(onnxruntime_ENABLE_TRAINING "Enable training functionality." OFF) @@ -203,6 +206,14 @@ if(onnxruntime_ENABLE_LTO) endif() endif() +# ORT build with as much excluded as possible. Supports ORT flatbuffers models only. +# Will expose option in build.py when all pieces are available +if(onnxruntime_MINIMAL_BUILD) + add_compile_definitions(ORT_MINIMAL_BUILD) + set(onnxruntime_REDUCED_OPS_BUILD ON) # TODO Defaulting to ON. TBD if we should always do that. + set(onnxruntime_DISABLE_RTTI ON) +endif() + if(onnxruntime_DISABLE_RTTI) add_compile_definitions(ORT_NO_RTTI GOOGLE_PROTOBUF_NO_RTTI) if(MSVC) diff --git a/cmake/onnxruntime_framework.cmake b/cmake/onnxruntime_framework.cmake index eebad5791a..a3ae8f4fdd 100644 --- a/cmake/onnxruntime_framework.cmake +++ b/cmake/onnxruntime_framework.cmake @@ -7,6 +7,15 @@ file(GLOB_RECURSE onnxruntime_framework_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/core/framework/*.cc" ) +if (onnxruntime_MINIMAL_BUILD) + file(GLOB onnxruntime_framework_src_exclude + "${ONNXRUNTIME_ROOT}/core/framework/provider_bridge_ort.cc" + "${ONNXRUNTIME_ROOT}/core/framework/graph_partitioner.*" + ) + + list(REMOVE_ITEM onnxruntime_framework_srcs ${onnxruntime_framework_src_exclude}) +endif() + source_group(TREE ${REPO_ROOT} FILES ${onnxruntime_framework_srcs}) add_library(onnxruntime_framework ${onnxruntime_framework_srcs}) diff --git a/cmake/onnxruntime_graph.cmake b/cmake/onnxruntime_graph.cmake index 3aa9ed1fa3..e134db0e86 100644 --- a/cmake/onnxruntime_graph.cmake +++ b/cmake/onnxruntime_graph.cmake @@ -7,30 +7,51 @@ file(GLOB_RECURSE onnxruntime_graph_src CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/core/graph/*.cc" ) +# create empty list for any excludes +set(onnxruntime_graph_src_exclude_patterns) + +if (onnxruntime_MINIMAL_BUILD) + # remove schema registration of contrib ops + list(APPEND onnxruntime_graph_src_exclude_patterns + "${ONNXRUNTIME_ROOT}/core/graph/contrib_ops/*defs.h" + "${ONNXRUNTIME_ROOT}/core/graph/contrib_ops/*defs.cc" + ) + + # no Function support initially + list(APPEND onnxruntime_graph_src_exclude_patterns + "${ONNXRUNTIME_ROOT}/core/graph/function*" + ) + + # no optimizer support initially + list(APPEND onnxruntime_graph_src_exclude_patterns + "${ONNXRUNTIME_ROOT}/core/graph/graph_utils.*" + ) +endif() + if (onnxruntime_DISABLE_CONTRIB_OPS) - list(REMOVE_ITEM onnxruntime_graph_src + list(APPEND onnxruntime_graph_src_exclude_patterns "${ONNXRUNTIME_ROOT}/core/graph/contrib_ops/*.h" "${ONNXRUNTIME_ROOT}/core/graph/contrib_ops/*.cc" ) endif() if(NOT onnxruntime_USE_FEATURIZERS) - file(GLOB_RECURSE featurizers_to_remove_graph_src + list(APPEND onnxruntime_graph_src_exclude_patterns "${ONNXRUNTIME_ROOT}/core/graph/featurizers_ops/*.h" "${ONNXRUNTIME_ROOT}/core/graph/featurizers_ops/*.cc" - ) - foreach(I in ${featurizers_to_remove_graph_src}) - list(REMOVE_ITEM onnxruntime_graph_src ${I}) - endforeach() + ) endif() if(NOT onnxruntime_USE_DML) - list(REMOVE_ITEM onnxruntime_graph_src + list(APPEND onnxruntime_graph_src_exclude_patterns "${ONNXRUNTIME_ROOT}/core/graph/dml_ops/*.h" "${ONNXRUNTIME_ROOT}/core/graph/dml_ops/*.cc" ) endif() +file(GLOB onnxruntime_graph_src_exclude ${onnxruntime_graph_src_exclude_patterns}) +list(REMOVE_ITEM onnxruntime_graph_src ${onnxruntime_graph_src_exclude}) + file(GLOB_RECURSE onnxruntime_ir_defs_src CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/core/defs/*.cc" ) diff --git a/cmake/onnxruntime_optimizer.cmake b/cmake/onnxruntime_optimizer.cmake index 6d83f758ff..309b3b554c 100644 --- a/cmake/onnxruntime_optimizer.cmake +++ b/cmake/onnxruntime_optimizer.cmake @@ -1,11 +1,20 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -file(GLOB onnxruntime_optimizer_srcs CONFIGURE_DEPENDS +if (onnxruntime_MINIMAL_BUILD) + # we include a couple of files so a library is produced and we minimize other changes to the build setup. + # as the transformer base class will be unused it will be excluded from the final binary size + file(GLOB onnxruntime_optimizer_srcs CONFIGURE_DEPENDS + "${ONNXRUNTIME_INCLUDE_DIR}/core/optimizer/graph_transformer.h" + "${ONNXRUNTIME_ROOT}/core/optimizer/graph_transformer.cc" + ) +else() + file(GLOB onnxruntime_optimizer_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_INCLUDE_DIR}/core/optimizer/*.h" "${ONNXRUNTIME_ROOT}/core/optimizer/*.h" "${ONNXRUNTIME_ROOT}/core/optimizer/*.cc" - ) + ) +endif() if (onnxruntime_ENABLE_TRAINING) file(GLOB orttraining_optimizer_srcs CONFIGURE_DEPENDS @@ -18,6 +27,7 @@ endif() source_group(TREE ${REPO_ROOT} FILES ${onnxruntime_optimizer_srcs}) add_library(onnxruntime_optimizer ${onnxruntime_optimizer_srcs}) + install(DIRECTORY ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/optimizer DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/core) onnxruntime_add_include_to_target(onnxruntime_optimizer onnxruntime_common onnxruntime_framework onnx onnx_proto protobuf::libprotobuf) if (MSVC AND NOT CMAKE_SIZEOF_VOID_P EQUAL 8) diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index 8726558543..4271098c0b 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -102,21 +102,25 @@ file(GLOB onnxruntime_test_common_src CONFIGURE_DEPENDS "${TEST_SRC_DIR}/common/logging/*.h" ) -file(GLOB onnxruntime_test_ir_src CONFIGURE_DEPENDS - "${TEST_SRC_DIR}/ir/*.cc" - "${TEST_SRC_DIR}/ir/*.h" - ) +if(NOT onnxruntime_MINIMAL_BUILD) + file(GLOB onnxruntime_test_ir_src CONFIGURE_DEPENDS + "${TEST_SRC_DIR}/ir/*.cc" + "${TEST_SRC_DIR}/ir/*.h" + ) -file(GLOB onnxruntime_test_optimizer_src CONFIGURE_DEPENDS - "${TEST_SRC_DIR}/optimizer/*.cc" - "${TEST_SRC_DIR}/optimizer/*.h" - ) + file(GLOB onnxruntime_test_optimizer_src CONFIGURE_DEPENDS + "${TEST_SRC_DIR}/optimizer/*.cc" + "${TEST_SRC_DIR}/optimizer/*.h" + ) -set(onnxruntime_test_framework_src_patterns - "${TEST_SRC_DIR}/framework/*.cc" - "${TEST_SRC_DIR}/framework/*.h" - "${TEST_SRC_DIR}/platform/*.cc" - ) + set(onnxruntime_test_framework_src_patterns + "${TEST_SRC_DIR}/framework/*.cc" + "${TEST_SRC_DIR}/framework/*.h" + "${TEST_SRC_DIR}/platform/*.cc" + ) +else() + # TODO: Add tests that can be used in a minimal build +endif() file(GLOB onnxruntime_test_training_src "${ORTTRAINING_SOURCE_DIR}/test/model/*.cc" @@ -137,32 +141,44 @@ if(onnxruntime_USE_CUDA) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/framework/cuda/*) endif() -set(onnxruntime_test_providers_src_patterns - "${TEST_SRC_DIR}/providers/*.h" - "${TEST_SRC_DIR}/providers/*.cc" - "${TEST_SRC_DIR}/opaque_api/test_opaque_api.cc" - "${TEST_SRC_DIR}/framework/TestAllocatorManager.cc" - "${TEST_SRC_DIR}/framework/TestAllocatorManager.h" - "${TEST_SRC_DIR}/framework/test_utils.cc" - "${TEST_SRC_DIR}/framework/test_utils.h" +if(NOT onnxruntime_MINIMAL_BUILD) + set(onnxruntime_test_providers_src_patterns + "${TEST_SRC_DIR}/providers/*.h" + "${TEST_SRC_DIR}/providers/*.cc" + "${TEST_SRC_DIR}/opaque_api/test_opaque_api.cc" + "${TEST_SRC_DIR}/framework/TestAllocatorManager.cc" + "${TEST_SRC_DIR}/framework/TestAllocatorManager.h" + "${TEST_SRC_DIR}/framework/test_utils.cc" + "${TEST_SRC_DIR}/framework/test_utils.h" + ) + + if(NOT onnxruntime_DISABLE_CONTRIB_OPS) + list(APPEND onnxruntime_test_providers_src_patterns + "${TEST_SRC_DIR}/contrib_ops/*.h" + "${TEST_SRC_DIR}/contrib_ops/*.cc") + endif() + + if(onnxruntime_USE_FEATURIZERS) + list(APPEND onnxruntime_test_providers_src_patterns + "${TEST_SRC_DIR}/featurizers_ops/*.h" + "${TEST_SRC_DIR}/featurizers_ops/*.cc") + endif() + +else() + set(onnxruntime_test_providers_src_patterns + "${TEST_SRC_DIR}/framework/test_utils.cc" + "${TEST_SRC_DIR}/framework/test_utils.h" + # TODO: Add anything that is needed for testing a minimal build ) -if(NOT onnxruntime_DISABLE_CONTRIB_OPS) - list(APPEND onnxruntime_test_providers_src_patterns - "${TEST_SRC_DIR}/contrib_ops/*.h" - "${TEST_SRC_DIR}/contrib_ops/*.cc") endif() -if(onnxruntime_USE_FEATURIZERS) - list(APPEND onnxruntime_test_providers_src_patterns - "${TEST_SRC_DIR}/featurizers_ops/*.h" - "${TEST_SRC_DIR}/featurizers_ops/*.cc") -endif() +file(GLOB onnxruntime_test_providers_src CONFIGURE_DEPENDS ${onnxruntime_test_providers_src_patterns}) -file(GLOB onnxruntime_test_providers_src CONFIGURE_DEPENDS - ${onnxruntime_test_providers_src_patterns}) -file(GLOB_RECURSE onnxruntime_test_providers_cpu_src CONFIGURE_DEPENDS - "${TEST_SRC_DIR}/providers/cpu/*" - ) +if(NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_REDUCED_OPS_BUILD) + file(GLOB_RECURSE onnxruntime_test_providers_cpu_src CONFIGURE_DEPENDS + "${TEST_SRC_DIR}/providers/cpu/*" + ) +endif() if(onnxruntime_DISABLE_ML_OPS) list(FILTER onnxruntime_test_providers_cpu_src EXCLUDE REGEX ".*/ml/.*") diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index fa2d66761a..ced837e7e7 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -66,15 +66,15 @@ class Node { explicit EdgeEnd(const Node& node) noexcept; /** Gets the Node that this EdgeEnd refers to. */ - const Node& GetNode() const noexcept; + const Node& GetNode() const noexcept { return *node_; } /** Gets the source arg index. @returns the source arg index of <*this> edge.*/ - int GetSrcArgIndex() const; + int GetSrcArgIndex() const { return src_arg_index_; } /** Gets the destination arg index. @returns the destination arg index of <*this> edge.*/ - int GetDstArgIndex() const; + int GetDstArgIndex() const { return dst_arg_index_; } private: const Node* node_; @@ -83,20 +83,22 @@ class Node { }; /** Gets the Node's NodeIndex. */ - NodeIndex Index() const noexcept; + NodeIndex Index() const noexcept { return index_; } /** Gets the Node's name. */ - const std::string& Name() const noexcept; + const std::string& Name() const noexcept { return name_; } /** Gets the Node's operator type. */ - const std::string& OpType() const noexcept; + const std::string& OpType() const noexcept { return op_type_; } /** Gets the domain of the OperatorSet that specifies the operator returned by #OpType. */ - const std::string& Domain() const noexcept; + const std::string& Domain() const noexcept { return domain_; } - /** Gets the Node's OpSchema. - @remarks The graph containing this node must be resolved, otherwise nullptr will be returned. */ - const ONNX_NAMESPACE::OpSchema* Op() const noexcept; + /** Gets the node description. */ + const std::string& Description() const noexcept { return description_; } + + /** Gets the Node's Node::Type. */ + Node::Type NodeType() const noexcept { return node_type_; } /** Gets the opset version that the Node's operator was first defined in. @returns Opset version. If -1 the Node's operator has not been set. @@ -104,8 +106,10 @@ class Node { */ int SinceVersion() const noexcept { return since_version_; } - /** Gets the Node's Node::Type. */ - Node::Type NodeType() const noexcept; +#if !defined(ORT_MINIMAL_BUILD) + /** Gets the Node's OpSchema. + @remarks The graph containing this node must be resolved, otherwise nullptr will be returned. */ + const ONNX_NAMESPACE::OpSchema* Op() const noexcept { return op_; } /** Gets the function body if applicable otherwise nullptr @@ -122,10 +126,8 @@ class Node { const Function* GetFunctionBody(bool try_init_func_body = true); /** Gets the function body if applicable otherwise nullptr. */ - const Function* GetFunctionBody() const noexcept; - - /** Gets the node description. */ - const std::string& Description() const noexcept; + const Function* GetFunctionBody() const noexcept { return func_body_; } +#endif /** Helper to iterate through the container returned by #InputDefs() or #OutputDefs() and call the provided function. @@ -146,6 +148,29 @@ class Node { return common::Status::OK(); } + /** Gets the count of arguments for each of the Node's explicit inputs. */ + const std::vector& InputArgCount() const noexcept { return definitions_.input_arg_count; } + + /** Gets the Node's input definitions. + @remarks requires ConstPointerContainer wrapper to apply const to the NodeArg pointers so access is read-only. */ + ConstPointerContainer> InputDefs() const noexcept { + return ConstPointerContainer>(definitions_.input_defs); + } + + /** Gets the implicit inputs to this Node. + If this Node contains a subgraph, these are the NodeArg's that are implicitly consumed by Nodes within that + subgraph. e.g. If and Loop operators.*/ + ConstPointerContainer> ImplicitInputDefs() const noexcept { + return ConstPointerContainer>(definitions_.implicit_input_defs); + } + + /** Gets the Node's output definitions. + @remarks requires ConstPointerContainer wrapper to apply const to the NodeArg pointers so access is read-only. */ + ConstPointerContainer> OutputDefs() const noexcept { + return ConstPointerContainer>(definitions_.output_defs); + } + +#if !defined(ORT_MINIMAL_BUILD) /** Helper to iterate through the container returned by #MutableInputDefs() or #MutableOutputDefs() and call the provided function. @param node_args Collection of NodeArgs returned by #MutableInputDefs() or #MutableOutputDefs() @@ -164,48 +189,26 @@ class Node { } return common::Status::OK(); } - - /** Gets the count of arguments for each of the Node's explicit inputs. */ - const std::vector& InputArgCount() const noexcept { return definitions_.input_arg_count; } - /** Gets a modifiable count of arguments for each of the Node's explicit inputs. @todo This should be removed in favor of a method that updates the input args and the count. Currently these operations are separate which is not a good setup. */ std::vector& MutableInputArgsCount() { return definitions_.input_arg_count; } - /** Gets the Node's input definitions. - @remarks requires ConstPointerContainer wrapper to apply const to the NodeArg pointers so access is read-only. */ - ConstPointerContainer> InputDefs() const noexcept { - return ConstPointerContainer>(definitions_.input_defs); - } - /** Gets a modifiable collection of the Node's input definitions. */ std::vector& MutableInputDefs() noexcept { return definitions_.input_defs; } - /** Gets the implicit inputs to this Node. - If this Node contains a subgraph, these are the NodeArg's that are implicitly consumed by Nodes within that - subgraph. e.g. If and Loop operators.*/ - ConstPointerContainer> ImplicitInputDefs() const noexcept { - return ConstPointerContainer>(definitions_.implicit_input_defs); - } - /** Gets a modifiable collection of the Node's implicit input definitions. */ std::vector& MutableImplicitInputDefs() noexcept { return definitions_.implicit_input_defs; } - /** Gets the Node's output definitions. - @remarks requires ConstPointerContainer wrapper to apply const to the NodeArg pointers so access is read-only. */ - ConstPointerContainer> OutputDefs() const noexcept { - return ConstPointerContainer>(definitions_.output_defs); - } - /** Gets a modifiable collection of the Node's output definitions. */ std::vector& MutableOutputDefs() noexcept { return definitions_.output_defs; } +#endif // !defined(ORT_MINIMAL_BUILD) /** Struct to provide sorting between EdgeEnd instances based on NodeIndex first, and NodeArg::Name second. */ struct EdgeEndCompare { @@ -297,14 +300,15 @@ class Node { ADD_ATTR_INTERFACES(ONNX_NAMESPACE::GraphProto) ADD_ATTR_INTERFACES(ONNX_NAMESPACE::SparseTensorProto) + /** Gets the Node's attributes. */ + const NodeAttributes& GetAttributes() const noexcept { return attributes_; } + +#if !defined(ORT_MINIMAL_BUILD) /** Remove the specified attribute from this Node */ bool ClearAttribute(const std::string& attr_name); - /** Gets the Node's attributes. */ - const NodeAttributes& GetAttributes() const noexcept; - /** Gets the Node's mutable attributes. */ - NodeAttributes& GetMutableAttributes() noexcept; + NodeAttributes& GetMutableAttributes() noexcept { return attributes_; } /** Gets the Graph instance that is instantiated from a GraphProto attribute during Graph::Resolve. @param attr_name Attribute name for the GraphProto attribute. @@ -317,6 +321,7 @@ class Node { @returns nullptr if the Graph instance has not been instantiated or attribute does not contain a GraphProto. */ Graph* GetMutableGraphAttribute(const std::string& attr_name); +#endif // !defined(ORT_MINIMAL_BUILD) /** Checks if the Node contains at least one subgraph (this is the case for control flow operators, such as If, Scan, Loop). @returns true if the Node contains a subgraph. @@ -338,18 +343,11 @@ class Node { } /** Gets the execution ProviderType that this node will be executed by. */ - ProviderType GetExecutionProviderType() const noexcept; + ProviderType GetExecutionProviderType() const noexcept { return execution_provider_type_; } /** Sets the execution ProviderType that this Node will be executed by. */ void SetExecutionProviderType(ProviderType execution_provider_type); - /** Gets the NodeProto representation of this Node. - @param update_subgraphs Update the GraphProto values for any subgraphs in the returned NodeProto. - If graph optimization has been run this is most likely required - to ensure the complete Graph is valid. - */ - void ToProto(ONNX_NAMESPACE::NodeProto& proto, bool update_subgraphs = false) const; - /** Call the provided function for all explicit inputs, implicit inputs, and outputs of this Node. If the NodeArg is an explicit or implicit input, is_input will be true when func is called. @param include_missing_optional_defs Include NodeArgs that are optional and were not provided @@ -358,11 +356,20 @@ class Node { void ForEachDef(std::function func, bool include_missing_optional_defs = false) const; +#if !defined(ORT_MINIMAL_BUILD) /** Replaces any matching definitions in the Node's explicit inputs or explicit outputs. @param replacements Map of current NodeArg to replacement NodeArg. */ void ReplaceDefs(const std::map& replacements); + /** Gets the NodeProto representation of this Node. + @param update_subgraphs Update the GraphProto values for any subgraphs in the returned NodeProto. + If graph optimization has been run this is most likely required + to ensure the complete Graph is valid. + */ + void ToProto(ONNX_NAMESPACE::NodeProto& proto, bool update_subgraphs = false) const; +#endif + /** @class Definitions The input and output definitions for this Node. @@ -432,6 +439,7 @@ class Node { Node(NodeIndex index, Graph& graph) : index_(index), graph_(&graph) {} +#if !defined(ORT_MINIMAL_BUILD) void Init(const std::string& name, const std::string& op_type, const std::string& description, @@ -451,9 +459,6 @@ class Node { const std::vector>& MutableSubgraphs() noexcept { return subgraphs_; } - const Definitions& GetDefinitions() const noexcept { return definitions_; } - const Relationships& GetRelationships() const noexcept { return relationships_; } - void SetNodeType(Node::Type node_type) noexcept; void SetFunctionBody(const Function& func); @@ -461,6 +466,11 @@ class Node { // validate and update the input arg count common::Status UpdateInputArgCount(); +#endif // !defined(ORT_MINIMAL_BUILD) + + const Definitions& GetDefinitions() const noexcept { return definitions_; } + const Relationships& GetRelationships() const noexcept { return relationships_; } + // Node index. Default to impossible value rather than 0. NodeIndex index_ = std::numeric_limits::max(); @@ -473,8 +483,10 @@ class Node { // OperatorSet domain of op_type_. std::string domain_; +#if !defined(ORT_MINIMAL_BUILD) // OperatorSchema that <*this> node refers to. const ONNX_NAMESPACE::OpSchema* op_ = nullptr; +#endif // set from op_->SinceVersion() or via deserialization when OpSchema is not available int since_version_ = -1; @@ -519,26 +531,23 @@ class Graph { public: /** Gets the Graph name. */ const std::string& Name() const noexcept; - /** Sets the Graph name. */ - void SetName(const std::string& name); /** Gets the Graph description. */ const std::string& Description() const noexcept; - /** Gets the Graph description. */ - void SetDescription(const std::string& description); /** Gets the path of the owning model, if any. */ const Path& ModelPath() const; +#if !defined(ORT_MINIMAL_BUILD) + /** Sets the Graph name. */ + void SetName(const std::string& name); + + /** Gets the Graph description. */ + void SetDescription(const std::string& description); + /** Add an initializer tensor to the Graph. */ void AddInitializedTensor(const ONNX_NAMESPACE::TensorProto& tensor_proto); - /** Remove the initializer tensor with the provided name from the Graph. */ - void RemoveInitializedTensor(const std::string& tensor_name); - - /** Check if a given name is an initializer tensor's name in this graph. */ - bool IsInitializedTensor(const std::string& name) const; - /** Replaces the initializer tensor with the same name as the given initializer tensor. The replacement initializer tensor must have the same type and shape as the existing initializer tensor. @@ -546,6 +555,13 @@ class Graph { how initializer tensors are stored and tracked. */ common::Status ReplaceInitializedTensor(const ONNX_NAMESPACE::TensorProto& new_initializer); +#endif // !defined(ORT_MINIMAL_BUILD) + + /** Remove the initializer tensor with the provided name from the Graph. */ + void RemoveInitializedTensor(const std::string& tensor_name); + + /** Check if a given name is an initializer tensor's name in this graph. */ + bool IsInitializedTensor(const std::string& name) const; /** Gets an initializer tensor with the provided name. @param[out] value Set to the TensorProto* if the initializer is found, or nullptr if not. @@ -554,7 +570,7 @@ class Graph { bool GetInitializedTensor(const std::string& tensor_name, const ONNX_NAMESPACE::TensorProto*& value) const; /** Gets all the initializer tensors in this Graph. */ - const InitializedTensorSet& GetAllInitializedTensors() const noexcept; + const InitializedTensorSet& GetAllInitializedTensors() const noexcept { return name_to_initial_tensor_; } /** Removes all initializer tensors from this Graph and releases the memory they were using. */ void CleanAllInitializedTensors() noexcept; @@ -613,9 +629,11 @@ class Graph { /** Gets the NodeArgs that represent value_info instances in the Graph. These are the values that are neither Graph inputs nor outputs. @remarks Contains no nullptr values. */ - const std::vector& GetValueInfo() const noexcept; + const std::vector& GetValueInfo() const noexcept { return value_info_; } +#if !defined(ORT_MINIMAL_BUILD) void AddValueInfo(const NodeArg* new_value_info); +#endif /** Gets the Node with the specified node index. @returns Node instance if found. nullptr if node_index is invalid or node has been freed. @@ -671,6 +689,7 @@ class Graph { return *(result.first->second); } +#if !defined(ORT_MINIMAL_BUILD) /** Generate a unique name in this Graph for a NodeArg */ std::string GenerateNodeArgName(const std::string& base_name); @@ -738,6 +757,8 @@ class Graph { */ bool AddControlEdge(NodeIndex src_node_index, NodeIndex dst_node_index); +#endif // !defined(ORT_MINIMAL_BUILD) + /** Mark the Graph as needing Resolve() to be called. This should be done after modifying any aspect of the Graph that changes the Nodes or relationships between them. */ Graph& SetGraphResolveNeeded() noexcept { @@ -804,6 +825,7 @@ class Graph { return domain_to_version_; } +#if !defined(ORT_MINIMAL_BUILD) /** Gets the GraphProto representation of this Graph. */ const ONNX_NAMESPACE::GraphProto& ToGraphProto(); ONNX_NAMESPACE::GraphProto ToGraphProto() const; @@ -850,6 +872,7 @@ class Graph { @remarks Note that the output order matters for subgraphs. */ void SetOutputs(const std::vector& outputs); +#endif // !defined(ORT_MINIMAL_BUILD) /** Returns true if this is a subgraph or false if it is a high-level graph. */ bool IsSubgraph() const { return parent_graph_ != nullptr; } @@ -860,6 +883,7 @@ class Graph { /** Returns the mutable parent graph if this is a subgraph */ Graph* MutableParentGraph() { return parent_graph_; } +#if !defined(ORT_MINIMAL_BUILD) /** Sets the type of a NodeArg, replacing existing type/shape if any */ void SetNodeArgType(NodeArg& arg, const onnx::TypeProto& type_proto); @@ -934,6 +958,8 @@ class Graph { return Resolve(default_options); } +#endif // !defined(ORT_MINIMAL_BUILD) + /** Returns the Node containing the GraphProto for this Graph instance if IsSubgraph is true */ const Node* ParentNode() const { return parent_node_; } @@ -942,6 +968,7 @@ class Graph { return resolve_context_.outer_scope_node_args.find(name) != resolve_context_.outer_scope_node_args.cend(); } +#if !defined(ORT_MINIMAL_BUILD) /** Construct a Graph instance for a subgraph that is created from a GraphProto attribute in a Node. Inherits some properties from the parent graph. @param parent_graph The Graph containing the Node that has the GraphProto attribute. @@ -949,6 +976,7 @@ class Graph { @param subgraph_proto The GraphProto from the Node attribute. */ Graph(Graph& parent_graph, const Node& parent_node, ONNX_NAMESPACE::GraphProto& subgraph_proto); +#endif virtual ~Graph(); @@ -961,6 +989,7 @@ class Graph { Graph() = delete; +#if !defined(ORT_MINIMAL_BUILD) // Constructor: Given a loaded from model file, construct // a object. Used by Model to create a Graph instance. Graph(const Model& owning_model, @@ -988,6 +1017,8 @@ class Graph { Node& AddNode(const ONNX_NAMESPACE::NodeProto& node_proto, const ArgNameToTypeMap& name_to_type); +#endif + Version IrVersion() const noexcept { return ir_version_; } @@ -1037,10 +1068,7 @@ class Graph { // Initialize overridable initializers container void ComputeOverridableInitializers(); - // recursively accumulate and set the outer scope node args in the resolve context for all subgraphs - // so they can be used to resolve outer scope dependencies when running BuildConnections for the subgraphs. - common::Status SetOuterScopeNodeArgs(const std::unordered_set& outer_scope_node_args); - +#if !defined(ORT_MINIMAL_BUILD) // Build and verify node connection (edges). // Verify NodeArg name/type/shape matching correctly. common::Status BuildConnections(std::unordered_set& outer_scope_node_args_consumed); @@ -1082,6 +1110,10 @@ class Graph { // Set graph inputs/outputs when resolving a graph.. common::Status SetGraphInputsOutputs(); + // recursively accumulate and set the outer scope node args in the resolve context for all subgraphs + // so they can be used to resolve outer scope dependencies when running BuildConnections for the subgraphs. + common::Status SetOuterScopeNodeArgs(const std::unordered_set& outer_scope_node_args); + // Clear all unused initializers void CleanUnusedInitializers(const std::unordered_set* initializer_names_to_preserve = nullptr); @@ -1091,16 +1123,6 @@ class Graph { // @returns false if node_index was invalid. bool ReleaseNode(NodeIndex node_index); - Node* NodeAtIndexImpl(NodeIndex node_index) const { - // if we are trying to access a node that doesn't exist there's (most - // likely) either a logic issue or a graph consistency/correctness issue. - // use ORT_ENFORCE to prove that or uncover scenarios where we actually - // expect attempts to retrieve a non-existent node. - ORT_ENFORCE(node_index < nodes_.size(), "Validating no unexpected access using an invalid node_index. Got:", - node_index, " Max:", nodes_.size()); - return nodes_[node_index].get(); - } - std::vector CreateNodeArgs(const google::protobuf::RepeatedPtrField& names, const ArgNameToTypeMap& name_to_type_map); @@ -1133,6 +1155,18 @@ class Graph { return results; } +#endif // !defined(ORT_MINIMAL_BUILD) + + Node* NodeAtIndexImpl(NodeIndex node_index) const { + // if we are trying to access a node that doesn't exist there's (most + // likely) either a logic issue or a graph consistency/correctness issue. + // use ORT_ENFORCE to prove that or uncover scenarios where we actually + // expect attempts to retrieve a non-existent node. + ORT_ENFORCE(node_index < nodes_.size(), "Validating no unexpected access using an invalid node_index. Got:", + node_index, " Max:", nodes_.size()); + return nodes_[node_index].get(); + } + const Model& owning_model_; // GraphProto to store name, version, initializer. @@ -1144,10 +1178,14 @@ class Graph { InitializedTensorSet name_to_initial_tensor_; +#if !defined(ORT_MINIMAL_BUILD) + IOnnxRuntimeOpSchemaCollectionPtr schema_registry_; std::vector> function_container_; +#endif // !defined(ORT_MINIMAL_BUILD) + // Graph nodes. // Element in may be nullptr due to graph optimization. std::vector> nodes_; @@ -1187,6 +1225,12 @@ class Graph { // Graph value_info. std::vector value_info_; + // All node args owned by <*this> graph. Key is node arg name. + std::unordered_map> node_args_; + +#if !defined(ORT_MINIMAL_BUILD) + int name_generator_ = 0; + // Strings which have been used as node names. // New node name should not conflict with this set. std::unordered_set generated_node_names_; @@ -1195,18 +1239,16 @@ class Graph { // New node_arg name should not conflict this this set. std::unordered_set generated_node_arg_names_; - // All node args owned by <*this> graph. Key is node arg name. - std::unordered_map> node_args_; - // node arg to its producer node std::unordered_map node_arg_to_producer_node_; // node arg to its consumer nodes std::unordered_map> node_arg_to_consumer_nodes_; - const std::unordered_map domain_to_version_; - std::unordered_map model_functions_; +#endif // !defined(ORT_MINIMAL_BUILD) + + const std::unordered_map domain_to_version_; // Model IR version. Version ir_version_{ONNX_NAMESPACE::Version::IR_VERSION}; @@ -1214,8 +1256,6 @@ class Graph { // Is model using latest ONNX opset bool using_latest_onnx_opset_{false}; - int name_generator_ = 0; - ResolveContext resolve_context_; // the parent graph if this is a subgraph. @@ -1236,6 +1276,8 @@ class Graph { const bool is_loaded_from_model_file_; }; +#if !defined(ORT_MINIMAL_BUILD) std::ostream& operator<<(std::ostream& out, const Graph& graph); +#endif } // namespace onnxruntime diff --git a/include/onnxruntime/core/graph/node_arg.h b/include/onnxruntime/core/graph/node_arg.h index 0c2b63e72e..ae16d2f2b1 100644 --- a/include/onnxruntime/core/graph/node_arg.h +++ b/include/onnxruntime/core/graph/node_arg.h @@ -59,6 +59,7 @@ class NodeArg { @returns true if NodeArg is a normal tensor with a non-empty shape or a scalar with an empty shape. Otherwise, returns false. */ bool HasTensorOrScalarShape() const; +#if !defined(ORT_MINIMAL_BUILD) /** Sets the shape. @remarks Shape can only be set if the TypeProto was provided to the ctor, or #SetType has been called, as the shape information is stored as part of TypeProto. */ @@ -85,6 +86,8 @@ class NodeArg { /** Gets this NodeArg as a ValueInfoProto. */ const NodeArgInfo& ToProto() const noexcept { return node_arg_info_; } +#endif // !defined(ORT_MINIMAL_BUILD) + /** Gets a flag indicating whether this NodeArg exists or not. Optional inputs are allowed in ONNX and an empty #Name represents a non-existent input argument. */ bool Exists() const noexcept; @@ -93,8 +96,10 @@ class NodeArg { ORT_DISALLOW_COPY_AND_ASSIGNMENT(NodeArg); friend class Graph; +#if !defined(ORT_MINIMAL_BUILD) void SetType(ONNX_NAMESPACE::DataType p_type); void SetType(const ONNX_NAMESPACE::TypeProto& type_proto); +#endif // Node arg PType. ONNX_NAMESPACE::DataType type_; diff --git a/onnxruntime/core/framework/sequential_executor.cc b/onnxruntime/core/framework/sequential_executor.cc index 7e4610d426..e725675ace 100644 --- a/onnxruntime/core/framework/sequential_executor.cc +++ b/onnxruntime/core/framework/sequential_executor.cc @@ -139,13 +139,18 @@ Status SequentialExecutor::Execute(const SessionState& session_state, const std: } ExecutionFrame frame{feed_mlvalue_idxs, feeds, fetch_mlvalue_idxs, fetches, fetch_allocators, session_state}; + const std::unordered_set* to_be_executed_nodes = nullptr; - const std::unordered_set* to_be_executed_nodes = session_state.GetToBeExecutedNodes(fetch_mlvalue_idxs); +#if !defined(ORT_MINIMAL_BUILD) + to_be_executed_nodes = session_state.GetToBeExecutedNodes(fetch_mlvalue_idxs); const bool only_execute_path_to_fetches = only_execute_path_to_fetches_ && (to_be_executed_nodes != nullptr); if (only_execute_path_to_fetches) { VLOGS(logger, 1) << to_be_executed_nodes->size() << " nodes to be executed\n"; } +#else + const bool only_execute_path_to_fetches = false; +#endif LOGS(logger, INFO) << "Begin execution"; const SequentialExecutionPlan& seq_exec_plan = *session_state.GetExecutionPlan(); @@ -445,12 +450,12 @@ Status SequentialExecutor::Execute(const SessionState& session_state, const std: session_state.Profiler().EndTimeAndRecordEvent(profiling::SESSION_EVENT, "SequentialExecutor::Execute", tp); } - for (auto i: frame.GetStaticMemorySizeInfo()) { + for (auto i : frame.GetStaticMemorySizeInfo()) { LOGS(logger, INFO) << "[Memory] ExecutionFrame statically allocates " << i.second << " bytes for " << i.first << std::endl; } - for (auto i: frame.GetDynamicMemorySizeInfo()) { + for (auto i : frame.GetDynamicMemorySizeInfo()) { LOGS(logger, INFO) << "[Memory] ExecutionFrame dynamically allocates " << i.second << " bytes for " << i.first << std::endl; } diff --git a/onnxruntime/core/framework/session_state.cc b/onnxruntime/core/framework/session_state.cc index 8f95fc17bc..7336180b39 100644 --- a/onnxruntime/core/framework/session_state.cc +++ b/onnxruntime/core/framework/session_state.cc @@ -118,6 +118,7 @@ void SessionState::CreateGraphInfo() { LOGS(logger_, VERBOSE) << "Done saving OrtValue mappings."; } +#if !defined(ORT_MINIMAL_BUILD) Status SessionState::PopulateKernelCreateInfo(KernelRegistryManager& kernel_registry_manager) { for (auto& node : graph_.Nodes()) { const KernelCreateInfo* kci = nullptr; @@ -135,6 +136,7 @@ Status SessionState::PopulateKernelCreateInfo(KernelRegistryManager& kernel_regi return Status::OK(); } +#endif const KernelCreateInfo& SessionState::GetNodeKernelCreateInfo(NodeIndex node_index) const { auto entry = kernel_create_info_map_.find(node_index); @@ -597,6 +599,7 @@ const NodeIndexInfo& SessionState::GetNodeIndexInfo() const { return *node_index_info_; } +#if !defined(ORT_MINIMAL_BUILD) void SessionState::UpdateToBeExecutedNodes(const std::vector& fetch_mlvalue_idxs) { std::vector sorted_idxs = fetch_mlvalue_idxs; std::sort(sorted_idxs.begin(), sorted_idxs.end()); @@ -629,6 +632,7 @@ const std::unordered_set* SessionState::GetToBeExecutedNodes( auto it = to_be_executed_nodes_.find(sorted_idxs); return (it != to_be_executed_nodes_.end()) ? &it->second : nullptr; } +#endif // !defined(ORT_MINIMAL_BUILD) Status SessionState::CreateSubgraphSessionState() { for (auto& node : graph_.Nodes()) { @@ -673,10 +677,17 @@ Status SessionState::FinalizeSessionState(const std::basic_string& graph_location, diff --git a/onnxruntime/core/framework/session_state.h b/onnxruntime/core/framework/session_state.h index d4b4c17d46..c494333e6d 100644 --- a/onnxruntime/core/framework/session_state.h +++ b/onnxruntime/core/framework/session_state.h @@ -246,10 +246,13 @@ class SessionState { const DataTransferManager& GetDataTransferMgr() const noexcept { return data_transfer_mgr_; } std::vector& GetMutableWeightsBuffers() noexcept { return weights_buffers_; } + const NodeIndexInfo& GetNodeIndexInfo() const; +#if !defined(ORT_MINIMAL_BUILD) void UpdateToBeExecutedNodes(const std::vector& fetch_mlvalue_idxs); const std::unordered_set* GetToBeExecutedNodes(const std::vector& fetch_mlvalue_idxs) const; +#endif Status FinalizeSessionState(const std::basic_string& graph_loc, KernelRegistryManager& kernel_registry_manager, @@ -284,7 +287,9 @@ class SessionState { void AddSubgraphSessionState(onnxruntime::NodeIndex index, const std::string& attribute_name, std::unique_ptr session_state); +#if !defined(ORT_MINIMAL_BUILD) Status PopulateKernelCreateInfo(KernelRegistryManager& kernel_registry_manager); +#endif Status FinalizeSessionStateImpl(const std::basic_string& graph_loc, KernelRegistryManager& kernel_registry_manager, @@ -391,7 +396,10 @@ class SessionState { std::unique_ptr node_index_info_; std::multimap> cached_feeds_fetches_managers_; + +#if !defined(ORT_MINIMAL_BUILD) std::map, std::unordered_set> to_be_executed_nodes_; +#endif #ifdef ONNXRUNTIME_ENABLE_INSTRUMENT SessionState* parent_ = nullptr; diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index 296cdaeba7..3b524240f1 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -17,23 +17,27 @@ #include "core/framework/tensor_shape.h" #include "core/framework/tensorprotoutils.h" #include "core/framework/utils.h" -#include "core/graph/function.h" -#include "core/graph/function_impl.h" #include "core/graph/graph_utils.h" #include "core/graph/graph_viewer.h" #include "core/graph/indexed_sub_graph.h" +#include "core/graph/model.h" #include "core/graph/schema_registry.h" #include "core/graph/op.h" +#if !defined(ORT_MINIMAL_BUILD) +#include "core/graph/function.h" +#include "core/graph/function_impl.h" #include "onnx/checker.h" +using namespace ONNX_NAMESPACE::checker; +#endif using namespace ONNX_NAMESPACE; using namespace ONNX_NAMESPACE::Utils; -using namespace ONNX_NAMESPACE::checker; using namespace ::onnxruntime::common; namespace onnxruntime { +#if !defined(ORT_MINIMAL_BUILD) #define NO_CHANGE_ON_SYNC_FLAG(...) \ do { \ const bool sync_needed = GraphProtoSyncNeeded(); \ @@ -131,6 +135,8 @@ NodeArg::NodeArg(const std::string& name, const TypeProto* p_node_arg_type) { } } +#endif // !defined(ORT_MINIMAL_BUILD) + const std::string& NodeArg::Name() const noexcept { return node_arg_info_.name(); } @@ -192,6 +198,7 @@ bool NodeArg::HasTensorOrScalarShape() const { } } +#if !defined(ORT_MINIMAL_BUILD) void NodeArg::SetShape(const TensorShapeProto& shape) { const auto type_case = node_arg_info_.type().value_case(); switch (type_case) { @@ -347,6 +354,8 @@ void NodeArg::SetType(const TypeProto& type_proto) { *(node_arg_info_.mutable_type()) = type_proto; } +#endif // !defined(ORT_MINIMAL_BUILD) + bool NodeArg::Exists() const noexcept { return exists_; } @@ -361,18 +370,6 @@ Node::EdgeEnd::EdgeEnd(const Node& node) noexcept : EdgeEnd(node, INT_MAX, INT_MAX) { } -const Node& Node::EdgeEnd::GetNode() const noexcept { - return *node_; -} - -int Node::EdgeEnd::GetSrcArgIndex() const { - return src_arg_index_; -} - -int Node::EdgeEnd::GetDstArgIndex() const { - return dst_arg_index_; -} - Node::NodeConstIterator::NodeConstIterator(EdgeConstIterator p_iter) { m_iter = p_iter; } @@ -401,33 +398,7 @@ const Node* Node::NodeConstIterator::operator->() const { return &(operator*()); } -NodeIndex Node::Index() const noexcept { - return index_; -} - -const std::string& Node::Name() const noexcept { - return name_; -} - -const std::string& Node::OpType() const noexcept { - return op_type_; -} - -const std::string& Node::Description() const noexcept { - return description_; -} - -const std::string& Node::Domain() const noexcept { - return domain_; -} - -const OpSchema* Node::Op() const noexcept { - return op_; -} - -Node::Type Node::NodeType() const noexcept { - return node_type_; -} +#if !defined(ORT_MINIMAL_BUILD) void Node::SetNodeType(Node::Type node_type) noexcept { node_type_ = node_type; @@ -446,20 +417,12 @@ const Function* Node::GetFunctionBody(bool try_init_func_body) { return func_body_; } -const Function* Node::GetFunctionBody() const noexcept { - return func_body_; -} - void Node::SetFunctionBody(const Function& func) { func_body_ = &func; op_ = &func.OpSchema(); since_version_ = op_->since_version(); } -const std::string& Node::GetExecutionProviderType() const noexcept { - return execution_provider_type_; -} - void Node::SetExecutionProviderType(ProviderType execution_provider_type) { execution_provider_type_ = execution_provider_type; } @@ -556,6 +519,8 @@ void Node::CreateSubgraph(const std::string& attr_name) { } } +#endif // !defined(ORT_MINIMAL_BUILD) + void Node::AddAttribute(const std::string& attr_name, const AttributeProto& value) { graph_->SetGraphResolveNeeded(); graph_->SetGraphProtoSyncNeeded(); @@ -607,7 +572,10 @@ void Node::AddAttribute(const std::string& attr_name, const GraphProto& value) { *a.mutable_g() = value; attributes_[attr_name] = a; +#if !defined(ORT_MINIMAL_BUILD) + // subgraph is created via deserialization and not here in a minimal build CreateSubgraph(attr_name); +#endif }; ADD_BASIC_ATTR_IMPL(float, AttributeProto_AttributeType::AttributeProto_AttributeType_FLOAT, f) @@ -622,6 +590,7 @@ ADD_LIST_ATTR_IMPL(TensorProto, AttributeProto_AttributeType::AttributeProto_Att ADD_LIST_ATTR_IMPL(GraphProto, AttributeProto_AttributeType::AttributeProto_AttributeType_GRAPHS, graphs) ADD_LIST_ATTR_IMPL(SparseTensorProto, AttributeProto_AttributeType::AttributeProto_AttributeType_SPARSE_TENSORS, sparse_tensors) +#if !defined(ORT_MINIMAL_BUILD) bool Node::ClearAttribute(const std::string& attr_name) { graph_->SetGraphResolveNeeded(); graph_->SetGraphProtoSyncNeeded(); @@ -684,14 +653,6 @@ Status Node::UpdateInputArgCount() { return Status::OK(); } -const NodeAttributes& Node::GetAttributes() const noexcept { - return attributes_; -} - -NodeAttributes& Node::GetMutableAttributes() noexcept { - return attributes_; -} - Graph* Node::GetMutableGraphAttribute(const std::string& attr_name) { Graph* subgraph = nullptr; @@ -707,6 +668,18 @@ const Graph* Node::GetGraphAttribute(const std::string& attr_name) const { return const_cast(this)->GetMutableGraphAttribute(attr_name); } +void Node::ReplaceDefs(const std::map& replacements) { + std::vector*> all_defs = {&definitions_.input_defs, &definitions_.output_defs}; + + for (auto pair : replacements) + for (auto* defs : all_defs) + for (auto& def : *defs) + if (def == pair.first) + def = pair.second; +} + +#endif // !defined(ORT_MINIMAL_BUILD) + std::vector> Node::GetSubgraphs() const { std::vector> subgraphs; subgraphs.reserve(attr_to_subgraph_map_.size()); @@ -735,16 +708,6 @@ void Node::ForEachDef(std::function& replacements) { - std::vector*> all_defs = {&definitions_.input_defs, &definitions_.output_defs}; - - for (auto pair : replacements) - for (auto* defs : all_defs) - for (auto& def : *defs) - if (def == pair.first) - def = pair.second; -} - // Constructor: Given a loaded from model file, construct // a object and Resolve() it. //Status Graph::LoadGraph(const GraphProto& graph_proto, @@ -764,6 +727,8 @@ void Node::ReplaceDefs(const std::map& domain_to_version, @@ -783,8 +748,8 @@ Graph::Graph(const Model& owning_model, graph_proto_(graph_proto), schema_registry_(schema_registry), graph_resolve_needed_(true), - domain_to_version_(domain_to_version), model_functions_(model_functions), + domain_to_version_(domain_to_version), ir_version_(ir_version), using_latest_onnx_opset_(UsingLatestOnnxOpset(domain_to_version)), parent_graph_(parent_graph), @@ -1066,16 +1031,6 @@ common::Status Graph::SetOuterScopeNodeArgs(const std::unordered_setGetNodeArgIncludingParentGraphs(node_arg_name); - } - - return node_arg; -} - void Graph::AddEdge(NodeIndex src_node_index, NodeIndex dst_node_index, int src_arg_slot, int dst_arg_slot) { if (nodes_.size() <= src_node_index || src_arg_slot < 0 || nodes_.size() <= dst_node_index || dst_arg_slot < 0 || nullptr == nodes_[src_node_index] || nullptr == nodes_[dst_node_index]) { @@ -1315,6 +1270,18 @@ Status Graph::BuildConnections(std::unordered_set& outer_scope_node return Status::OK(); } +NodeArg* Graph::GetNodeArgIncludingParentGraphs(const std::string& node_arg_name) { + NodeArg* node_arg = GetNodeArg(node_arg_name); + + if (!node_arg && parent_graph_) { + node_arg = parent_graph_->GetNodeArgIncludingParentGraphs(node_arg_name); + } + + return node_arg; +} + +#endif // !defined(ORT_MINIMAL_BUILD) + void Graph::ReverseDFSFrom(const std::vector& from, const std::function& enter, const std::function& leave, @@ -1395,6 +1362,8 @@ void Graph::ReverseDFSFrom(const std::vector& from, } } +#if !defined(ORT_MINIMAL_BUILD) + GSL_SUPPRESS(es .84) // noisy warning about ignoring return value from insert(...) Status Graph::PerformTopologicalSortAndCheckIsAcyclic() { nodes_in_topological_order_.clear(); @@ -2125,15 +2094,6 @@ void Graph::InitFunctionBodyForNode(Node& node) { } } -void Graph::FindAllSubgraphs(std::vector& subgraphs) { - for (auto& node : Nodes()) { - for (auto& subgraph : node.MutableSubgraphs()) { - subgraphs.push_back(subgraph.get()); - subgraph->FindAllSubgraphs(subgraphs); - } - } -} - Status Graph::VerifyInputAndInitializerNames() { std::unordered_set& inputs_and_initializers = resolve_context_.inputs_and_initializers; @@ -2201,6 +2161,15 @@ Status Graph::PerformTypeAndShapeInferencing(const ResolveOptions& options) { return Status::OK(); } +void Graph::FindAllSubgraphs(std::vector& subgraphs) { + for (auto& node : Nodes()) { + for (auto& subgraph : node.MutableSubgraphs()) { + subgraphs.push_back(subgraph.get()); + subgraph->FindAllSubgraphs(subgraphs); + } + } +} + Status Graph::ForThisAndAllSubgraphs(const std::vector& subgraphs, std::function func) { auto status = func(*this); ORT_RETURN_IF_ERROR(status); @@ -2276,26 +2245,6 @@ Status Graph::Resolve(const ResolveOptions& options) { return Status::OK(); } -const std::string& Graph::Name() const noexcept { - return graph_proto_->name(); -} - -void Graph::SetName(const std::string& name) { - graph_proto_->set_name(name); -} - -const std::string& Graph::Description() const noexcept { - return graph_proto_->doc_string(); -} - -void Graph::SetDescription(const std::string& description) { - graph_proto_->set_doc_string(description); -} - -const Path& Graph::ModelPath() const { - return owning_model_.ModelPath(); -} - void Graph::AddInitializedTensor(const TensorProto& tensor) { auto existing = name_to_initial_tensor_.find(tensor.name()); if (existing != name_to_initial_tensor_.cend()) { @@ -2319,6 +2268,28 @@ void Graph::AddInitializedTensor(const TensorProto& tensor) { } } +void Graph::SetName(const std::string& name) { + graph_proto_->set_name(name); +} + +void Graph::SetDescription(const std::string& description) { + graph_proto_->set_doc_string(description); +} + +#endif // !defined(ORT_MINIMAL_BUILD) + +const std::string& Graph::Name() const noexcept { + return graph_proto_->name(); +} + +const std::string& Graph::Description() const noexcept { + return graph_proto_->doc_string(); +} + +const Path& Graph::ModelPath() const { + return owning_model_.ModelPath(); +} + template static void RemoveRepeatedFieldEntry(T& repeated_field, const TIter& entry_to_remove) { auto num_entries = repeated_field.size(); @@ -2359,6 +2330,7 @@ void Graph::RemoveInitializedTensor(const std::string& tensor_name) { } } +#if !defined(ORT_MINIMAL_BUILD) Status Graph::ReplaceInitializedTensor(const ONNX_NAMESPACE::TensorProto& new_initializer) { // name_to_initial_tensor_ maps from name to const TensorProto*, so we first // look up the const pointer by name, then find and modify the mutable @@ -2395,6 +2367,7 @@ Status Graph::ReplaceInitializedTensor(const ONNX_NAMESPACE::TensorProto& new_in return Status::OK(); } +#endif // !defined(ORT_MINIMAL_BUILD) bool Graph::GetInitializedTensor(const std::string& tensor_name, const TensorProto*& value) const { auto iter = name_to_initial_tensor_.find(tensor_name); @@ -2419,14 +2392,7 @@ void Graph::CleanAllInitializedTensors() noexcept { } } -const InitializedTensorSet& Graph::GetAllInitializedTensors() const noexcept { - return name_to_initial_tensor_; -} - -const std::vector& Graph::GetValueInfo() const noexcept { - return value_info_; -} - +#if !defined(ORT_MINIMAL_BUILD) void Graph::AddValueInfo(const NodeArg* new_value_info) { for (const auto* info : value_info_) { ORT_ENFORCE(info->Name() != new_value_info->Name(), "Error: trying to add an existing value info."); @@ -2748,6 +2714,33 @@ void Graph::CleanUnusedInitializers(const std::unordered_set* initi }); } +#endif // !defined(ORT_MINIMAL_BUILD) + +void Graph::ComputeOverridableInitializers() { + graph_overridable_initializers_.clear(); + if (CanOverrideInitializer()) { + // graph_inputs_excluding_initializers_ and graph_inputs_including_initializers_ + // are inserted in the same order. So we walk and compute the difference. + auto f_incl = graph_inputs_including_initializers_.cbegin(); + const auto l_incl = graph_inputs_including_initializers_.cend(); + auto f_excl = graph_inputs_excluding_initializers_.cbegin(); + const auto l_excl = graph_inputs_excluding_initializers_.cend(); + + while (f_incl != l_incl) { + // Equal means not an initializer + if (f_excl != l_excl && *f_incl == *f_excl) { + ++f_incl; + ++f_excl; + continue; + } + graph_overridable_initializers_.push_back(*f_incl); + ++f_incl; + } + } +} + +#if !defined(ORT_MINIMAL_BUILD) + GSL_SUPPRESS(es .84) // warning about ignoring return value from insert(...) Status Graph::SetGraphInputsOutputs() { // If loaded from a model file, we start from the specified inputs and @@ -2889,29 +2882,6 @@ Status Graph::SetGraphInputsOutputs() { return Status::OK(); } -void Graph::ComputeOverridableInitializers() { - graph_overridable_initializers_.clear(); - if (CanOverrideInitializer()) { - // graph_inputs_excluding_initializers_ and graph_inputs_including_initializers_ - // are inserted in the same order. So we walk and compute the difference. - auto f_incl = graph_inputs_including_initializers_.cbegin(); - const auto l_incl = graph_inputs_including_initializers_.cend(); - auto f_excl = graph_inputs_excluding_initializers_.cbegin(); - const auto l_excl = graph_inputs_excluding_initializers_.cend(); - - while (f_incl != l_incl) { - // Equal means not an initializer - if (f_excl != l_excl && *f_incl == *f_excl) { - ++f_incl; - ++f_excl; - continue; - } - graph_overridable_initializers_.push_back(*f_incl); - ++f_incl; - } - } -} - // calling private ctor GSL_SUPPRESS(r .11) gsl::not_null Graph::AllocateNode() { @@ -3092,11 +3062,14 @@ void Graph::SetNodeArgType(NodeArg& arg, const onnx::TypeProto& type_proto) { GraphResolveNeeded(true); } +#endif // !defined(ORT_MINIMAL_BUILD) + Graph::~Graph() { // nothing to do, but we put it here so we don't need to fully define types in Graph that are held in unique_ptr // such as std::unique_ptr function_container_; } +#if !defined(ORT_MINIMAL_BUILD) std::ostream& operator<<(std::ostream& out, const Graph& graph) { out << "Inputs:\n"; for (auto* x : graph.GetInputs()) { @@ -3126,5 +3099,5 @@ std::ostream& operator<<(std::ostream& out, const Graph& graph) { } return out; } - +#endif // !defined(ORT_MINIMAL_BUILD) } // namespace onnxruntime diff --git a/onnxruntime/core/graph/model.cc b/onnxruntime/core/graph/model.cc index e57e8f9b48..18aca63ab1 100644 --- a/onnxruntime/core/graph/model.cc +++ b/onnxruntime/core/graph/model.cc @@ -29,6 +29,9 @@ using namespace onnxruntime::common; static constexpr int DEFAULT_PROTOBUF_BLOCK_SIZE = 4 * 1024 * 1024; namespace onnxruntime { + +#if !defined(ORT_MINIMAL_BUILD) + Model::Model(const std::string& graph_name, bool is_onnx_domain_only, const ModelMetaData& model_metadata, @@ -209,6 +212,8 @@ void Model::SetDocString(const std::string& doc_string) { model_proto_.set_doc_string(doc_string); } +#endif // !defined(ORT_MINIMAL_BUILD) + const ModelMetaData& Model::MetaData() const noexcept { return model_metadata_; } @@ -221,6 +226,8 @@ const Graph& Model::MainGraph() const noexcept { return *graph_; } +#if !defined(ORT_MINIMAL_BUILD) + void Model::AddFunction(const ONNX_NAMESPACE::FunctionProto& func_proto) { auto func_ptr = model_proto_.add_functions(); func_ptr->CopyFrom(func_proto); @@ -513,4 +520,7 @@ Status Model::Save(Model& model, int p_fd) { } return Status(ONNXRUNTIME, INVALID_PROTOBUF, "Protobuf serialization failed."); } + +#endif // !defined(ORT_MINIMAL_BUILD) + } // namespace onnxruntime diff --git a/onnxruntime/core/graph/model.h b/onnxruntime/core/graph/model.h index c20a89d84a..4715a67eb8 100644 --- a/onnxruntime/core/graph/model.h +++ b/onnxruntime/core/graph/model.h @@ -23,6 +23,7 @@ class Model { public: static constexpr Version kNoVersion = INT64_MAX; +#if !defined(ORT_MINIMAL_BUILD) explicit Model(const std::string& graph_name, bool is_onnx_domain_only, const logging::Logger& logger) @@ -67,6 +68,9 @@ class Model { const IOnnxRuntimeOpSchemaRegistryList* local_registries, const logging::Logger& logger); +#endif // !defined(ORT_MINIMAL_BUILD) + +#if !defined(ORT_MINIMAL_BUILD) // Get model's IR version. // Return if not specified. Version IrVersion() const; @@ -100,6 +104,31 @@ class Model { const std::string& DocString() const; // Set models' doc string. void SetDocString(const std::string& doc_string); +#else + // Get model's IR version. + // Return if not specified. + Version IrVersion() const { return ir_version_; } + + // Get model's producer name. + // Return null pointer if not specified. + const std::string& ProducerName() const { return producer_name_; } + + // Get model's producer version. + // Return null pointer if not specified. + const std::string& ProducerVersion() const { return producer_version_; } + + // Get model's domain. + const std::string& Domain() const { return domain_; } + + // Get model's version. + // Return null pointer if not specified. + Version ModelVersion() const { return model_version_; } + + // Get model's doc string. + // Return null pointer if not specified. + const std::string& DocString() const { return doc_string_; } + +#endif const ModelMetaData& MetaData() const noexcept; @@ -110,6 +139,7 @@ class Model { Graph& MainGraph() noexcept; const Graph& MainGraph() const noexcept; +#if !defined(ORT_MINIMAL_BUILD) // Add function proto to Model void AddFunction(const ONNX_NAMESPACE::FunctionProto& func_proto); @@ -182,10 +212,21 @@ class Model { /*out*/ std::shared_ptr& p_model, const IOnnxRuntimeOpSchemaRegistryList* local_registries, const logging::Logger& logger); +#endif // !defined(ORT_MINIMAL_BUILD) private: // Model data. +#if !defined(ORT_MINIMAL_BUILD) ONNX_NAMESPACE::ModelProto model_proto_; +#else + // properties that would normally come from ModelProto + std::string producer_version_; + std::string producer_name_; + int64_t model_version_; + int64_t ir_version_; + std::string domain_; + std::string doc_string_; +#endif // This is a duplication of . // It gives better accessibility. diff --git a/onnxruntime/core/optimizer/graph_transformer.cc b/onnxruntime/core/optimizer/graph_transformer.cc index 07d395ba51..70c495b2d4 100644 --- a/onnxruntime/core/optimizer/graph_transformer.cc +++ b/onnxruntime/core/optimizer/graph_transformer.cc @@ -11,6 +11,7 @@ Status GraphTransformer::Apply(Graph& graph, bool& modified, const logging::Logg // the Graph should be in a good state prior this being called, so there should be no need to call Resolve here // ORT_RETURN_IF_ERROR(graph.Resolve()); +#if !defined(ORT_MINIMAL_BUILD) auto status = ApplyImpl(graph, modified, 0, logger); ORT_RETURN_IF_ERROR(status); @@ -19,7 +20,12 @@ Status GraphTransformer::Apply(Graph& graph, bool& modified, const logging::Logg if (modified) { status = graph.Resolve(); } - +#else + ORT_UNUSED_PARAMETER(graph); + ORT_UNUSED_PARAMETER(modified); + ORT_UNUSED_PARAMETER(logger); + Status status(ONNXRUNTIME, FAIL, "Transformers are not supported in this build"); +#endif return status; } diff --git a/onnxruntime/core/session/environment.cc b/onnxruntime/core/session/environment.cc index b64a0e0f87..d8dead06d3 100644 --- a/onnxruntime/core/session/environment.cc +++ b/onnxruntime/core/session/environment.cc @@ -71,6 +71,7 @@ Status Environment::Initialize(std::unique_ptr logging_ } try { +#if !defined(ORT_MINIMAL_BUILD) // Register Microsoft domain with min/max op_set version as 1/1. std::call_once(schemaRegistrationOnceFlag, []() { ONNX_NAMESPACE::OpSchemaRegistry::DomainToVersionRange::Instance().AddDomainToVersion(onnxruntime::kMSDomain, 1, 1); @@ -137,6 +138,7 @@ Internal copy node Internal copy node )DOC"); +#endif // !defined(ORT_MINIMAL_BUILD) // fire off startup telemetry (this call is idempotent) const Env& env = Env::Default(); env.GetTelemetryProvider().LogProcessInfo(); diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index f6fc2b9ba8..f64d99f2d7 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -95,6 +95,7 @@ static Status FinalizeSessionOptions(const SessionOptions& user_provided_session const ONNX_NAMESPACE::ModelProto& model_proto, bool is_model_proto_parsed, /*out*/ SessionOptions& finalized_session_options) { +#if !defined(ORT_MINIMAL_BUILD) const logging::Logger& default_logger = logging::LoggingManager::DefaultLogger(); // By now the environment should have initialized. (It is enforced prior to this.) @@ -151,6 +152,11 @@ static Status FinalizeSessionOptions(const SessionOptions& user_provided_session // use user provided session options instance finalized_session_options = user_provided_session_options; } +#else + ORT_UNUSED_PARAMETER(model_proto); + ORT_UNUSED_PARAMETER(is_model_proto_parsed); + finalized_session_options = user_provided_session_options; +#endif // !defined(ORT_MINIMAL_BUILD) return Status::OK(); } @@ -165,8 +171,11 @@ void InferenceSession::ConstructorCommon(const SessionOptions& session_options, // after the invocation of FinalizeSessionOptions. InitLogger(logging_manager_); // this sets session_logger_ so that it can be used for logging after this point. +#if !defined(ORT_MINIMAL_BUILD) // Update the number of steps for the graph transformer manager using the "finalized" session options ORT_ENFORCE(graph_transformation_mgr_.SetSteps(session_options_.max_num_graph_transformation_steps).IsOK()); +#endif + use_per_session_threads_ = session_options.use_per_session_threads; if (use_per_session_threads_) { @@ -219,19 +228,23 @@ void InferenceSession::ConstructorCommon(const SessionOptions& session_options, } InferenceSession::InferenceSession(const SessionOptions& session_options, const Environment& session_env) - : graph_transformation_mgr_(session_options.max_num_graph_transformation_steps), - logging_manager_(session_env.GetLoggingManager()), - insert_cast_transformer_("CastFloat16Transformer") { + : +#if !defined(ORT_MINIMAL_BUILD) + graph_transformation_mgr_(session_options.max_num_graph_transformation_steps), + insert_cast_transformer_("CastFloat16Transformer"), +#endif + logging_manager_(session_env.GetLoggingManager()) { // Initialize assets of this session instance ConstructorCommon(session_options, session_env); } +#if !defined(ORT_MINIMAL_BUILD) InferenceSession::InferenceSession(const SessionOptions& session_options, const Environment& session_env, const std::string& model_uri) : model_location_(ToWideString(model_uri)), graph_transformation_mgr_(session_options.max_num_graph_transformation_steps), - logging_manager_(session_env.GetLoggingManager()), - insert_cast_transformer_("CastFloat16Transformer") { + insert_cast_transformer_("CastFloat16Transformer"), + logging_manager_(session_env.GetLoggingManager()) { auto status = Model::Load(model_location_, model_proto_); ORT_ENFORCE(status.IsOK(), "Given model could not be parsed while creating inference session. Error message: ", status.ErrorMessage()); @@ -245,8 +258,8 @@ InferenceSession::InferenceSession(const SessionOptions& session_options, const Environment& session_env, const std::wstring& model_uri) : graph_transformation_mgr_(session_options.max_num_graph_transformation_steps), - logging_manager_(session_env.GetLoggingManager()), - insert_cast_transformer_("CastFloat16Transformer") { + insert_cast_transformer_("CastFloat16Transformer"), + logging_manager_(session_env.GetLoggingManager()) { model_location_ = ToWideString(model_uri); auto status = Model::Load(model_location_, model_proto_); ORT_ENFORCE(status.IsOK(), "Given model could not be parsed while creating inference session. Error message: ", @@ -260,8 +273,8 @@ InferenceSession::InferenceSession(const SessionOptions& session_options, InferenceSession::InferenceSession(const SessionOptions& session_options, const Environment& session_env, std::istream& model_istream) : graph_transformation_mgr_(session_options.max_num_graph_transformation_steps), - logging_manager_(session_env.GetLoggingManager()), - insert_cast_transformer_("CastFloat16Transformer") { + insert_cast_transformer_("CastFloat16Transformer"), + logging_manager_(session_env.GetLoggingManager()) { Status st = Model::Load(model_istream, &model_proto_); ORT_ENFORCE(st.IsOK(), "Could not parse model successfully while constructing the inference session"); is_model_proto_parsed_ = true; @@ -272,8 +285,8 @@ InferenceSession::InferenceSession(const SessionOptions& session_options, const InferenceSession::InferenceSession(const SessionOptions& session_options, const Environment& session_env, const void* model_data, int model_data_len) : graph_transformation_mgr_(session_options.max_num_graph_transformation_steps), - logging_manager_(session_env.GetLoggingManager()), - insert_cast_transformer_("CastFloat16Transformer") { + insert_cast_transformer_("CastFloat16Transformer"), + logging_manager_(session_env.GetLoggingManager()) { const bool result = model_proto_.ParseFromArray(model_data, model_data_len); ORT_ENFORCE(result, "Could not parse model successfully while constructing the inference session"); is_model_proto_parsed_ = true; @@ -281,6 +294,8 @@ InferenceSession::InferenceSession(const SessionOptions& session_options, const ConstructorCommon(session_options, session_env); } +#endif // !defined(ORT_MINIMAL_BUILD) + InferenceSession::~InferenceSession() { if (session_options_.enable_profiling) { try { @@ -344,6 +359,8 @@ common::Status InferenceSession::RegisterExecutionProvider(std::unique_ptr p_graph_transformer, TransformerLevel level) { if (p_graph_transformer == nullptr) { @@ -698,6 +715,8 @@ common::Status InferenceSession::TransformGraph(onnxruntime::Graph& graph, return common::Status::OK(); } +#endif // !defined(ORT_MINIMAL_BUILD) + bool InferenceSession::IsInitialized() const { std::lock_guard l(session_mutex_); return is_inited_; @@ -822,6 +841,8 @@ common::Status InferenceSession::Initialize() { // Register 2nd registries into KernelRegistryManager. ORT_RETURN_IF_ERROR_SESSIONID_(kernel_registry_manager_.RegisterKernels(execution_providers_)); +#if !defined(ORT_MINIMAL_BUILD) + // add predefined transformers AddPredefinedTransformers(graph_transformation_mgr_, session_options_.graph_optimization_level, transformers_to_enable_); @@ -833,6 +854,7 @@ common::Status InferenceSession::Initialize() { // now that all the transforms are done, call Resolve on the main graph. this will recurse into the subgraphs. ORT_RETURN_IF_ERROR_SESSIONID_(graph.Resolve()); +#endif // !defined(ORT_MINIMAL_BUILD) // need to keep the initializers if we're going to save the optimized model bool keep_initializers = !session_options_.optimized_model_filepath.empty(); @@ -841,6 +863,7 @@ common::Status InferenceSession::Initialize() { session_options_, !keep_initializers)); +#if !defined(ORT_MINIMAL_BUILD) if (!session_options_.optimized_model_filepath.empty()) { // Serialize optimized ONNX model. ORT_RETURN_IF_ERROR_SESSIONID_(Model::Save(*model_, session_options_.optimized_model_filepath)); @@ -852,6 +875,7 @@ common::Status InferenceSession::Initialize() { " the model was optimized for."; } } +#endif // !defined(ORT_MINIMAL_BUILD) session_state_->ResolveMemoryPatternFlag(); is_inited_ = true; @@ -1125,9 +1149,12 @@ Status InferenceSession::Run(const RunOptions& run_options, ORT_CHECK_AND_SET_RETVAL(start_func()); } +#if !defined(ORT_MINIMAL_BUILD) if (run_options.only_execute_path_to_fetches) { session_state_->UpdateToBeExecutedNodes(feeds_fetches_manager.GetFeedsFetchesInfo().fetches_mlvalue_idxs); } +#endif + // execute the graph ORT_CHECK_AND_SET_RETVAL(utils::ExecuteGraph(*session_state_, feeds_fetches_manager, feeds, *p_fetches, session_options_.execution_mode, run_options.terminate, run_logger, @@ -1312,12 +1339,14 @@ AllocatorPtr InferenceSession::GetAllocator(const OrtMemoryInfo& mem_info) const return session_state_->GetAllocator(mem_info); } +#if !defined(ORT_MINIMAL_BUILD) // assumes model has already been loaded before common::Status InferenceSession::DoPostLoadProcessing(onnxruntime::Model& model) { // TODO add other post load processing here common::Status status = SaveModelMetadata(model); return status; } +#endif common::Status InferenceSession::SaveModelMetadata(const onnxruntime::Model& model) { VLOGS(*session_logger_, 1) << "Saving model metadata"; @@ -1435,6 +1464,8 @@ void InferenceSession::InitLogger(logging::LoggingManager* logging_manager) { } } +#if !defined(ORT_MINIMAL_BUILD) + // Registers all the predefined transformers with transformer manager void InferenceSession::AddPredefinedTransformers(GraphTransformerManager& transformer_manager, TransformerLevel graph_optimization_level, @@ -1460,6 +1491,8 @@ void InferenceSession::AddPredefinedTransformers(GraphTransformerManager& transf } } +#endif // !defined(ORT_MINIMAL_BUILD) + common::Status InferenceSession::WaitForNotification(Notification* p_executor_done, int64_t timeout_in_ms) { if (timeout_in_ms > 0) { ORT_NOT_IMPLEMENTED(__FUNCTION__, "timeout_in_ms >0 is not supported"); // TODO diff --git a/onnxruntime/core/session/inference_session.h b/onnxruntime/core/session/inference_session.h index aa8769ae2d..8035ba6358 100644 --- a/onnxruntime/core/session/inference_session.h +++ b/onnxruntime/core/session/inference_session.h @@ -110,6 +110,8 @@ class InferenceSession { explicit InferenceSession(const SessionOptions& session_options, const Environment& session_env); +#if !defined(ORT_MINIMAL_BUILD) + /** Create a new InferenceSession @param session_options Session options. @@ -150,6 +152,8 @@ class InferenceSession { const void* model_data, int model_data_len); +#endif // !defined(ORT_MINIMAL_BUILD) + virtual ~InferenceSession(); /** @@ -161,6 +165,7 @@ class InferenceSession { */ common::Status RegisterExecutionProvider(std::unique_ptr p_exec_provider) ORT_MUST_USE_RESULT; +#if !defined(ORT_MINIMAL_BUILD) /** * Register a graph transformer. If you've one to register, call this before invoking Initialize(). * Calling this API is optional. @@ -227,6 +232,8 @@ class InferenceSession { */ common::Status Load() ORT_MUST_USE_RESULT; +#endif // !defined(ORT_MINIMAL_BUILD) + /** * Initializes a previously loaded model. Initialization includes but is not * limited to graph transformations, construction of kernels, etc. @@ -328,7 +335,6 @@ class InferenceSession { * Get all the providers' options this session was initialized with. */ const ProviderOptionsMap& GetAllProviderOptions() const; - /** * Start profiling on this inference session. This simply turns on profiling events to be * recorded. A corresponding EndProfiling has to follow to write profiling data to a file. @@ -365,6 +371,7 @@ class InferenceSession { const logging::Logger* GetLogger() const { return session_logger_; }; protected: +#if !defined(ORT_MINIMAL_BUILD) /** * Load an ONNX model. * @param protobuf object corresponding to the model file. model_proto will be copied by the API. @@ -381,6 +388,26 @@ class InferenceSession { common::Status DoPostLoadProcessing(onnxruntime::Model& model) ORT_MUST_USE_RESULT; +#endif // !defined(ORT_MINIMAL_BUILD) + + bool IsInitialized() const; + + const SessionState& GetSessionState() const { + ORT_ENFORCE(session_state_ != nullptr, "Session must be initialized to create session state."); + return *session_state_; + } + + // Use these 2 threadpool methods to get access to the threadpools since they rely on + // specific flags in session options + // These methods assume that session options have been finalized before the call. + onnxruntime::concurrency::ThreadPool* GetIntraOpThreadPoolToUse() const { + return session_options_.use_per_session_threads ? thread_pool_.get() : intra_op_thread_pool_from_env_; + } + + onnxruntime::concurrency::ThreadPool* GetInterOpThreadPoolToUse() const { + return session_options_.use_per_session_threads ? inter_op_thread_pool_.get() : inter_op_thread_pool_from_env_; + } + /// convenience pointer to logger. should always be the same as session_state_.Logger(); const logging::Logger* session_logger_; @@ -403,10 +430,6 @@ class InferenceSession { void ConstructorCommon(const SessionOptions& session_options, const Environment& session_env); - bool HasLocalSchema() const { - return !custom_schema_registries_.empty(); - } - common::Status SaveModelMetadata(const onnxruntime::Model& model) ORT_MUST_USE_RESULT; // Create a Logger for a single execution if possible. Otherwise use the default logger. @@ -417,19 +440,17 @@ class InferenceSession { const logging::Logger& CreateLoggerForRun(const RunOptions& run_options, std::unique_ptr& new_run_logger); +#if !defined(ORT_MINIMAL_BUILD) common::Status Load(std::function&)> loader, const std::string& event_name) ORT_MUST_USE_RESULT; - virtual void AddPredefinedTransformers(GraphTransformerManager& transformer_manager, - TransformerLevel graph_optimization_level, - const std::vector& custom_list); - - common::Status TransformGraph(onnxruntime::Graph& graph, - const onnxruntime::GraphTransformerManager& graph_transformer_mgr, - const ExecutionProviders& providers, KernelRegistryManager& kernel_registry_manager, - const InsertCastTransformer& insert_cast_transformer, - SessionState& session_state) ORT_MUST_USE_RESULT; + template + common::Status Load(const std::basic_string& model_uri) ORT_MUST_USE_RESULT; + bool HasLocalSchema() const { + return !custom_schema_registries_.empty(); + } +#endif void InitLogger(logging::LoggingManager* logging_manager); common::Status CheckShapes(const std::string& input_name, const TensorShape& input_shape, @@ -443,20 +464,31 @@ class InferenceSession { common::Status WaitForNotification(Notification* p_executor_done, int64_t timeout_in_ms) ORT_MUST_USE_RESULT; - template - common::Status Load(const std::basic_string& model_uri) ORT_MUST_USE_RESULT; - template void StartProfiling(const std::basic_string& file_prefix); - SessionOptions session_options_; +#if !defined(ORT_MINIMAL_BUILD) + virtual void AddPredefinedTransformers(GraphTransformerManager& transformer_manager, + TransformerLevel graph_optimization_level, + const std::vector& custom_list); + + common::Status TransformGraph(onnxruntime::Graph& graph, + const onnxruntime::GraphTransformerManager& graph_transformer_mgr, + const ExecutionProviders& providers, KernelRegistryManager& kernel_registry_manager, + const InsertCastTransformer& insert_cast_transformer, + SessionState& session_state) ORT_MUST_USE_RESULT; onnxruntime::GraphTransformerManager graph_transformation_mgr_; + InsertCastTransformer insert_cast_transformer_; + // List of transformers to run. When this list is not empty only the transformers in this list // will be run regardless of the level set. // .i.e This list overrides both SessionOptions.graph_optimization_level and predefined transformers. std::vector transformers_to_enable_; +#endif + + SessionOptions session_options_; /// Logging manager if provided. logging::LoggingManager* const logging_manager_; @@ -470,26 +502,6 @@ class InferenceSession { // The list of execution providers. ExecutionProviders execution_providers_; - protected: - bool IsInitialized() const; - - const SessionState& GetSessionState() const { - ORT_ENFORCE(session_state_ != nullptr, "Session must be initialized to create session state."); - return *session_state_; - } - - // Use these 2 threadpool methods to get access to the threadpools since they rely on - // specific flags in session options - // These methods assume that session options have been finalized before the call. - onnxruntime::concurrency::ThreadPool* GetIntraOpThreadPoolToUse() const { - return session_options_.use_per_session_threads ? thread_pool_.get() : intra_op_thread_pool_from_env_; - } - - onnxruntime::concurrency::ThreadPool* GetInterOpThreadPoolToUse() const { - return session_options_.use_per_session_threads ? inter_op_thread_pool_.get() : inter_op_thread_pool_from_env_; - } - - private: // Immutable state for each op in the model. Shared by all executors. // It has a dependency on execution_providers_. std::unique_ptr session_state_; @@ -510,8 +522,15 @@ class InferenceSession { bool use_per_session_threads_; KernelRegistryManager kernel_registry_manager_; + +#if !defined(ORT_MINIMAL_BUILD) std::list> custom_schema_registries_; + //CustomRegistry objects own the corresponding KernelRegistry and OnnxRuntimeOpSchemaRegistry objects. + //So its lifetime should be same as its constituents. This vector is to extend the lifetime of the owner. + std::vector> custom_registries_; +#endif + ModelMetadata model_metadata_; std::unordered_set required_inputs_; @@ -536,11 +555,6 @@ class InferenceSession { mutable onnxruntime::OrtMutex session_mutex_; // to ensure only one thread can invoke Load/Initialize bool is_model_loaded_ = false; // GUARDED_BY(session_mutex_) bool is_inited_ = false; // GUARDED_BY(session_mutex_) - InsertCastTransformer insert_cast_transformer_; - - //CustomRegistry objects own the corresponding KernelRegistry and OnnxRuntimeOpSchemaRegistry objects. - //So its lifetime should be same as its constituents. This vector is to extend the lifetime of the owner. - std::vector> custom_registries_; #ifdef ENABLE_LANGUAGE_INTEROP_OPS InterOpDomains interop_domains_; diff --git a/onnxruntime/core/session/onnxruntime_c_api.cc b/onnxruntime/core/session/onnxruntime_c_api.cc index 8428f38a21..89660149de 100644 --- a/onnxruntime/core/session/onnxruntime_c_api.cc +++ b/onnxruntime/core/session/onnxruntime_c_api.cc @@ -403,9 +403,14 @@ ORT_STATUS_PTR LoadAndInitializeSession(_In_ const OrtEnv* /*env*/, _In_ const O Status status; if (options) { if (!options->custom_op_domains_.empty()) { +#if !defined(ORT_MINIMAL_BUILD) status = sess->AddCustomOpDomains(options->custom_op_domains_); - if (!status.IsOK()) + if (!status.IsOK()) { return ToOrtStatus(status); + } +#else + return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "Custom operator domains are not supported in this build."); +#endif } } @@ -418,11 +423,16 @@ ORT_STATUS_PTR LoadAndInitializeSession(_In_ const OrtEnv* /*env*/, _In_ const O } } +#if !defined(ORT_MINIMAL_BUILD) status = sess->Load(); if (!status.IsOK()) return ToOrtStatus(status); status = sess->Initialize(); +#else + // TODO: Add path to load from ORT format model +#endif + if (!status.IsOK()) return ToOrtStatus(status); @@ -436,19 +446,30 @@ ORT_API_STATUS_IMPL(OrtApis::CreateSession, _In_ const OrtEnv* env, _In_ const O API_IMPL_BEGIN std::unique_ptr sess; try { +#if !defined(ORT_MINIMAL_BUILD) sess = onnxruntime::make_unique( options == nullptr ? onnxruntime::SessionOptions() : options->value, env->GetEnvironment(), model_path); + + return LoadAndInitializeSession(env, options, sess, out); +#else + ORT_UNUSED_PARAMETER(env); + ORT_UNUSED_PARAMETER(model_path); + ORT_UNUSED_PARAMETER(options); + ORT_UNUSED_PARAMETER(out); + return OrtApis::CreateStatus(ORT_NOT_IMPLEMENTED, "Pending"); +#endif + } catch (const std::exception& e) { return OrtApis::CreateStatus(ORT_FAIL, e.what()); } - return LoadAndInitializeSession(env, options, sess, out); API_IMPL_END } -ORT_API_STATUS_IMPL(OrtApis::CreateSessionFromArray, _In_ const OrtEnv* env, _In_ const void* model_data, size_t model_data_length, - _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out) { +ORT_API_STATUS_IMPL(OrtApis::CreateSessionFromArray, _In_ const OrtEnv* env, _In_ const void* model_data, + size_t model_data_length, _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out) { API_IMPL_BEGIN +#if !defined(ORT_MINIMAL_BUILD) std::unique_ptr sess; try { sess = onnxruntime::make_unique( @@ -458,6 +479,14 @@ ORT_API_STATUS_IMPL(OrtApis::CreateSessionFromArray, _In_ const OrtEnv* env, _In return OrtApis::CreateStatus(ORT_FAIL, e.what()); } return LoadAndInitializeSession(env, options, sess, out); +#else + ORT_UNUSED_PARAMETER(env); + ORT_UNUSED_PARAMETER(model_data); + ORT_UNUSED_PARAMETER(model_data_length); + ORT_UNUSED_PARAMETER(options); + ORT_UNUSED_PARAMETER(out); + return OrtApis::CreateStatus(ORT_NOT_IMPLEMENTED, "Pending"); +#endif API_IMPL_END } @@ -1604,7 +1633,7 @@ ORT_API_STATUS_IMPL(OrtApis::GetAvailableProviders, _Outptr_ char*** out_ptr, out[i][MAX_LEN] = '\0'; #elif defined(__APPLE__) strlcpy(out[i], providers_available[i], MAX_LEN); -#else +#else strncpy(out[i], providers_available[i], MAX_LEN); out[i][MAX_LEN] = '\0'; #endif diff --git a/onnxruntime/test/common/tensor_op_test_utils.h b/onnxruntime/test/common/tensor_op_test_utils.h index ca824e1bea..61d3e6352b 100644 --- a/onnxruntime/test/common/tensor_op_test_utils.h +++ b/onnxruntime/test/common/tensor_op_test_utils.h @@ -10,7 +10,6 @@ #include "core/common/common.h" #include "core/util/math.h" -#include "test/providers/provider_test_utils.h" #include "test/util/include/test_random_seed.h" namespace onnxruntime { diff --git a/onnxruntime/test/common/utf8_util_test.cc b/onnxruntime/test/common/utf8_util_test.cc index 47d631f977..a6a9886f82 100644 --- a/onnxruntime/test/common/utf8_util_test.cc +++ b/onnxruntime/test/common/utf8_util_test.cc @@ -3,7 +3,6 @@ #include "core/common/utf8_util.h" #include "gtest/gtest.h" -#include "test/providers/provider_test_utils.h" namespace onnxruntime { namespace test { diff --git a/onnxruntime/test/contrib_ops/tensor_op_test.cc b/onnxruntime/test/contrib_ops/tensor_op_test.cc index 594801cab5..2d4c836782 100644 --- a/onnxruntime/test/contrib_ops/tensor_op_test.cc +++ b/onnxruntime/test/contrib_ops/tensor_op_test.cc @@ -2,8 +2,9 @@ // Licensed under the MIT License. #include "gtest/gtest.h" -#include "test/common/tensor_op_test_utils.h" #include "contrib_ops/cpu/crop.h" +#include "test/common/tensor_op_test_utils.h" +#include "test/providers/provider_test_utils.h" using namespace ONNX_NAMESPACE; using namespace onnxruntime::test; diff --git a/onnxruntime/test/providers/cpu/tensor/tensor_op_test.cc b/onnxruntime/test/providers/cpu/tensor/tensor_op_test.cc index d4619b60b8..2a09fd4a26 100644 --- a/onnxruntime/test/providers/cpu/tensor/tensor_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/tensor_op_test.cc @@ -2,9 +2,9 @@ // Licensed under the MIT License. #include "gtest/gtest.h" +#include "test/providers/provider_test_utils.h" #include "test/common/tensor_op_test_utils.h" - using namespace ONNX_NAMESPACE; namespace onnxruntime { namespace test { @@ -30,7 +30,7 @@ TEST(TensorOpTest, ReshapeWithEmptyDim) { test.AddInput("data", {1, 1, 1}, std::vector(1, 1.0f)); test.AddInput("shape", {0}, {}, true); test.AddOutput("reshaped", {}, std::vector(1, 1.0f)); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // TensorRT doesn't support empty dimension + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // TensorRT doesn't support empty dimension } TEST(TensorOpTest, ReshapeWithEmptyInput) { @@ -38,7 +38,7 @@ TEST(TensorOpTest, ReshapeWithEmptyInput) { test.AddInput("data", {0, 10}, std::vector()); test.AddInput("shape", {3}, {0, 10, 1}, false); test.AddOutput("reshaped", {0, 10, 1}, std::vector()); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // TensorRT doesn't support empty dimension + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // TensorRT doesn't support empty dimension } TEST(TensorOpTest, ReshapeWithEmptyInputAndDynamicShape) { @@ -47,7 +47,7 @@ TEST(TensorOpTest, ReshapeWithEmptyInputAndDynamicShape) { test.AddInput("data", {1, 0}, std::vector()); test.AddInput("shape", {3}, {1, 0, -1}, false); test.AddOutput("reshaped", {1, 0, 1}, {}); - test.Run(OpTester::ExpectResult::kExpectFailure, "The input tensor cannot be reshaped to the requested shape", {kTensorrtExecutionProvider}); // TensorRT doesn't support empty dimension + test.Run(OpTester::ExpectResult::kExpectFailure, "The input tensor cannot be reshaped to the requested shape", {kTensorrtExecutionProvider}); // TensorRT doesn't support empty dimension } { @@ -55,7 +55,7 @@ TEST(TensorOpTest, ReshapeWithEmptyInputAndDynamicShape) { test.AddInput("data", {1, 0}, std::vector()); test.AddInput("shape", {3}, {1, 1, -1}, false); test.AddOutput("reshaped", {1, 1, 0}, {}); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // TensorRT doesn't support empty dimension + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // TensorRT doesn't support empty dimension } }