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