diff --git a/onnxruntime/core/providers/shared_library/provider_api.h b/onnxruntime/core/providers/shared_library/provider_api.h index 2f54a04e15..0bfa52e786 100644 --- a/onnxruntime/core/providers/shared_library/provider_api.h +++ b/onnxruntime/core/providers/shared_library/provider_api.h @@ -123,6 +123,7 @@ struct ValueInfoProto; struct ValueInfoProtos; // RepeatedPtrField struct FunctionProto; struct InferenceContext; +struct OpSchema; class GraphInferencer; using InferenceFunction = std::function; } // namespace ONNX_NAMESPACE diff --git a/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc b/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc index 252ce9298b..d3b12f9728 100644 --- a/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc +++ b/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc @@ -174,6 +174,7 @@ MLDataType DataTypeImpl::GetType() { return Provider_GetHost()->DataTyp template <> MLDataType DataTypeImpl::GetType() { return Provider_GetHost()->DataTypeImpl__GetType_string(); } +MLDataType DataTypeImpl::GetTensorTypeFromOnnxType(int onnx_type) { return Provider_GetHost()->DataTypeImpl__GetTensorTypeFromOnnxType(onnx_type); } template <> MLDataType DataTypeImpl::GetTensorType() { return Provider_GetHost()->DataTypeImpl__GetTensorType_bool(); } template <> diff --git a/onnxruntime/core/providers/shared_library/provider_interfaces.h b/onnxruntime/core/providers/shared_library/provider_interfaces.h index 4527c0a893..1059443469 100644 --- a/onnxruntime/core/providers/shared_library/provider_interfaces.h +++ b/onnxruntime/core/providers/shared_library/provider_interfaces.h @@ -27,6 +27,8 @@ enum OperatorStatus : int; // String pointer as unique TypeProto identifier. using DataType = const std::string*; +using DataTypeSet = std::unordered_set; +using TypeConstraintMap = std::unordered_map>; } // namespace ONNX_NAMESPACE @@ -566,6 +568,12 @@ struct ProviderHost { virtual ONNX_NAMESPACE::StringStringEntryProto* FunctionProto__add_metadata_props(ONNX_NAMESPACE::FunctionProto* p) = 0; virtual void RegisterSchema(const std::string& domain, const OrtCustomOp* op, int type) = 0; + virtual const ONNX_NAMESPACE::OpSchema* GetSchema(const std::string& name, const int maxInclusiveVersion, const std::string& domain) = 0; + virtual const std::string& OpSchema__inputs__GetName(const ONNX_NAMESPACE::OpSchema* p, const size_t i) = 0; + virtual const std::string& OpSchema__inputs__GetTypeStr(const ONNX_NAMESPACE::OpSchema* p, const size_t i) = 0; + virtual const std::string& OpSchema__outputs__GetName(const ONNX_NAMESPACE::OpSchema* p, const size_t i) = 0; + virtual const std::string& OpSchema__outputs__GetTypeStr(const ONNX_NAMESPACE::OpSchema* p, const size_t i) = 0; + virtual const ONNX_NAMESPACE::TypeConstraintMap& OpSchema__typeConstraintMap(const ONNX_NAMESPACE::OpSchema* p) const = 0; // ConfigOptions virtual std::optional ConfigOptions__GetConfigEntry(const ConfigOptions* p, const std::string& config_key) = 0; @@ -694,6 +702,7 @@ struct ProviderHost { virtual MLDataType DataTypeImpl__GetType_Int4x2() = 0; virtual MLDataType DataTypeImpl__GetType_UInt4x2() = 0; + virtual MLDataType DataTypeImpl__GetTensorTypeFromOnnxType(int) = 0; virtual MLDataType DataTypeImpl__GetTensorType_bool() = 0; virtual MLDataType DataTypeImpl__GetTensorType_int8() = 0; virtual MLDataType DataTypeImpl__GetTensorType_uint8() = 0; diff --git a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h index d98d91759b..a0bc73a478 100644 --- a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h +++ b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h @@ -451,6 +451,15 @@ struct FunctionProto final { FunctionProto(const FunctionProto&) = delete; void operator=(const FunctionProto&) = delete; }; + +struct OpSchema final { + const TypeConstraintMap& typeConstraintMap() const { return g_host->OpSchema__typeConstraintMap(this); } + const std::string& inputs__GetName(const size_t i) const { return g_host->OpSchema__inputs__GetName(this, i); }; + const std::string& inputs__GetTypeStr(const size_t i) const { return g_host->OpSchema__inputs__GetTypeStr(this, i); }; + const std::string& outputs__GetName(const size_t i) const { return g_host->OpSchema__outputs__GetName(this, i); }; + const std::string& outputs__GetTypeStr(const size_t i) const { return g_host->OpSchema__outputs__GetTypeStr(this, i); }; + PROVIDER_DISALLOW_ALL(OpSchema) +}; } // namespace ONNX_NAMESPACE namespace onnxruntime { @@ -702,6 +711,7 @@ class DataTypeImpl final { #endif static MLDataType GetTypeFromOnnxType(int); + static MLDataType GetTensorTypeFromOnnxType(int); bool IsTensorType() const { return g_host->DataTypeImpl__IsTensorType(this); } bool IsTensorSequenceType() const { return g_host->DataTypeImpl__IsTensorSequenceType(this); } diff --git a/onnxruntime/core/providers/vitisai/imp/capability.cc b/onnxruntime/core/providers/vitisai/imp/capability.cc index 6d188076fe..f2cefe9dff 100644 --- a/onnxruntime/core/providers/vitisai/imp/capability.cc +++ b/onnxruntime/core/providers/vitisai/imp/capability.cc @@ -42,7 +42,7 @@ std::unique_ptr XirSubgraphToComputeCapability1(const onnxrun std::vector> GetComputeCapabilityOps(const onnxruntime::GraphViewer& graph, vaip_core::DllSafe>>* eps, - const std::set& all_support_optypes_by_eps) { + const onnxruntime::IExecutionProvider::IKernelLookup& kernel_lookup) { std::set all_nodes_included_eps; for (auto& ep : **eps) { auto nodes = node_names_to_nodes(graph, *ep->get_meta_def_nodes()); @@ -52,11 +52,8 @@ GetComputeCapabilityOps(const onnxruntime::GraphViewer& graph, std::vector node_indexs = graph.GetNodesInTopologicalOrder(); node_indexs.erase(std::remove_if(node_indexs.begin(), node_indexs.end(), [&](NodeIndex index) { return all_nodes_included_eps.count(index) > 0; }), node_indexs.end()); node_indexs.erase(std::remove_if(node_indexs.begin(), node_indexs.end(), - [&](NodeIndex index) { - auto node = graph.GetNode(index); - return all_support_optypes_by_eps.count(node->Domain() + ":" + node->OpType()) == 0; }), + [&](NodeIndex index) { return kernel_lookup.LookUpKernel(*graph.GetNode(index)) == nullptr; }), node_indexs.end()); - std::vector> result; for (auto& n : node_indexs) { auto indexed_subgraph = IndexedSubGraph::Create(); diff --git a/onnxruntime/core/providers/vitisai/imp/global_api.cc b/onnxruntime/core/providers/vitisai/imp/global_api.cc index d4125fcc09..e5610f9464 100644 --- a/onnxruntime/core/providers/vitisai/imp/global_api.cc +++ b/onnxruntime/core/providers/vitisai/imp/global_api.cc @@ -133,17 +133,46 @@ void create_kernel_registry(std::vector domains) { s_kernel_registry_vitisaiep = KernelRegistry::Create(); for (const auto& domain : domains) { for (const auto* op : domain->custom_ops_) { + const size_t input_count = op->GetInputTypeCount(op); + const size_t output_count = op->GetOutputTypeCount(op); auto def_builder = KernelDefBuilder::Create(); def_builder->SetName(op->GetName(op)); def_builder->SetDomain(domain->domain_.c_str()); def_builder->SinceVersion(op->GetStartVersion(op), op->GetEndVersion(op)); if (op->version > 12) { - auto input_count = op->GetInputTypeCount(op); for (auto i = 0u; i < input_count; i++) { def_builder->InputMemoryType(op->GetInputMemoryType(op, i), i); } } - def_builder->Provider(onnxruntime::kVitisAIExecutionProvider); + def_builder->Provider(op->GetExecutionProviderType(op)); + + auto schema = Provider_GetHost()->GetSchema(op->GetName(op), op->GetStartVersion(op), domain->domain_); + for (size_t i = 0; i < input_count; i++) { + const auto input_type = op->GetInputType(op, i); + auto input_name = schema->inputs__GetName(i); + if (schema->typeConstraintMap().count(schema->inputs__GetTypeStr(i))) { + input_name = schema->inputs__GetTypeStr(i); + } + if (input_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED) { + def_builder->TypeConstraint(input_name.c_str(), DataTypeImpl::AllTensorTypes()); + } else { + def_builder->TypeConstraint(input_name.c_str(), DataTypeImpl::GetTensorTypeFromOnnxType(input_type)); + } + } + for (size_t i = 0; i < output_count; i++) { + const auto output_type = op->GetOutputType(op, i); + auto output_name = schema->outputs__GetName(i); + if (schema != nullptr) { + if (schema->typeConstraintMap().count(schema->outputs__GetTypeStr(i))) { + output_name = schema->outputs__GetTypeStr(i); + } + } + if (output_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED) { + def_builder->TypeConstraint(output_name.c_str(), DataTypeImpl::AllTensorTypes()); + } else { + def_builder->TypeConstraint(output_name.c_str(), DataTypeImpl::GetTensorTypeFromOnnxType(output_type)); + } + } KernelCreateFn kernel_create_fn = [op](FuncManager&, const OpKernelInfo& info, std::unique_ptr& out) -> Status { out = std::make_unique(info, *op); diff --git a/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc b/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc index 97ed2d3b4b..03458f42d5 100644 --- a/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc +++ b/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc @@ -12,13 +12,15 @@ namespace vaip { void register_xir_ops(const std::vector& domains) { for (auto domain : domains) { for (auto op : domain->custom_ops_) { - auto name = op->GetName(op); - if ((std::string)name == "super_layer") { - Provider_GetHost()->RegisterSchema(domain->domain_, op, 1); - } else if ((std::string)name == "FixNeuron") { - Provider_GetHost()->RegisterSchema(domain->domain_, op, 2); - } else { - Provider_GetHost()->RegisterSchema(domain->domain_, op, 3); + if (Provider_GetHost()->GetSchema(op->GetName(op), op->GetStartVersion(op), domain->domain_) == nullptr) { + auto name = op->GetName(op); + if ((std::string)name == "super_layer") { + Provider_GetHost()->RegisterSchema(domain->domain_, op, 1); + } else if ((std::string)name == "FixNeuron") { + Provider_GetHost()->RegisterSchema(domain->domain_, op, 2); + } else { + Provider_GetHost()->RegisterSchema(domain->domain_, op, 3); + } } } } diff --git a/onnxruntime/core/providers/vitisai/include/vaip/capability.h b/onnxruntime/core/providers/vitisai/include/vaip/capability.h index e7644dbe86..9e37dc5279 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/capability.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/capability.h @@ -8,6 +8,6 @@ namespace vaip { using namespace ::onnxruntime; std::unique_ptr XirSubgraphToComputeCapability1(const onnxruntime::GraphViewer& graph, vaip_core::ExecutionProvider* ep, size_t index); std::vector> GetComputeCapabilityOps(const onnxruntime::GraphViewer& graph, - vaip_core::DllSafe>>* ep, const std::set& all_not_support_optypes); + vaip_core::DllSafe>>* ep, const onnxruntime::IExecutionProvider::IKernelLookup& kernel_lookup); } // namespace vaip diff --git a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc index 4c21f39511..57c3e21b70 100644 --- a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc +++ b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc @@ -25,8 +25,6 @@ constexpr const char* VITISAI = "VITISAI"; VitisAIExecutionProvider::VitisAIExecutionProvider( const ProviderOptions& info) : IExecutionProvider{onnxruntime::kVitisAIExecutionProvider}, info_(info) { - CreateKernelRegistry(); - auto it = info_.find("ep_context_enable"); ep_ctx_enabled_ = it != info_.end() && it->second == "1"; it = info_.find("ep_context_embed_mode"); @@ -39,14 +37,6 @@ VitisAIExecutionProvider::VitisAIExecutionProvider( LOGS_DEFAULT(VERBOSE) << "User specified EP context cache path: " << ep_ctx_model_path_cfg_; } -void VitisAIExecutionProvider::CreateKernelRegistry() { - for (const auto& domain : get_domains_vitisaiep()) { - for (const auto* op : domain->custom_ops_) { - vitisai_optypes_.insert(domain->domain_ + ":" + op->GetName(op)); - } - } -} - std::shared_ptr VitisAIExecutionProvider::GetKernelRegistry() const { return get_kernel_registry_vitisaiep(); } // This method is called after both `GetComputeCapabilityOps()` and `Compile()`. @@ -60,7 +50,7 @@ const InlinedVector VitisAIExecutionProvider::GetEpContextNodes() c return ep_context_node_ptrs; } std::vector> VitisAIExecutionProvider::GetCapability( - const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/) const { + const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& kernel_lookup) const { if (graph_viewer.IsSubgraph()) { // VITIS AI EP not support sungraph. Assigned to CPU. return {}; @@ -70,7 +60,7 @@ std::vector> VitisAIExecutionProvider::GetCap return {}; } execution_providers_ = std::make_unique(compile_onnx_model(graph_viewer, *GetLogger(), info_)); - auto result = vaip::GetComputeCapabilityOps(graph_viewer, execution_providers_.get(), vitisai_optypes_); + auto result = vaip::GetComputeCapabilityOps(graph_viewer, execution_providers_.get(), kernel_lookup); size_t index = 0u; for (auto& ep : **execution_providers_) { result.emplace_back(vaip::XirSubgraphToComputeCapability1(graph_viewer, ep.get(), index)); diff --git a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h index cca647abe0..24692dd45c 100644 --- a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h +++ b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h @@ -41,7 +41,6 @@ class VitisAIExecutionProvider : public IExecutionProvider { const InlinedVector GetEpContextNodes() const override; private: - void CreateKernelRegistry(); using my_ep_t = vaip_core::DllSafe>>; using my_ep_uptr_t = std::shared_ptr; // we have to hide the implementation by forward declaration. diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index ff841950b4..dc5b983f86 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -813,6 +813,14 @@ struct ProviderHostImpl : ProviderHost { } ONNX_NAMESPACE::RegisterSchema(schema, ORT_API_VERSION); } + const ONNX_NAMESPACE::OpSchema* GetSchema(const std::string& name, const int maxInclusiveVersion, const std::string& domain) override { + return ONNX_NAMESPACE::OpSchemaRegistry::Instance()->GetSchema(name, maxInclusiveVersion, domain); + } + const std::string& OpSchema__inputs__GetName(const ONNX_NAMESPACE::OpSchema* p, const size_t i) override { return p->inputs()[i].GetName(); } + const std::string& OpSchema__inputs__GetTypeStr(const ONNX_NAMESPACE::OpSchema* p, const size_t i) override { return p->inputs()[i].GetTypeStr(); } + const std::string& OpSchema__outputs__GetName(const ONNX_NAMESPACE::OpSchema* p, const size_t i) override { return p->outputs()[i].GetName(); } + const std::string& OpSchema__outputs__GetTypeStr(const ONNX_NAMESPACE::OpSchema* p, const size_t i) override { return p->outputs()[i].GetTypeStr(); } + const ONNX_NAMESPACE::TypeConstraintMap& OpSchema__typeConstraintMap(const ONNX_NAMESPACE::OpSchema* p) const override { return p->typeConstraintMap(); } // ConfigOptions (wrapped) std::optional ConfigOptions__GetConfigEntry(const ConfigOptions* p, const std::string& config_key) override { @@ -946,6 +954,7 @@ struct ProviderHostImpl : ProviderHost { MLDataType DataTypeImpl__GetType_Int4x2() override { return DataTypeImpl::GetType(); } MLDataType DataTypeImpl__GetType_UInt4x2() override { return DataTypeImpl::GetType(); } + MLDataType DataTypeImpl__GetTensorTypeFromOnnxType(int onnx_type) override { return DataTypeImpl::TensorTypeFromONNXEnum(onnx_type)->AsTensorType(); } MLDataType DataTypeImpl__GetTensorType_bool() override { return DataTypeImpl::GetTensorType(); } MLDataType DataTypeImpl__GetTensorType_int8() override { return DataTypeImpl::GetTensorType(); } MLDataType DataTypeImpl__GetTensorType_uint8() override { return DataTypeImpl::GetTensorType(); }