Skip to content

Commit

Permalink
[VitisAI] 1. api compatbile 2. dynamic load onnx (#18470)
Browse files Browse the repository at this point in the history
### Description
<!-- Describe your changes. -->

1. Add a backward-compatible API for compiling model.
2. Run-time load vitisai-ep.dll


### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->

---------

Co-authored-by: Yueqing Zhang <[email protected]>
Co-authored-by: Zhenze Wang <[email protected]>
  • Loading branch information
3 people authored Dec 14, 2023
1 parent 6d5ee4d commit b42d4b8
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 293 deletions.
10 changes: 2 additions & 8 deletions cmake/onnxruntime_providers_vitisai.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,10 @@
"${ONNXRUNTIME_ROOT}/core/providers/vitisai/imp/*.cc"
"${ONNXRUNTIME_ROOT}/core/providers/vitisai/imp/*.h"
)
list(REMOVE_ITEM onnxruntime_providers_vitisai_cc_srcs "${ONNXRUNTIME_ROOT}/core/providers/vitisai/onnxruntime_vitisai_ep_stub.cc")
source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_vitisai_cc_srcs})
onnxruntime_add_static_library(onnxruntime_providers_vitisai ${onnxruntime_providers_vitisai_cc_srcs})
onnxruntime_add_include_to_target(onnxruntime_providers_vitisai onnxruntime_common onnxruntime_framework onnx onnx_proto)
onnxruntime_add_shared_library(onnxruntime_vitisai_ep ${ONNXRUNTIME_ROOT}/core/providers/vitisai/onnxruntime_vitisai_ep_stub.cc)
onnxruntime_add_include_to_target(onnxruntime_vitisai_ep onnxruntime_common)
target_include_directories(onnxruntime_vitisai_ep PRIVATE "${ONNXRUNTIME_ROOT}" "${ONNXRUNTIME_ROOT}/core/providers/vitisai/include")
target_link_libraries(onnxruntime_providers_vitisai PUBLIC onnxruntime_vitisai_ep PRIVATE onnx protobuf::libprotobuf nlohmann_json::nlohmann_json )
target_compile_definitions(onnxruntime_vitisai_ep
PRIVATE "-DONNXRUNTIME_VITISAI_EP_STUB=1" "-DONNXRUNTIME_VITISAI_EP_EXPORT_DLL=1")
target_link_libraries(onnxruntime_providers_vitisai PRIVATE onnx protobuf::libprotobuf nlohmann_json::nlohmann_json)
if(NOT MSVC)
target_compile_options(onnxruntime_providers_vitisai PUBLIC $<$<CONFIG:DEBUG>:-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0>)
endif(NOT MSVC)
Expand All @@ -49,4 +43,4 @@
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
endif()
270 changes: 151 additions & 119 deletions onnxruntime/core/providers/vitisai/imp/global_api.cc

Large diffs are not rendered by default.

This file was deleted.

10 changes: 10 additions & 0 deletions onnxruntime/core/providers/vitisai/include/vaip/global_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include <vector>
#include <memory>
#include <string>

#include "core/session/onnxruntime_cxx_api.h"
#include "core/framework/provider_options.h"
#include "vaip/my_ort.h"
#include "vaip/dll_safe.h"
#include "vaip/custom_op.h"

std::vector<OrtCustomOpDomain*> initialize_vitisai_ep();
vaip_core::DllSafe<std::vector<std::unique_ptr<vaip_core::ExecutionProvider>>> compile_onnx_model_with_options(
const std::string& model_path, const onnxruntime::Graph& graph, const onnxruntime::ProviderOptions& options);
30 changes: 0 additions & 30 deletions onnxruntime/core/providers/vitisai/onnxruntime_vitisai_ep_stub.cc

This file was deleted.

45 changes: 17 additions & 28 deletions onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,28 @@
#include "core/session/custom_ops.h"
#include "core/session/inference_session.h"

#include "onnxruntime_vitisai_ep/onnxruntime_vitisai_ep.h"

using namespace ONNX_NAMESPACE;

