Initial release of Vitis-AI Execution Provider (#3771)

* Initial release of Vitis-AI Execution Provider

* Add documentation, fix for onnxruntime::Model changes and use stringstream instead of file dump for model passing

* - Add Vitis-AI docker file
- Add online quantization flow Vitis-AI execution provider
- Fix remarks

* - Add fatal error build message for Vitis-AI cmake build on Windows
- Fix pep8 issue in build.py
- Add Vitis-AI execution provider example in docs

Co-authored-by: Elliott Delaye <elliott@xilinx.com>
Co-authored-by: Jorn Tuyls <jornt@xilinx.com>
Co-authored-by: Jorn Tuyls <jtuyls@users.noreply.github.com>
This commit is contained in:
edelaye 2020-05-19 05:32:32 -07:00 committed by GitHub
parent c42867c016
commit 64b5f7edf6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 953 additions and 6 deletions

View file

@ -20,6 +20,7 @@
* [DirectML](#DirectML)
* [ARM Compute Library](#ARM-Compute-Library)
* [Rockchip RKNPU](#RKNPU)
* [Xilinx Vitis-AI](#Vitis-AI)
* Options
* [OpenMP](#OpenMP)
* [OpenBLAS](#OpenBLAS)
@ -517,8 +518,22 @@ See more information on the RKNPU Execution Provider [here](./docs/execution_pro
onnxruntime_test_all
rknpu_ddk/lib64/librknpu_ddk.so
```
---
### Vitis-AI
See more information on the Xilinx Vitis-AI execution provider [here](./docs/execution_providers/Vitis-AI-ExecutionProvider.md).
For instructions to setup the hardware environment: [Hardware setup](./docs/execution_providers/Vitis-AI-ExecutionProvider.md#Hardware-setup)
#### Linux
```
./build.sh --use_vitisai
```
#### Notes
The Vitis-AI execution provider is only supported on Linux.
## Options
### OpenMP
#### Build Instructions

View file

@ -137,7 +137,7 @@ For production scenarios, it's strongly recommended to build only from an [offic
|CPU|GPU|IoT/Edge/Mobile|Other|
|---|---|---|---|
|<ul><li>Default CPU - *MLAS (Microsoft Linear Algebra Subprograms) + Eigen*</li><li>[Intel DNNL](./docs/execution_providers/DNNL-ExecutionProvider.md)</li><li>[Intel nGraph](./docs/execution_providers/nGraph-ExecutionProvider.md)</li><li>Intel MKL-ML *(build option)*</li></ul>|<ul><li>NVIDIA CUDA</li><li>[NVIDIA TensorRT](./docs/execution_providers/TensorRT-ExecutionProvider.md)</li><li>[DirectML](./docs/execution_providers/DirectML-ExecutionProvider.md)</li></ul>|<ul><li>[Intel OpenVINO](./docs/execution_providers/OpenVINO-ExecutionProvider.md)</li><li>[ARM Compute Library](./docs/execution_providers/ACL-ExecutionProvider.md) (*preview*)</li><li>[Android Neural Networks API](./docs/execution_providers/NNAPI-ExecutionProvider.md) (*preview*)</li></ul>|<ul><li>[Nuphar Model Compiler](./docs/execution_providers/Nuphar-ExecutionProvider.md) - (*preview*)</li><li>[Rockchip NPU](./docs/execution_providers/RKNPU-ExecutionProvider.md) (*preview*)</li></ul>|
|<ul><li>Default CPU - *MLAS (Microsoft Linear Algebra Subprograms) + Eigen*</li><li>[Intel DNNL](./docs/execution_providers/DNNL-ExecutionProvider.md)</li><li>[Intel nGraph](./docs/execution_providers/nGraph-ExecutionProvider.md)</li><li>Intel MKL-ML *(build option)*</li></ul>|<ul><li>NVIDIA CUDA</li><li>[NVIDIA TensorRT](./docs/execution_providers/TensorRT-ExecutionProvider.md)</li><li>[DirectML](./docs/execution_providers/DirectML-ExecutionProvider.md)</li></ul>|<ul><li>[Intel OpenVINO](./docs/execution_providers/OpenVINO-ExecutionProvider.md)</li><li>[ARM Compute Library](./docs/execution_providers/ACL-ExecutionProvider.md) (*preview*)</li><li>[Android Neural Networks API](./docs/execution_providers/NNAPI-ExecutionProvider.md) (*preview*)</li></ul>|<ul><li>[Nuphar Model Compiler](./docs/execution_providers/Nuphar-ExecutionProvider.md) - (*preview*)</li><li>[Rockchip NPU](./docs/execution_providers/RKNPU-ExecutionProvider.md) (*preview*)</li><li>[Xilinx Vitis-AI](./docs/execution_providers/Vitis-AI-ExecutionProvider.md) (*preview*)</li></ul>|
* [Roadmap: Upcoming accelerators](./docs/Roadmap.md#accelerators-and-execution-providers)
* [Extensibility: Add an execution provider](docs/AddingExecutionProvider.md)

View file

@ -72,6 +72,7 @@ option(onnxruntime_USE_OPENMP "Build with OpenMP support" OFF)
option(onnxruntime_BUILD_SHARED_LIB "Build a shared library" OFF)
option(onnxruntime_ENABLE_MICROSOFT_INTERNAL "Use this option to enable/disable microsoft internal only code" OFF)
option(onnxruntime_USE_NUPHAR "Build with Nuphar" OFF)
option(onnxruntime_USE_VITISAI "Build with Vitis-AI" OFF)
option(onnxruntime_USE_TENSORRT "Build with TensorRT support" OFF)
option(onnxruntime_ENABLE_LTO "Enable link time optimization" OFF)
option(onnxruntime_CROSS_COMPILING "Cross compiling onnx runtime" OFF)
@ -762,6 +763,17 @@ if(onnxruntime_USE_OPENVINO)
endif()
if (onnxruntime_USE_VITISAI)
if(WIN32)
message(FATAL_ERROR "Vitis-AI execution provider is not supported on Windows.")
else()
add_definitions(-DUSE_VITISAI=1)
include(pyxir)
list(APPEND onnxruntime_EXTERNAL_LIBRARIES pyxir)
list(APPEND onnxruntime_EXTERNAL_DEPENDENCIES pyxir)
endif()
endif()
if (onnxruntime_USE_OPENBLAS)
add_definitions(-DUSE_OPENBLAS=1)
if (WIN32)

28
cmake/external/pyxir.cmake vendored Normal file
View file

@ -0,0 +1,28 @@
# Copyright(C) Xilinx Inc.
# Licensed under the MIT License
set(PYXIR_SHARED_LIB libpyxir.so)
if(PYTHONINTERP_FOUND)
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
"import pyxir as px; print(px.get_include_dir()); print(px.get_lib_dir());"
RESULT_VARIABLE __result
OUTPUT_VARIABLE __output
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(__result MATCHES 0)
string(REGEX REPLACE ";" "\\\\;" __values ${__output})
string(REGEX REPLACE "\r?\n" ";" __values ${__values})
list(GET __values 0 PYXIR_INCLUDE_DIR)
list(GET __values 1 PYXIR_LIB_DIR)
endif()
else()
message(STATUS "To find Pyxir, Python interpretater is required to be found.")
endif()
add_library(pyxir SHARED IMPORTED)
message("-- Found Pyxir lib: ${PYXIR_LIB_DIR}/${PYXIR_SHARED_LIB}")
set_property(TARGET pyxir PROPERTY IMPORTED_LOCATION ${PYXIR_LIB_DIR}/${PYXIR_SHARED_LIB})
message("-- Found Pyxir include: ${PYXIR_INCLUDE_DIR}")
include_directories(${PYXIR_INCLUDE_DIR})

View file

@ -84,6 +84,7 @@ target_link_libraries(onnxruntime PRIVATE
${PROVIDERS_TENSORRT}
${PROVIDERS_OPENVINO}
${PROVIDERS_NUPHAR}
${PROVIDERS_VITISAI}
${PROVIDERS_DML}
${PROVIDERS_ACL}
${onnxruntime_winml}

View file

@ -43,6 +43,10 @@ if(onnxruntime_USE_NUPHAR)
set(PROVIDERS_NUPHAR onnxruntime_providers_nuphar)
list(APPEND ONNXRUNTIME_PROVIDER_NAMES nuphar)
endif()
if(onnxruntime_USE_VITISAI)
set(PROVIDERS_VITISAI onnxruntime_providers_vitisai)
list(APPEND ONNXRUNTIME_PROVIDER_NAMES vitisai)
endif()
if(onnxruntime_USE_CUDA)
set(PROVIDERS_CUDA onnxruntime_providers_cuda)
list(APPEND ONNXRUNTIME_PROVIDER_NAMES cuda)
@ -413,6 +417,22 @@ if (onnxruntime_USE_NUPHAR)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/providers/nuphar DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/core/providers)
endif()
if (onnxruntime_USE_VITISAI)
file(GLOB_RECURSE onnxruntime_providers_vitisai_cc_srcs CONFIGURE_DEPENDS
"${ONNXRUNTIME_ROOT}/core/providers/vitisai/*.h"
"${ONNXRUNTIME_ROOT}/core/providers/vitisai/*.cc"
)
source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_vitisai_cc_srcs})
add_library(onnxruntime_providers_vitisai ${onnxruntime_providers_vitisai_cc_srcs})
onnxruntime_add_include_to_target(onnxruntime_providers_vitisai onnxruntime_common onnxruntime_framework onnx onnx_proto protobuf::libprotobuf)
add_dependencies(onnxruntime_providers_vitisai ${onnxruntime_EXTERNAL_DEPENDENCIES})
set_target_properties(onnxruntime_providers_vitisai PROPERTIES FOLDER "ONNXRuntime")
target_include_directories(onnxruntime_providers_vitisai PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS} ${VITISAI_INCLUDE_DIR})
install(DIRECTORY ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/providers/vitisai DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/core/providers)
set_target_properties(onnxruntime_providers_vitisai PROPERTIES LINKER_LANGUAGE CXX)
endif()
if (onnxruntime_USE_OPENVINO)
include_directories("${CMAKE_CURRENT_BINARY_DIR}/onnx")

View file

@ -88,6 +88,7 @@ set(onnxruntime_pybind11_state_libs
${PROVIDERS_NGRAPH}
${PROVIDERS_OPENVINO}
${PROVIDERS_NUPHAR}
${PROVIDERS_VITISAI}
${PROVIDERS_NNAPI}
${PROVIDERS_RKNPU}
${PROVIDERS_DML}

View file

@ -0,0 +1,37 @@
# --------------------------------------------------------------
# Copyright(C) Xilinx Inc.
# Licensed under the MIT License.
# --------------------------------------------------------------
# Dockerfile to run ONNXRuntime with Vitis-AI integration
FROM xilinx/vitis-ai:latest
ARG ONNXRUNTIME_REPO=https://github.com/Microsoft/onnxruntime
ARG ONNXRUNTIME_BRANCH=master
ARG PYXIR_REPO=https://github.com/Xilinx/pyxir
ARG PYXIR_BRANCH=master
RUN apt-get update &&\
apt-get install -y sudo git bash
ENV PATH /code/cmake-3.14.3-Linux-x86_64/bin:$PATH
ENV LD_LIBRARY_PATH /opt/xilinx/xrt/lib:$LD_LIBRARY_PATH
WORKDIR /code
RUN . $VAI_ROOT/conda/etc/profile.d/conda.sh &&\
conda activate vitis-ai-tensorflow &&\
git clone --single-branch --branch ${PYXIR_BRANCH} --recursive ${PYXIR_REPO} pyxir &&\
cd pyxir && python3 setup.py install --use_vai_rt
RUN . $VAI_ROOT/conda/etc/profile.d/conda.sh &&\
conda activate vitis-ai-tensorflow &&\
git clone --single-branch --branch ${ONNXRUNTIME_BRANCH} --recursive ${ONNXRUNTIME_REPO} onnxruntime &&\
/bin/sh onnxruntime/dockerfiles/scripts/install_common_deps.sh &&\
cp onnxruntime/docs/Privacy.md /code/Privacy.md &&\
cp onnxruntime/dockerfiles/LICENSE-IMAGE.txt /code/LICENSE-IMAGE.txt &&\
cp onnxruntime/ThirdPartyNotices.txt /code/ThirdPartyNotices.txt &&\
cd onnxruntime &&\
/bin/sh ./build.sh --config RelWithDebInfo --enable_pybind --build_wheel --use_vitisai --parallel --update --build --build_shared_lib &&\
pip install /code/onnxruntime/build/Linux/RelWithDebInfo/dist/*-linux_x86_64.whl &&\
cd .. &&\
rm -rf onnxruntime cmake-3.14.3-Linux-x86_64

View file

@ -0,0 +1,33 @@
# --------------------------------------------------------------
# Copyright(C) Xilinx Inc.
# Licensed under the MIT License.
# --------------------------------------------------------------
user=`whoami`
uid=`id -u`
gid=`id -g`
xclmgmt_driver="$(find /dev -name xclmgmt\*)"
docker_devices=""
for i in ${xclmgmt_driver} ;
do
docker_devices+="--device=$i "
done
render_driver="$(find /dev/dri -name renderD\*)"
for i in ${render_driver} ;
do
docker_devices+="--device=$i "
done
docker run \
$docker_devices \
-v /opt/xilinx/dsa:/opt/xilinx/dsa \
-v /opt/xilinx/overlaybins:/opt/xilinx/overlaybins \
-e USER=$user -e UID=$uid -e GID=$gid \
-v $PWD:/workspace \
-w /workspace \
-it \
--rm \
--network=host \
onnxruntime-vitisai

View file

@ -0,0 +1,100 @@
<p align="center">
<img src="./images/Vitis-AI.png">
</p>
# Vitis-AI Execution Provider
[Vitis-AI](https://github.com/Xilinx/Vitis-AI) is Xilinx's development stack for hardware-accelerated AI inference on Xilinx platforms, including both edge devices and Alveo cards. It consists of optimized IP, tools, libraries, models, and example designs. It is designed with high efficiency and ease of use in mind, unleashing the full potential of AI acceleration on Xilinx FPGA and ACAP.
## Build
For build instructions, please see the [BUILD page](../../BUILD.md#Vitis-AI). Please setup the hardware environment before starting the build: [Hardware setup](#Hardware-setup).
### System requirements
The following table lists system requirements for running docker containers as well as Alveo cards.
| **Component** | **Requirement** |
|-----------------------------------------------------|------------------------------------------------------------|
| Motherboard | PCI Express 3\.0\-compliant with one dual\-width x16 slot |
| System Power Supply | 225W |
| Operating System | Ubuntu 16\.04, 18\.04 |
| | CentOS 7\.4, 7\.5 |
| | RHEL 7\.4, 7\.5 |
| CPU | Intel i3/i5/i7/i9/Xeon 64-bit CPU |
| GPU \(Optional to accelerate quantization\) | NVIDIA GPU with a compute capability > 3.0 |
| CUDA Driver \(Optional to accelerate quantization\) | nvidia\-410 |
| FPGA | Xilinx Alveo U200 or U250 |
| Docker Version | 19\.03\.1 |
### Hardware setup
1. Clone the Vitis AI repository:
```
git clone https://github.com/xilinx/vitis-ai
```
2. Install the Docker, and add the user to the docker group. Link the user to docker installation instructions from the following docker's website:
* https://docs.docker.com/install/linux/docker-ce/ubuntu/
* https://docs.docker.com/install/linux/docker-ce/centos/
* https://docs.docker.com/install/linux/linux-postinstall/
3. Any GPU instructions will have to be separated from Vitis AI.
4. Set up Vitis AI to target Alveo cards. To target Alveo cards with Vitis AI for machine learning workloads, you must install the following software components:
* Xilinx Runtime (XRT)
* Alveo Deployment Shells (DSAs)
* Xilinx Resource Manager (XRM) (xbutler)
* Xilinx Overlaybins (Accelerators to Dynamically Load - binary programming files)
While it is possible to install all of these software components individually, a script has been provided to automatically install them at once. To do so:
* Run the following commands:
```
cd Vitis-AI/alveo/packages
sudo su
./install.sh
```
* Power cycle the system.
5. Build and start the ONNXRuntime Vitis-AI Docker Container.
```
cd {onnxruntime-root}/dockerfiles
docker build -t onnxruntime-vitisai -f Dockerfile.vitisai .
./scripts/docker_run_vitisai.sh
```
Setup inside container
```
source /opt/xilinx/xrt/setup.sh
conda activate vitis-ai-tensorflow
```
### Samples
For python, you can base yourself on the following example:
```
# Import pyxir before onnxruntime
import pyxir
import pyxir.frontend.onnx
import pyxir.contrib.dpuv1.dpuv1
import onnxruntime
# Add other imports
# ...
# Load inputs and do preprocessing
# ...
# Create an inference session using the Vitis-AI execution provider
session = onnxruntime.InferenceSession('[model_file].onnx', None,["VitisAIExecutionProvider"])
# First N (default = 128) inputs are used for quantization calibration and will
# be executed on the CPU
imput_name = [...]
outputs = [session.run([], {input_name: calib_inputs[i]})[0] for i in range(128)]
# Afterwards, computations will be accelerated on the FPGA
input_data = [...]
result = session.run([], {input_name: input_data})
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

View file

@ -22,12 +22,14 @@ constexpr const char* kMSNchwcDomain = "com.microsoft.nchwc";
constexpr const char* kMSFeaturizersDomain = "com.microsoft.mlfeaturizers";
constexpr const char* kMSDmlDomain = "com.microsoft.dml";
constexpr const char* kNGraphDomain = "com.intel.ai";
constexpr const char* kVitisAIDomain = "com.xilinx";
constexpr const char* kCpuExecutionProvider = "CPUExecutionProvider";
constexpr const char* kCudaExecutionProvider = "CUDAExecutionProvider";
constexpr const char* kDnnlExecutionProvider = "DnnlExecutionProvider";
constexpr const char* kNGraphExecutionProvider = "NGRAPHExecutionProvider";
constexpr const char* kOpenVINOExecutionProvider = "OpenVINOExecutionProvider";
constexpr const char* kNupharExecutionProvider = "NupharExecutionProvider";
constexpr const char* kVitisAIExecutionProvider = "VitisAIExecutionProvider";
constexpr const char* kTensorrtExecutionProvider = "TensorrtExecutionProvider";
constexpr const char* kNnapiExecutionProvider = "NnapiExecutionProvider";
constexpr const char* kRknpuExecutionProvider = "RknpuExecutionProvider";

View file

@ -0,0 +1,17 @@
// Copyright (c) Xilinx Inc.
// Licensed under the MIT License.
#include "onnxruntime_c_api.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \param use_arena zero: false. non-zero: true.
*/
ORT_API_STATUS(OrtSessionOptionsAppendExecutionProvider_VITISAI, _In_ OrtSessionOptions* options, const char *backend_type, int device_id);
#ifdef __cplusplus
}
#endif

View file

@ -99,6 +99,7 @@ bool ProviderIsCpuBased(const std::string& provider_type) {
provider_type == onnxruntime::kDnnlExecutionProvider ||
provider_type == onnxruntime::kNGraphExecutionProvider ||
provider_type == onnxruntime::kNupharExecutionProvider ||
provider_type == onnxruntime::kVitisAIExecutionProvider ||
provider_type == onnxruntime::kOpenVINOExecutionProvider ||
provider_type == onnxruntime::kNnapiExecutionProvider ||
provider_type == onnxruntime::kRknpuExecutionProvider;

View file

@ -73,6 +73,7 @@ common::Status MemcpyTransformer::ApplyImpl(Graph& graph, bool& modified, int gr
provider != onnxruntime::kDnnlExecutionProvider &&
provider != onnxruntime::kNGraphExecutionProvider &&
provider != onnxruntime::kNupharExecutionProvider &&
provider != onnxruntime::kVitisAIExecutionProvider &&
provider != onnxruntime::kOpenVINOExecutionProvider &&
provider != onnxruntime::kAclExecutionProvider) {
TransformerMemcpyImpl copy_impl(graph, provider);
@ -219,6 +220,7 @@ void TransformerMemcpyImpl::ProcessDefs(onnxruntime::Node& node, const KernelReg
} else if (node_provider_type != kCudaExecutionProvider && node_provider_type != kTensorrtExecutionProvider) {
// TODO: copy between devices? i.e. multiple GPUs
if (node_provider_type != onnxruntime::kCpuExecutionProvider &&
node_provider_type != onnxruntime::kVitisAIExecutionProvider &&
node_provider_type != onnxruntime::kNGraphExecutionProvider && !node_provider_type.empty()) {
ORT_THROW("Execution type '", node_provider_type, "' doesn't support memcpy ");
}

View file

@ -0,0 +1 @@
OrtSessionOptionsAppendExecutionProvider_VITISAI

View file

@ -0,0 +1,170 @@
// Copyright(C) Xilinx Inc.
// Licensed under the MIT License
#include <fstream>
#include <iostream>
#include <string>
#if defined(_MSC_VER)
#pragma warning(disable : 4244 4245)
#elif __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#if defined(_MSC_VER)
#pragma warning(default : 4244 4245)
#elif __GNUC__
#pragma GCC diagnostic pop
#endif
#include <chrono>
#include <pyxir/common/xbuffer.hpp>
#include <pyxir/frontend/onnx.hpp>
#include <pyxir/runtime/run_options.hpp>
#include "vitisai_custom_op.h"
#include "core/graph/graph_viewer.h"
#include "core/graph/model.h"
#include "core/common/logging/logging.h"
#include "core/session/onnxruntime_cxx_api.h"
namespace onnxruntime {
namespace vitisai_ep {
static ONNX_NAMESPACE::ModelProto GetModelProtoFromFusedNode(const onnxruntime::Node* fused_node,
const logging::Logger& logger) {
const auto* node_function = fused_node->GetFunctionBody();
ORT_ENFORCE(node_function != nullptr, "Could not extract function body for node: ",
fused_node->Name());
const Graph& node_subgraph = node_function->Body();
onnxruntime::Model model{node_subgraph.Name(), true, ModelMetaData{}, PathString{},
IOnnxRuntimeOpSchemaRegistryList{}, node_subgraph.DomainToVersionMap(),
std::vector<ONNX_NAMESPACE::FunctionProto>(), logger};
ONNX_NAMESPACE::ModelProto model_proto = model.ToProto();
model_proto.set_ir_version(ONNX_NAMESPACE::Version::IR_VERSION);
*(model_proto.mutable_graph()) = node_subgraph.ToGraphProto();
return model_proto;
}
VitisAICustomOp::VitisAICustomOp(const ComputeContext* context,
const onnxruntime::Node* fused_node,
const std::string &backend_type,
const logging::Logger* logger)
: backend_type_(backend_type)
{
SetLogger(logger);
allocate_func_ = context->allocate_func;
release_func_ = context->release_func;
allocator_ = context->allocator_handle;
name_ = context->node_name;
model_proto_ = GetModelProtoFromFusedNode(fused_node, *GetLogger());
std::istringstream model_stream{model_proto_.SerializeAsString()};
xg_ = pyxir::onnx::import_onnx_model(model_stream);
pyxir::partition(xg_, std::vector<std::string>{backend_type_}, "");
auto input_defs = fused_node->InputDefs();
for (auto idef : input_defs) {
// std::cout << "DPU input def: " << idef->Name() << std::endl;
in_tensor_names_.push_back(idef->Name());
}
auto output_defs = fused_node->OutputDefs();
for (auto odef : output_defs) {
// std::cout << "DPU output def: " << odef->Name() << std::endl;
out_tensor_names_.push_back(odef->Name());
}
pyxir::RunOptionsHolder run_options(new pyxir::runtime::RunOptions());
run_options->online_quantization = true;
rt_mod_ = pyxir::build_rt(xg_, backend_type_, in_tensor_names_, out_tensor_names_,
"vai", run_options);
}
VitisAICustomOp::~VitisAICustomOp() {}
Status VitisAICustomOp::Compute(const OrtApi* api, OrtKernelContext* context) const {
Ort::CustomOpApi ort{*api};
const unsigned num_inputs = (unsigned) xg_->get_nb_inputs();
ssize_t batch_size = 1;
std::vector<pyxir::XBufferHolder> in_tensors;
std::vector<pyxir::XBufferHolder> out_tensors;
// Initialize input tensors.
try {
for (unsigned i = 0; i < num_inputs; ++i) {
// std::cout << "Input name: " << in_tensor_names_[i];
const OrtValue* input_tensor = ort.KernelContext_GetInput(context, i);
auto tensor_info = ort.GetTensorTypeAndShape(input_tensor);
auto tensor_type = ort.GetTensorElementType(tensor_info);
auto ort_shape = ort.GetTensorShape(tensor_info);
std::vector<ssize_t> tensor_shape{ort_shape.begin(), ort_shape.end()};
batch_size = tensor_shape[0];
if (tensor_type != ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT)
return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL,
"VITIS-AI EP input onnx tensor data type: " + std::to_string(tensor_type) + " not supported.");
void* input_data = const_cast<void*>(ort.GetTensorData<void>(input_tensor));
in_tensors.push_back(std::shared_ptr<pyxir::XBuffer>(
new pyxir::XBuffer(input_data, 4, "f", tensor_shape.size(), tensor_shape,
false, false)));
}
} catch (const std::exception& exp) {
return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL, name_ + ": Exception while copying input data to Pyxir: " + std::string(exp.what()));
} catch (...) {
return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL, name_ + ": Unknown exception while copying input data to Pyxir");
}
// Initialize output tensors
try {
for (unsigned i = 0; i < out_tensor_names_.size(); ++i) {
auto shape = xg_->get(out_tensor_names_[i])->shapes[0];
std::vector<ssize_t> out_shape{shape.begin(), shape.end()};
out_shape[0] = batch_size;
std::vector<int64_t> ort_shape{out_shape.begin(), out_shape.end()};
OrtValue* output_tensor = ort.KernelContext_GetOutput(context, i, ort_shape.data(), ort_shape.size());
auto tensor_info = ort.GetTensorTypeAndShape(output_tensor);
auto tensor_type = ort.GetTensorElementType(tensor_info);
if (tensor_type != ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT)
return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL,
"VITIS-AI EP input onnx tensor data type: " + std::to_string(tensor_type) + " not supported.");
void* output_data = ort.GetTensorMutableData<void>(output_tensor);
out_tensors.push_back(std::shared_ptr<pyxir::XBuffer>(
new pyxir::XBuffer(output_data, 4, "f", out_shape.size(), out_shape,
false, false)));
}
} catch (const std::exception& exp) {
return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL, name_ + ": Exception while creating Pyxir output Tensor: " + std::string(exp.what()));
} catch (...) {
return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL, name_ + ": Unknown exception while creating Pyxir output Tensor");
}
// Run the graph through Vitis-AI Pyxir
try {
// std::lock_guard<std::mutex> lock(compute_lock_);
rt_mod_->execute(in_tensors, out_tensors);
} catch (const std::exception& exp) {
return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL, name_ + ": Exception while executing Pyxir computation: " + std::string(exp.what()));
} catch (...) {
return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL, name_ + ": Unknown exception while executing Pyxir computation");
}
return Status::OK();
}
} // namespace vitisai_ep
} // namespace onnxruntime

View file

@ -0,0 +1,74 @@
// Copyright(C) Xilinx Inc.
// Licensed under the MIT License
#pragma once
#if defined(_MSC_VER)
#pragma warning(disable : 4244 4245)
#elif __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#if defined(_MSC_VER)
#pragma warning(default : 4244 4245)
#elif __GNUC__
#pragma GCC diagnostic pop
#endif
#include <pyxir/pyxir.hpp>
#include "core/session/onnxruntime_c_api.h"
#include "core/framework/func_api.h"
#include "core/graph/graph_viewer.h"
#include "core/common/logging/logging.h"
#include "core/graph/onnx_protobuf.h"
namespace onnxruntime {
namespace vitisai_ep {
class VitisAICustomOp {
public:
VitisAICustomOp(const ComputeContext* context,
const onnxruntime::Node* fused_node,
const std::string &backend_type,
const logging::Logger* logger);
Status Compute(const OrtApi* api, OrtKernelContext* context) const;
~VitisAICustomOp();
void SetLogger(const logging::Logger* logger) {
logger_ = logger;
}
const logging::Logger* GetLogger() const {
return logger_;
}
private:
Status Initialize(const OrtApi* api, OrtKernelContext* context) const;
std::vector<std::string> in_tensor_names_;
std::vector<std::string> out_tensor_names_;
pyxir::XGraphHolder xg_;
std::string backend_type_;
pyxir::RtModHolder rt_mod_ = nullptr;
AllocateFunc allocate_func_ = nullptr;
DestroyFunc release_func_ = nullptr;
AllocatorHandle allocator_ = nullptr;
std::string name_;
mutable std::mutex compute_lock_;
const logging::Logger* logger_ = nullptr;
ONNX_NAMESPACE::ModelProto model_proto_;
};
} // namespace vitisai_ep
} // namespace onnxruntime

View file

@ -0,0 +1,324 @@
// Copyright (c) Xilinx Inc. All rights reserved.
// Licensed under the MIT License.
#include <istream>
#include <fstream>
#include <pyxir/pyxir.hpp>
#include <pyxir/frontend/onnx.hpp>
#include "core/common/common.h"
#include "core/common/logging/logging.h"
#include "core/framework/compute_capability.h"
#include "core/framework/allocatormgr.h"
#include "core/framework/kernel_registry.h"
#include "core/graph/graph_viewer.h"
#include "core/graph/model.h"
#include "vitisai_execution_provider.h"
#include "vitisai_custom_op.h"
#define MEMCPY_S(dest, src, destsz, srcsz) memcpy(dest, src, std::min(destsz, srcsz))
using namespace ONNX_NAMESPACE;
using namespace ::onnxruntime::logging;
namespace onnxruntime {
constexpr const char* PREFIX = "VITISAI";
typedef std::shared_ptr<pyxir::graph::XGraph> XGraphHolder;
typedef std::shared_ptr<pyxir::graph::XLayer> XLayerHolder;
VitisAIExecutionProvider::VitisAIExecutionProvider(const VitisAIExecutionProviderInfo& info)
: IExecutionProvider{onnxruntime::kVitisAIExecutionProvider}, backend_type_(info.backend_type),
device_id_(info.device_id) {
auto default_allocator_factory = [](int) {
auto memory_info = onnxruntime::make_unique<OrtMemoryInfo>(PREFIX, OrtAllocatorType::OrtDeviceAllocator);
return onnxruntime::make_unique<CPUAllocator>(std::move(memory_info));
};
DeviceAllocatorRegistrationInfo default_memory_info{
OrtMemTypeDefault,
std::move(default_allocator_factory),
std::numeric_limits<size_t>::max()
};
InsertAllocator(CreateAllocator(default_memory_info));
}
static std::vector<NodeIndex>
GetUnsupportedNodeIndices(const XGraphHolder &xg, const std::string &backend_type,
const GraphViewer& graph_viewer,
/*out*/ std::unordered_set<std::string>& required_initializers) {
// Retrieve
std::set<std::string> supported_tensors;
for (auto &xl_name : xg->get_layer_names()) {
XLayerHolder xl = xg->get(xl_name);
if (xl->target == backend_type)
supported_tensors.insert(xl->get_attr("onnx_id").get_string());
}
std::vector<NodeIndex> unsupported_nodes_idx;
for (const auto& node_idx : graph_viewer.GetNodesInTopologicalOrder()) {
ConstPointerContainer<std::vector<NodeArg*>> node_args
= graph_viewer.GetNode(node_idx)->OutputDefs();
bool is_node_supported = false;
for (ConstPointerContainer<std::vector<NodeArg*>>::ConstIterator it =
node_args.begin(); it != node_args.end(); ++it) {
if (supported_tensors.find((*it)->Name()) != supported_tensors.end()) {
is_node_supported = true;
} else if (is_node_supported) {
// Some output tensors are supported but not others,
// should not happen
LOGS_DEFAULT(FATAL) << "VITIS-AI EP: Found node output tensor "
<< (*it)->Name() << " which is partially supported by "
<< " DPU accelerator. This is an invalid case";
}
}
if (is_node_supported) {
// Collect inputs that are initializers
graph_viewer.GetNode(node_idx)->ForEachDef([&required_initializers, &graph_viewer](const onnxruntime::NodeArg& node_arg, bool is_input) {
if(is_input && graph_viewer.GetAllInitializedTensors().count(node_arg.Name())) {
required_initializers.insert(node_arg.Name());
} }, true);
} else {
unsupported_nodes_idx.push_back(node_idx);
}
}
return unsupported_nodes_idx;
}
/**
* Returns a vector clusters(or node_idx). For each unsupported node, the graph is split into 3 parts.
* supported_cluster + (UNsupported_node + rest_of_the_graph). This functions returns vector of all supported_clusters by DPU
*/
static std::vector<std::vector<NodeIndex>>
GetPartitionedClusters(const std::vector<NodeIndex>& topological_order, const std::vector<NodeIndex>& unsupported_nodes) {
std::vector<std::vector<NodeIndex>> clusters;
auto prev = topological_order.begin();
for (const auto& unsup_node : unsupported_nodes) {
auto it = std::find(prev, topological_order.end(), unsup_node);
// Create a cluster vector[supported_node_idx, unsupported_node_idx) and append it to return list.
std::vector<NodeIndex> this_cluster{prev, it};
if (!this_cluster.empty()) {
clusters.push_back(std::move(this_cluster));
}
// Point prev to node idx past this unsuported node.
prev = ++it;
}
//Tail
std::vector<NodeIndex> this_cluster{prev, topological_order.end()};
if (!this_cluster.empty()) {
clusters.push_back(std::move(this_cluster));
}
return clusters;
}
static void GetInputsOutputsOfCluster(const GraphViewer& graph_viewer,
const std::vector<NodeIndex>& cluster,
const std::unordered_set<std::string>& ng_required_initializers,
/*out*/ std::vector<std::string>& cluster_inputs,
/*out*/ std::vector<std::string>& cluster_outputs) {
std::unordered_set<std::string> input_args;
std::vector<std::string> ordered_input_args;
std::unordered_set<std::string> output_args;
std::unordered_set<std::string> external_output_args;
for (const auto& node_idx : cluster) {
const auto& node = graph_viewer.GetNode(node_idx);
// Collect all inputs and outputs
node->ForEachDef(
[&input_args, &ordered_input_args, &output_args](const NodeArg& node_arg, bool is_input) {
if (is_input) {
if (!input_args.count(node_arg.Name())) {
ordered_input_args.push_back(node_arg.Name());
}
input_args.insert(node_arg.Name());
} else {
output_args.insert(node_arg.Name());
}
},
true);
// Check if output of this node is used by nodes outside this_cluster. If yes add this to cluster outputs
for (auto it = node->OutputNodesBegin(); it != node->OutputNodesEnd(); ++it) {
const auto& ext_node = graph_viewer.GetNode((*it).Index());
if (std::find(cluster.begin(), cluster.end(), ext_node->Index()) == cluster.end()) {
// Node is external to this_cluster. Search through its inputs to find the output that is generated by this_cluster.
std::set<std::string> ext_node_inputs;
ext_node->ForEachDef(
[&ext_node_inputs](const onnxruntime::NodeArg& arg, bool is_input) {
if (is_input) {
ext_node_inputs.insert(arg.Name());
}
},
true);
for (const auto& out_def : node->OutputDefs()) {
if (ext_node_inputs.find(out_def->Name()) != ext_node_inputs.end()) {
external_output_args.insert(out_def->Name());
}
}
}
}
}
//Extract initializers used by this_cluster.
std::unordered_set<std::string> original_graph_inputs;
for (const auto& node_arg : graph_viewer.GetInputsIncludingInitializers()) {
original_graph_inputs.insert(node_arg->Name());
}
const auto& initializers = graph_viewer.GetAllInitializedTensors();
std::vector<std::string> const_inputs;
for (const auto& in_arg : ordered_input_args) {
if ((initializers.count(in_arg) && !original_graph_inputs.count(in_arg)) ||
ng_required_initializers.count(in_arg)) {
const_inputs.push_back(in_arg);
}
}
for (const auto& in_arg : ordered_input_args) {
if (!output_args.count(in_arg) &&
!((initializers.count(in_arg) && !original_graph_inputs.count(in_arg)) ||
ng_required_initializers.count(in_arg))) {
cluster_inputs.push_back(in_arg);
}
}
for (const auto& in_arg : const_inputs) {
cluster_inputs.push_back(in_arg);
}
std::copy(external_output_args.begin(), external_output_args.end(), std::back_inserter(cluster_outputs));
for (const auto& node_arg : graph_viewer.GetOutputs()) {
const auto& name = node_arg->Name();
if (output_args.count(name) && !external_output_args.count(name)) {
cluster_outputs.push_back(name);
}
}
}
static void AppendClusterToSubGraph(const std::vector<NodeIndex>& nodes,
const std::vector<std::string>& inputs,
const std::vector<std::string>& outputs,
std::vector<std::unique_ptr<ComputeCapability>>& result) {
static size_t op_counter = 0;
auto meta_def = onnxruntime::make_unique<IndexedSubGraph::MetaDef>();
meta_def->name = "VitisAICustomOp_" + std::to_string(++op_counter);
meta_def->domain = kVitisAIDomain;
meta_def->since_version = 1;
meta_def->status = ONNX_NAMESPACE::EXPERIMENTAL;
meta_def->inputs = inputs;
meta_def->outputs = outputs;
std::unique_ptr<IndexedSubGraph> sub_graph = onnxruntime::make_unique<IndexedSubGraph>();
sub_graph->nodes = nodes;
sub_graph->SetMetaDef(meta_def);
result.push_back(onnxruntime::make_unique<ComputeCapability>(std::move(sub_graph)));
}
std::vector<std::unique_ptr<ComputeCapability>>
VitisAIExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph,
const std::vector<const KernelRegistry*>& kernel_registries) const {
ORT_UNUSED_PARAMETER(kernel_registries);
std::vector<std::unique_ptr<ComputeCapability>> result;
// Dump model Proto to file to pass it to pyxir
auto logger = *GetLogger();
const Graph& node_graph = graph.GetGraph();
const std::string& name_ = node_graph.Name();
onnxruntime::Model model{name_, true, ModelMetaData{}, PathString{},
IOnnxRuntimeOpSchemaRegistryList{},
node_graph.DomainToVersionMap(),
std::vector<ONNX_NAMESPACE::FunctionProto>(),
logger};
ONNX_NAMESPACE::ModelProto model_proto = model.ToProto();
model_proto.set_ir_version(ONNX_NAMESPACE::Version::IR_VERSION);
*(model_proto.mutable_graph()) = node_graph.ToGraphProto();
std::istringstream model_stream{model_proto.SerializeAsString()};
// Transform ONNX into Pyxir XGraph data structure
XGraphHolder xg = pyxir::onnx::import_onnx_model(model_stream);
// Annotate the subgraph layers in the XGraph that can be executed on the
// specified `backend_type_` target
pyxir::partition(xg, std::vector<std::string>{backend_type_}, "");
// Next stuff
if (graph.IsSubgraph()) {
return result;
}
// Need access to model_path_
for (const auto& tensor : graph.GetAllInitializedTensors()) {
if (tensor.second->has_data_location() && tensor.second->data_location() == ONNX_NAMESPACE::TensorProto_DataLocation_EXTERNAL) {
LOGS_DEFAULT(WARNING) << "VITIS-AI EP: Initializers with external data location are not currently supported";
return result;
}
}
std::unordered_set<std::string> required_initializers;
const auto unsupported_nodes = GetUnsupportedNodeIndices(xg, backend_type_, graph, required_initializers);
const auto clusters = GetPartitionedClusters(graph.GetNodesInTopologicalOrder(), unsupported_nodes);
for (const auto& this_cluster : clusters) {
std::vector<std::string> cluster_inputs, cluster_outputs;
GetInputsOutputsOfCluster(graph, this_cluster, required_initializers, cluster_inputs, cluster_outputs);
if (!cluster_inputs.empty()) {
AppendClusterToSubGraph(this_cluster, cluster_inputs, cluster_outputs, result);
}
}
return result;
}
common::Status VitisAIExecutionProvider::Compile(const std::vector<onnxruntime::Node*>& fused_nodes,
std::vector<NodeComputeInfo>& node_compute_funcs) {
for (const auto& fused_node : fused_nodes)
{
NodeComputeInfo compute_info;
compute_info.create_state_func = [this, fused_node, logger=GetLogger()](ComputeContext* context, FunctionState* state) {
auto* p = new vitisai_ep::VitisAICustomOp(context, fused_node, backend_type_, logger);
*state = p;
return 0;
};
compute_info.release_state_func = [](FunctionState state) {
if (state)
delete reinterpret_cast<onnxruntime::vitisai_ep::VitisAICustomOp*>(state);
};
compute_info.compute_func = [](FunctionState state, const OrtApi* api, OrtKernelContext* context) {
onnxruntime::vitisai_ep::VitisAICustomOp* custom_op = reinterpret_cast<onnxruntime::vitisai_ep::VitisAICustomOp*>(state);
return custom_op->Compute(api, context);
};
node_compute_funcs.push_back(compute_info);
}
return Status::OK();
}
} // namespace onnxruntime

View file

@ -0,0 +1,38 @@
// Copyright (c) Xilinx Inc. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include <ctime>
#include "core/framework/execution_provider.h"
#include "core/platform/ort_mutex.h"
namespace onnxruntime {
// Information needed to construct execution providers.
struct VitisAIExecutionProviderInfo {
int device_id{0};
std::string backend_type;
};
// Logical device representation.
class VitisAIExecutionProvider : public IExecutionProvider {
public:
explicit VitisAIExecutionProvider(const VitisAIExecutionProviderInfo& info);
~VitisAIExecutionProvider() = default;
std::vector<std::unique_ptr<ComputeCapability>>
GetCapability(const onnxruntime::GraphViewer& graph,
const std::vector<const KernelRegistry*>& /*kernel_registries*/) const override;
int GetDeviceId() const { return device_id_; }
common::Status Compile(const std::vector<onnxruntime::Node*>& fused_nodes,
std::vector<NodeComputeInfo>& node_compute_funcs) override;
private:
std::string backend_type_;
int device_id_;
};
} // namespace onnxruntime

View file

@ -0,0 +1,41 @@
// Copyright (c) Xilinx Inc. All rights reserved.
// Licensed under the MIT License.
#include "core/providers/vitisai/vitisai_provider_factory.h"
#include <atomic>
#include "vitisai_execution_provider.h"
#include "core/session/abi_session_options_impl.h"
using namespace onnxruntime;
namespace onnxruntime {
struct VitisAIProviderFactory : IExecutionProviderFactory {
VitisAIProviderFactory(std::string&& backend_type, int device_id)
: backend_type_(std::move(backend_type)), device_id_(device_id) {}
~VitisAIProviderFactory() = default;
std::unique_ptr<IExecutionProvider> CreateProvider() override;
private:
const std::string backend_type_;
int device_id_;
};
std::unique_ptr<IExecutionProvider> VitisAIProviderFactory::CreateProvider() {
VitisAIExecutionProviderInfo info;
info.backend_type = backend_type_;
info.device_id = device_id_;
return onnxruntime::make_unique<VitisAIExecutionProvider>(info);
}
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_VITISAI(const char *backend_type, int device_id) {
return std::make_shared<onnxruntime::VitisAIProviderFactory>(backend_type, device_id);
}
} // namespace onnxruntime
ORT_API_STATUS_IMPL(OrtSessionOptionsAppendExecutionProvider_VITISAI, _In_ OrtSessionOptions* options, _In_ const char* backend_type, int device_id) {
options->provider_factories.push_back(onnxruntime::CreateExecutionProviderFactory_VITISAI(backend_type, device_id));
return nullptr;
}

View file

@ -81,6 +81,13 @@
#define BACKEND_NUPHAR ""
#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
@ -113,6 +120,9 @@ std::string openvino_device;
#include "core/providers/nuphar/nuphar_provider_factory.h"
std::string nuphar_settings;
#endif
#ifdef USE_VITISAI
#include "core/providers/vitisai/vitisai_provider_factory.h"
#endif
namespace onnxruntime {
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_CPU(int use_arena);
@ -124,6 +134,8 @@ std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_Dnnl(i
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_NGraph(const char* ng_backend_type);
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_OpenVINO(const char* device);
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_Nuphar(bool, const char*);
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_VITISAI(const char *backend_type, int device_id);
} // namespace onnxruntime
#if defined(_MSC_VER)
@ -265,7 +277,7 @@ inline void RegisterExecutionProvider(InferenceSession* sess, onnxruntime::IExec
const std::vector<std::string>& GetAllProviders() {
static std::vector<std::string> all_providers = {kTensorrtExecutionProvider, kCudaExecutionProvider, kDnnlExecutionProvider,
kNGraphExecutionProvider, kOpenVINOExecutionProvider, kNupharExecutionProvider,
kCpuExecutionProvider};
kVitisAIExecutionProvider, kCpuExecutionProvider};
return all_providers;
}
@ -289,6 +301,9 @@ const std::vector<std::string>& GetAvailableProviders() {
#endif
#ifdef USE_NUPHAR
available_providers.push_back(kNupharExecutionProvider);
#endif
#ifdef USE_VITISAI
available_providers.push_back(kVitisAIExecutionProvider);
#endif
return available_providers;
};
@ -328,6 +343,10 @@ void RegisterExecutionProviders(InferenceSession* sess, const std::vector<std::s
#if USE_NUPHAR
RegisterExecutionProvider(sess, *onnxruntime::CreateExecutionProviderFactory_Nuphar(true, nuphar_settings.c_str()));
nuphar_settings.clear(); // clear nuphar_settings after use to avoid it being accidentally passed on to next session
#endif
} else if (type == kVitisAIExecutionProvider) {
#if USE_VITISAI
RegisterExecutionProvider(sess, *onnxruntime::CreateExecutionProviderFactory_VITISAI("dpuv1", 0));
#endif
} else {
// unknown provider
@ -416,6 +435,9 @@ void addGlobalMethods(py::module& m, const Environment& env) {
#endif
#ifdef USE_TENSORRT
onnxruntime::CreateExecutionProviderFactory_Tensorrt(0)
#endif
#ifdef USE_VITISAI
onnxruntime::CreateExecutionProviderFactory_VitisAI("DPU", 0),
#endif
};

View file

@ -65,6 +65,9 @@ elif '--use_dnnl' in sys.argv:
elif '--use_nuphar' in sys.argv:
package_name = 'onnxruntime-nuphar'
sys.argv.remove('--use_nuphar')
elif '--use_vitisai' in sys.argv:
package_name = 'onnxruntime-vitisai'
sys.argv.remove('--use_vitisai')
# --use_acl is specified in build.py, but not parsed here
# PEP 513 defined manylinux1_x86_64 and manylinux1_i686

View file

@ -274,6 +274,8 @@ def parse_arguments():
"--enable_msinternal", action="store_true",
help="Enable for Microsoft internal builds only.")
parser.add_argument("--llvm_path", help="Path to llvm dir")
parser.add_argument(
"--use_vitisai", action='store_true', help="Build with Vitis-AI")
parser.add_argument(
"--use_nuphar", action='store_true', help="Build with nuphar")
parser.add_argument(
@ -573,6 +575,7 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home,
"-Donnxruntime_USE_LLVM=" + ("ON" if args.use_llvm else "OFF"),
"-Donnxruntime_ENABLE_MICROSOFT_INTERNAL=" + (
"ON" if args.enable_msinternal else "OFF"),
"-Donnxruntime_USE_VITISAI=" + ("ON" if args.use_vitisai else "OFF"),
"-Donnxruntime_USE_NUPHAR=" + ("ON" if args.use_nuphar else "OFF"),
"-Donnxruntime_USE_TENSORRT=" + ("ON" if args.use_tensorrt else "OFF"),
"-Donnxruntime_TENSORRT_HOME=" + (
@ -629,7 +632,7 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home,
# nGraph, TensorRT and OpenVINO providers currently only supports
# full_protobuf option.
if (args.use_full_protobuf or args.use_ngraph or args.use_tensorrt or
args.use_openvino or args.gen_doc):
args.use_openvino or args.use_vitisai or args.gen_doc):
cmake_args += [
"-Donnxruntime_USE_FULL_PROTOBUF=ON",
"-DProtobuf_USE_STATIC_LIBS=ON"
@ -1351,9 +1354,8 @@ def nuphar_run_python_tests(build_dir, configs):
def build_python_wheel(
source_dir, build_dir, configs, use_cuda, use_ngraph, use_dnnl,
use_tensorrt, use_openvino, use_nuphar, wheel_name_suffix, use_acl,
nightly_build=False,
featurizers_build=False):
use_tensorrt, use_openvino, use_nuphar, use_vitisai, wheel_name_suffix,
use_acl, nightly_build=False, featurizers_build=False):
for config in configs:
cwd = get_config_build_dir(build_dir, config)
if is_windows():
@ -1393,6 +1395,8 @@ def build_python_wheel(
args.append('--use_dnnl')
elif use_nuphar:
args.append('--use_nuphar')
elif use_vitisai:
args.append('--use_vitisai')
elif use_acl:
args.append('--use_acl')
@ -1737,6 +1741,7 @@ def main():
args.use_tensorrt,
args.use_openvino,
args.use_nuphar,
args.use_vitisai,
args.wheel_name_suffix,
args.use_acl,
nightly_build=nightly_build,