namespace onnxruntime {

constexpr const char* VITISAI = "VITISAI";

static vaip_core::DllSafe<std::vector<std::unique_ptr<vaip_core::ExecutionProvider>>> compile_onnx_model(
const onnxruntime::GraphViewer& graph_viewer,
const logging::Logger& logger, const char* json_config) {
const onnxruntime::GraphViewer& graph_viewer, const logging::Logger& logger, const ProviderOptions& options) {
#ifndef _WIN32
auto model_path = graph_viewer.ModelPath().ToPathString();
#else
using convert_t = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_t, wchar_t> strconverter;
auto model_path = strconverter.to_bytes(graph_viewer.ModelPath().ToPathString());
#endif
return onnxruntime_vitisai_ep::compile_onnx_model_3(model_path, graph_viewer.GetGraph(), json_config);
return compile_onnx_model_with_options(model_path, graph_viewer.GetGraph(), options);
}

struct MyCustomOpKernel : OpKernel {
MyCustomOpKernel(const OpKernelInfo& info, const OrtCustomOp& op) : OpKernel(info), op_(op) {
op_kernel_ = op_.CreateKernel(&op_, OrtGetApiBase()->GetApi(op_.version),
reinterpret_cast<const OrtKernelInfo*>(&info));
op_kernel_ =
op_.CreateKernel(&op_, OrtGetApiBase()->GetApi(op_.version), reinterpret_cast<const OrtKernelInfo*>(&info));
}

~MyCustomOpKernel() override { op_.KernelDestroy(op_kernel_); }
Expand All @@ -55,8 +53,7 @@ struct MyCustomOpKernel : OpKernel {
void* op_kernel_;
};

VitisAIExecutionProvider::VitisAIExecutionProvider(
const VitisAIExecutionProviderInfo& info)
VitisAIExecutionProvider::VitisAIExecutionProvider(const ProviderOptions& info)
: IExecutionProvider{onnxruntime::kVitisAIExecutionProvider}, info_(info) {
custom_op_domains_ = initialize_vitisai_ep();
registry_ = std::make_shared<KernelRegistry>();
Expand All @@ -77,7 +74,8 @@ void VitisAIExecutionProvider::CreateKernelRegistry() {
}
}
def_builder.Provider(onnxruntime::kVitisAIExecutionProvider);
KernelCreateFn kernel_create_fn = [op](FuncManager&, const OpKernelInfo& info, std::unique_ptr<OpKernel>& out) -> Status {
KernelCreateFn kernel_create_fn = [op](FuncManager&, const OpKernelInfo& info,
std::unique_ptr<OpKernel>& out) -> Status {
out = std::make_unique<MyCustomOpKernel>(info, *op);
return Status::OK();
};
Expand All @@ -89,9 +87,8 @@ void VitisAIExecutionProvider::CreateKernelRegistry() {

std::shared_ptr<KernelRegistry> VitisAIExecutionProvider::GetKernelRegistry() const { return registry_; }

std::vector<std::unique_ptr<ComputeCapability>>
VitisAIExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph,
const IKernelLookup& /*kernel_lookup*/) const {
std::vector<std::unique_ptr<ComputeCapability>> VitisAIExecutionProvider::GetCapability(
const onnxruntime::GraphViewer& graph, const IKernelLookup& /*kernel_lookup*/) const {
if (graph.IsSubgraph()) {
// VITIS AI EP not support sungraph. Assigned to CPU.
return {};
Expand All @@ -100,9 +97,7 @@ VitisAIExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph,
// Only compiling a model once is currently supported
return {};
}
auto opt_str = info_.get_json_config_str(); // String
execution_providers_ =
std::make_unique<my_ep_t>(compile_onnx_model(graph, *GetLogger(), opt_str));
execution_providers_ = std::make_unique<my_ep_t>(compile_onnx_model(graph, *GetLogger(), info_));
auto result = vaip::GetComputeCapabilityOps(graph, execution_providers_.get(), vitisai_optypes_);
size_t index = 0u;
for (auto& ep : **execution_providers_) {
Expand All @@ -112,32 +107,26 @@ VitisAIExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph,
return result;
}

common::Status VitisAIExecutionProvider::Compile(
const std::vector<FusedNodeAndGraph>& fused_nodes_and_graphs,
std::vector<NodeComputeInfo>& node_compute_funcs) {
common::Status VitisAIExecutionProvider::Compile(const std::vector<FusedNodeAndGraph>& fused_nodes_and_graphs,
std::vector<NodeComputeInfo>& node_compute_funcs) {
for (const auto& fused_node_graph : fused_nodes_and_graphs) {
NodeComputeInfo compute_info;
const onnx::AttributeProto* attr = graph_utils::GetNodeAttribute(fused_node_graph.fused_node, "index");
assert(attr != nullptr);
size_t index = (size_t)attr->i();
compute_info.create_state_func = [this, index](ComputeContext* context,
FunctionState* state) {
compute_info.create_state_func = [this, index](ComputeContext* context, FunctionState* state) {
auto* p = (**this->execution_providers_)[index]->compile().release();
*state = p;
return 0;
};

compute_info.release_state_func = [](FunctionState state) {
if (state) {
delete reinterpret_cast<vaip_core::CustomOp*>(
state);
delete reinterpret_cast<vaip_core::CustomOp*>(state);
}
};
compute_info.compute_func = [](FunctionState state, const OrtApi* api,
OrtKernelContext* context) {
reinterpret_cast<vaip_core::CustomOp*>(
state)
->Compute(api, context);
compute_info.compute_func = [](FunctionState state, const OrtApi* api, OrtKernelContext* context) {
reinterpret_cast<vaip_core::CustomOp*>(state)->Compute(api, context);
return Status::OK();
};
node_compute_funcs.push_back(compute_info);
Expand Down
31 changes: 10 additions & 21 deletions onnxruntime/core/providers/vitisai/vitisai_execution_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#pragma once

#include <ctime>
#include <vector>
#include <memory>
#include <set>
#include <string>

#include "core/framework/execution_provider.h"
#include "core/framework/customregistry.h"
Expand All @@ -18,34 +22,19 @@ class ExecutionProvider;
} // namespace vaip_core
namespace onnxruntime {

// Information needed to construct execution providers.
struct VitisAIExecutionProviderInfo {
VitisAIExecutionProviderInfo(const ProviderOptions& provider_options);

const char* get_json_config_str() const {
return json_config_.c_str();
}

private:
ProviderOptions provider_options_;
const std::string json_config_;
};

// Logical device representation.
class VitisAIExecutionProvider : public IExecutionProvider {
public:
explicit VitisAIExecutionProvider(const VitisAIExecutionProviderInfo& info);
explicit VitisAIExecutionProvider(const ProviderOptions& info);
~VitisAIExecutionProvider() = default;

std::vector<std::unique_ptr<ComputeCapability>>
GetCapability(const onnxruntime::GraphViewer& graph,
const IKernelLookup& /*kernel_lookup*/) const override;
std::vector<std::unique_ptr<ComputeCapability>> GetCapability(const onnxruntime::GraphViewer& graph,
const IKernelLookup& /*kernel_lookup*/) const override;

int GetDeviceId() const { return 0; }

common::Status Compile(
const std::vector<FusedNodeAndGraph>& fused_nodes_and_graphs,
std::vector<NodeComputeInfo>& node_compute_funcs) override;
common::Status Compile(const std::vector<FusedNodeAndGraph>& fused_nodes_and_graphs,
std::vector<NodeComputeInfo>& node_compute_funcs) override;
std::shared_ptr<KernelRegistry> GetKernelRegistry() const override;

private:
Expand All @@ -54,7 +43,7 @@ class VitisAIExecutionProvider : public IExecutionProvider {
using my_ep_uptr_t = std::shared_ptr<my_ep_t>;
// we have to hide the implementation by forward declaration.
mutable my_ep_uptr_t execution_providers_;
VitisAIExecutionProviderInfo info_;
ProviderOptions info_;
std::vector<OrtCustomOpDomain*> custom_op_domains_;
std::shared_ptr<KernelRegistry> registry_;
std::set<std::string> vitisai_optypes_;
Expand Down
37 changes: 9 additions & 28 deletions onnxruntime/core/providers/vitisai/vitisai_provider_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,37 @@

#include "vitisai_provider_factory_creator.h"

#include <unordered_map>
#include <string>

#include "vaip/global_api.h"
#include "./vitisai_execution_provider.h"
#include "core/framework/execution_provider.h"

#include "core/session/abi_session_options_impl.h"
#include "nlohmann/json.hpp"
#include <fstream>
#include <unordered_map>
#include <string>
#include "core/providers/shared_library/provider_host_api.h"

using namespace onnxruntime;
using json = nlohmann::json;
namespace onnxruntime {

static std::string ConfigToJsonStr(const std::unordered_map<std::string, std::string>& config) {
const auto& filename = config.at("config_file");
std::ifstream f(filename);
json data = json::parse(f);
for (const auto& entry : config) {
data[entry.first] = entry.second;
}
return data.dump();
}

VitisAIExecutionProviderInfo::VitisAIExecutionProviderInfo(const ProviderOptions& provider_options) : provider_options_(provider_options), json_config_{ConfigToJsonStr(provider_options)} {}

struct VitisAIProviderFactory : IExecutionProviderFactory {
VitisAIProviderFactory(const VitisAIExecutionProviderInfo& info) : info_(info) {}
VitisAIProviderFactory(const ProviderOptions& info) : info_(info) {}

Check warning on line 20 in onnxruntime/core/providers/vitisai/vitisai_provider_factory.cc

View workflow job for this annotation

GitHub Actions / cpplint

[cpplint] onnxruntime/core/providers/vitisai/vitisai_provider_factory.cc#L20

Single-parameter constructors should be marked explicit. [runtime/explicit] [5]
Raw output
onnxruntime/core/providers/vitisai/vitisai_provider_factory.cc:20:  Single-parameter constructors should be marked explicit.  [runtime/explicit] [5]
~VitisAIProviderFactory() = default;

std::unique_ptr<IExecutionProvider> CreateProvider() override;

private:
VitisAIExecutionProviderInfo info_;
ProviderOptions info_;
};

std::unique_ptr<IExecutionProvider> VitisAIProviderFactory::CreateProvider() {
return std::make_unique<VitisAIExecutionProvider>(info_);
}

std::shared_ptr<IExecutionProviderFactory>
CreateExecutionProviderFactory_VITISAI(const VitisAIExecutionProviderInfo& info) {
initialize_vitisai_ep();
return std::make_shared<VitisAIProviderFactory>(info);
}

std::shared_ptr<IExecutionProviderFactory> VitisAIProviderFactoryCreator::Create(const ProviderOptions& provider_options) {
std::shared_ptr<IExecutionProviderFactory> VitisAIProviderFactoryCreator::Create(
const ProviderOptions& provider_options) {
initialize_vitisai_ep();
auto info = VitisAIExecutionProviderInfo{provider_options};
return std::make_shared<VitisAIProviderFactory>(info);
return std::make_shared<VitisAIProviderFactory>(provider_options);
}

} // namespace onnxruntime
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
#include "core/framework/provider_options.h"

namespace onnxruntime {

struct VitisAIExecutionProviderInfo;

struct VitisAIProviderFactoryCreator {
static std::shared_ptr<IExecutionProviderFactory> Create(const ProviderOptions& provider_options);
};
Expand Down
10 changes: 0 additions & 10 deletions onnxruntime/python/onnxruntime_pybind_state_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,6 @@ struct OrtStatus {
#define BACKEND_TVM ""
#endif

#if USE_VITISAI
#define BACKEND_VITISAI "-VITISAI"
#include "core/providers/vitisai/vitisai_execution_provider.h"
#else
#define BACKEND_VITISAI ""
#endif

#if USE_OPENBLAS
#define BACKEND_OPENBLAS "-OPENBLAS"
#else
Expand Down Expand Up @@ -451,9 +444,6 @@ std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_Dnnl(c
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_Tvm(const tvm::TvmEPOptions& info);
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_Tvm(const char* params);
#endif
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_VITISAI(const char* backend_type, int device_id,
const char* export_runtime_module,
const char* load_runtime_module);
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_ACL(int use_arena);
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_ArmNN(int use_arena);
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_DML(int device_id);
Expand Down

0 comments on commit b42d4b8

Please sign in to comment.