mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-29 20:14:01 +00:00
Add CI minimal build with all options disabled. Fix python binding code if sparse tensors are disabled. (#9898)
* Add 2 builds to validate the cmake defines for excluding optional components work in both full and minimal builds. * Create empty config for no-ops build * Create empty config for no-ops build - attempt #2 * Create empty config for no-ops build - attempt #3 * Update python binding code to work when sparse tensors are disabled.
This commit is contained in:
parent
3f5c1e1c58
commit
912e50f61c
6 changed files with 426 additions and 312 deletions
|
|
@ -51,19 +51,19 @@ void addOrtValueMethods(pybind11::module& m) {
|
|||
// TODO: Add check to ensure that string arrays are not passed - we currently don't support string tensors in CUDA
|
||||
CreateGenericMLValue(nullptr, GetCudaAllocator(device.Id()), "", array_on_cpu, ml_value.get(), true, false, CpuToCudaMemCpy);
|
||||
#elif USE_ROCM
|
||||
if (!IsRocmDeviceIdValid(logging::LoggingManager::DefaultLogger(), device.Id())) {
|
||||
throw std::runtime_error("The provided device id doesn't match any available GPUs on the machine.");
|
||||
}
|
||||
if (!IsRocmDeviceIdValid(logging::LoggingManager::DefaultLogger(), device.Id())) {
|
||||
throw std::runtime_error("The provided device id doesn't match any available GPUs on the machine.");
|
||||
}
|
||||
|
||||
// InputDeflist is null because OrtValue creation is not tied to a specific model
|
||||
// Likewise, there is no need to specify the name (as the name was previously used to lookup the def list)
|
||||
// TODO: Add check to ensure that string arrays are not passed - we currently don't support string tensors in CUDA
|
||||
CreateGenericMLValue(nullptr, GetRocmAllocator(device.Id()), "", array_on_cpu, ml_value.get(), true, false, CpuToRocmMemCpy);
|
||||
// InputDeflist is null because OrtValue creation is not tied to a specific model
|
||||
// Likewise, there is no need to specify the name (as the name was previously used to lookup the def list)
|
||||
// TODO: Add check to ensure that string arrays are not passed - we currently don't support string tensors in CUDA
|
||||
CreateGenericMLValue(nullptr, GetRocmAllocator(device.Id()), "", array_on_cpu, ml_value.get(), true, false, CpuToRocmMemCpy);
|
||||
|
||||
#else
|
||||
throw std::runtime_error(
|
||||
"Can't allocate memory on the CUDA device using this package of OnnxRuntime. "
|
||||
"Please use the CUDA package of OnnxRuntime to use this feature.");
|
||||
throw std::runtime_error(
|
||||
"Can't allocate memory on the CUDA device using this package of OnnxRuntime. "
|
||||
"Please use the CUDA package of OnnxRuntime to use this feature.");
|
||||
#endif
|
||||
} else {
|
||||
throw std::runtime_error("Unsupported device: Cannot place the OrtValue on this device");
|
||||
|
|
@ -97,9 +97,9 @@ void addOrtValueMethods(pybind11::module& m) {
|
|||
}
|
||||
allocator = GetCudaAllocator(device.Id());
|
||||
#else
|
||||
throw std::runtime_error(
|
||||
"Can't allocate memory on the CUDA device using this package of OnnxRuntime. "
|
||||
"Please use the CUDA package of OnnxRuntime to use this feature.");
|
||||
throw std::runtime_error(
|
||||
"Can't allocate memory on the CUDA device using this package of OnnxRuntime. "
|
||||
"Please use the CUDA package of OnnxRuntime to use this feature.");
|
||||
#endif
|
||||
} else {
|
||||
throw std::runtime_error("Unsupported device: Cannot place the OrtValue on this device");
|
||||
|
|
@ -111,6 +111,7 @@ void addOrtValueMethods(pybind11::module& m) {
|
|||
return ml_value;
|
||||
})
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
.def_static("ort_value_from_sparse_tensor", [](const PySparseTensor* py_sparse_tensor) -> std::unique_ptr<OrtValue> {
|
||||
return py_sparse_tensor->AsOrtValue();
|
||||
})
|
||||
|
|
@ -121,6 +122,7 @@ void addOrtValueMethods(pybind11::module& m) {
|
|||
}
|
||||
return std::make_unique<PySparseTensor>(*ort_value);
|
||||
})
|
||||
#endif
|
||||
// Get a pointer to Tensor data
|
||||
.def("data_ptr", [](OrtValue* ml_value) -> int64_t {
|
||||
// TODO: Assumes that the OrtValue is a Tensor, make this generic to handle non-Tensors
|
||||
|
|
@ -138,21 +140,31 @@ void addOrtValueMethods(pybind11::module& m) {
|
|||
.def("device_name", [](const OrtValue* ort_value) -> std::string {
|
||||
if (ort_value->IsTensor()) {
|
||||
return std::string(GetDeviceName(ort_value->Get<Tensor>().Location().device));
|
||||
} else if (ort_value->IsSparseTensor()) {
|
||||
return std::string(GetDeviceName(ort_value->Get<SparseTensor>().Location().device));
|
||||
} else {
|
||||
ORT_THROW("Only OrtValues that are Tensors/SparseTensors are currently supported");
|
||||
}
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
else if (ort_value->IsSparseTensor()) {
|
||||
return std::string(GetDeviceName(ort_value->Get<SparseTensor>().Location().device));
|
||||
}
|
||||
|
||||
ORT_THROW("Only OrtValues that are Tensors/SparseTensors are currently supported");
|
||||
#else
|
||||
ORT_THROW("Only OrtValues that are Tensors are supported in this build");
|
||||
#endif
|
||||
})
|
||||
.def("shape", [](const OrtValue* ort_value) -> py::list {
|
||||
py::list shape_arr;
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
// OrtValue can only be a Tensor/SparseTensor, make this generic to handle non-Tensors
|
||||
ORT_ENFORCE(ort_value->IsTensor() || ort_value->IsSparseTensor(),
|
||||
"Only OrtValues that are Tensors/SpareTensors are currently supported");
|
||||
|
||||
py::list shape_arr;
|
||||
const auto& dims = (ort_value->IsTensor())
|
||||
? ort_value->Get<Tensor>().Shape().GetDims()
|
||||
: ort_value->Get<SparseTensor>().DenseShape().GetDims();
|
||||
#else
|
||||
ORT_ENFORCE(ort_value->IsTensor(), "Only OrtValues that are Tensors are supported in this build");
|
||||
const auto& dims = ort_value->Get<Tensor>().Shape().GetDims();
|
||||
#endif
|
||||
|
||||
for (auto dim : dims) {
|
||||
// For sequence tensors - we would append a list of dims to the outermost list
|
||||
|
|
@ -168,9 +180,11 @@ void addOrtValueMethods(pybind11::module& m) {
|
|||
if (ort_value->IsTensor()) {
|
||||
auto elem_type = ort_value->Get<Tensor>().GetElementType();
|
||||
type_proto = DataTypeImpl::TensorTypeFromONNXEnum(elem_type)->GetTypeProto();
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
} else if (ort_value->IsSparseTensor()) {
|
||||
auto elem_type = ort_value->Get<SparseTensor>().GetElementType();
|
||||
type_proto = DataTypeImpl::SparseTensorTypeFromONNXEnum(elem_type)->GetTypeProto();
|
||||
#endif
|
||||
} else if (ort_value->IsTensorSequence()) {
|
||||
auto elem_type = ort_value->Get<TensorSeq>().DataType()->AsPrimitiveDataType()->GetDataType();
|
||||
type_proto = DataTypeImpl::SequenceTensorTypeFromONNXEnum(elem_type)->GetTypeProto();
|
||||
|
|
@ -204,9 +218,9 @@ void addOrtValueMethods(pybind11::module& m) {
|
|||
#ifdef USE_CUDA
|
||||
GetPyObjFromTensor(ml_value->Get<Tensor>(), obj, nullptr, GetCudaToHostMemCpyFunction());
|
||||
#elif USE_ROCM
|
||||
GetPyObjFromTensor(ml_value->Get<Tensor>(), obj, nullptr, GetRocmToHostMemCpyFunction());
|
||||
GetPyObjFromTensor(ml_value->Get<Tensor>(), obj, nullptr, GetRocmToHostMemCpyFunction());
|
||||
#else
|
||||
GetPyObjFromTensor(ml_value->Get<Tensor>(), obj, nullptr, nullptr);
|
||||
GetPyObjFromTensor(ml_value->Get<Tensor>(), obj, nullptr, nullptr);
|
||||
#endif
|
||||
return obj;
|
||||
})
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ namespace python {
|
|||
namespace py = pybind11;
|
||||
using namespace onnxruntime::logging;
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
|
||||
namespace {
|
||||
// Create a pybind11:dtype numpy instance using ONNX Tensor Element Type
|
||||
template <typename T>
|
||||
|
|
@ -79,13 +81,17 @@ class PySparseBlockSparseView : public SparseTensor::BlockSparseView {
|
|||
: SparseTensor::BlockSparseView(view), parent_(parent) {}
|
||||
};
|
||||
|
||||
#endif // !defined(DISABLE_SPARSE_TENSORS)
|
||||
|
||||
void addSparseTensorMethods(pybind11::module& m) {
|
||||
// this is exported via __init__.py so has to exist
|
||||
py::enum_<OrtSparseFormat>(m, "OrtSparseFormat")
|
||||
.value("ORT_SPARSE_UNDEFINED", OrtSparseFormat::ORT_SPARSE_UNDEFINED)
|
||||
.value("ORT_SPARSE_COO", OrtSparseFormat::ORT_SPARSE_COO)
|
||||
.value("ORT_SPARSE_CSRC", OrtSparseFormat::ORT_SPARSE_CSRC)
|
||||
.value("ORT_SPARSE_BLOCK_SPARSE", OrtSparseFormat::ORT_SPARSE_BLOCK_SPARSE);
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
py::class_<PySparseCooView>(m, "SparseCooView")
|
||||
// Returns a numpy array of COO indices backed by Sparse Tensor memory
|
||||
// be aware that indices may reside on GPU if Sparse Tensor is on GPU
|
||||
|
|
@ -111,59 +117,63 @@ void addSparseTensorMethods(pybind11::module& m) {
|
|||
});
|
||||
|
||||
py::class_<PySparseTensor> sparse_bind(m, "SparseTensor");
|
||||
// Factory method to create a COO Sparse Tensor from numpy arrays acting as backing storage.
|
||||
// Numeric arrays memory is used as is with reference count increment. All other supported
|
||||
// types are copied and supported only on CPU.
|
||||
// Use numpy.ascontiguousarray() to obtain contiguous array of values and indices if necessary
|
||||
// py_dense_shape - numpy dense shape of the sparse tensor
|
||||
// py_values - contiguous and homogeneous numpy array of values
|
||||
// py_indices - contiguous numpy array of int64_t indices
|
||||
// ort_device - where the value and indices buffers are allocated. For non-primitive types,
|
||||
// only cpu device is supported. There is not a way to verify that ort_device
|
||||
// accurately describes the memory that is backing values and indices.
|
||||
sparse_bind
|
||||
.def_static("sparse_coo_from_numpy", [](const std::vector<int64_t>& py_dense_shape, const py::array& py_values, const py::array_t<int64_t>& py_indices, const OrtDevice& ort_device) -> std::unique_ptr<PySparseTensor> {
|
||||
if (1 != py_values.ndim()) {
|
||||
ORT_THROW("Expecting values 1-D numpy values array for COO format. Got dims: ", py_values.ndim());
|
||||
}
|
||||
// Factory method to create a COO Sparse Tensor from numpy arrays acting as backing storage.
|
||||
// Numeric arrays memory is used as is with reference count increment. All other supported
|
||||
// types are copied and supported only on CPU.
|
||||
// Use numpy.ascontiguousarray() to obtain contiguous array of values and indices if necessary
|
||||
// py_dense_shape - numpy dense shape of the sparse tensor
|
||||
// py_values - contiguous and homogeneous numpy array of values
|
||||
// py_indices - contiguous numpy array of int64_t indices
|
||||
// ort_device - where the value and indices buffers are allocated. For non-primitive types,
|
||||
// only cpu device is supported. There is not a way to verify that ort_device
|
||||
// accurately describes the memory that is backing values and indices.
|
||||
sparse_bind
|
||||
.def_static("sparse_coo_from_numpy",
|
||||
[](const std::vector<int64_t>& py_dense_shape,
|
||||
const py::array& py_values,
|
||||
const py::array_t<int64_t>& py_indices,
|
||||
const OrtDevice& ort_device) -> std::unique_ptr<PySparseTensor> {
|
||||
if (1 != py_values.ndim()) {
|
||||
ORT_THROW("Expecting values 1-D numpy values array for COO format. Got dims: ", py_values.ndim());
|
||||
}
|
||||
|
||||
TensorShape dense_shape(py_dense_shape);
|
||||
auto values_type = GetNumpyArrayType(py_values);
|
||||
auto ml_type = NumpyToOnnxRuntimeTensorType(values_type);
|
||||
TensorShape dense_shape(py_dense_shape);
|
||||
auto values_type = GetNumpyArrayType(py_values);
|
||||
auto ml_type = NumpyToOnnxRuntimeTensorType(values_type);
|
||||
|
||||
std::unique_ptr<PySparseTensor> result;
|
||||
if (IsNumericNumpyType(values_type)) {
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_values.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of values");
|
||||
}
|
||||
std::unique_ptr<PySparseTensor> result;
|
||||
if (IsNumericNumpyType(values_type)) {
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_values.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of values");
|
||||
}
|
||||
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_indices.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of indices");
|
||||
}
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_indices.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of indices");
|
||||
}
|
||||
|
||||
// create references to make sure storage does not disappear
|
||||
std::vector<py::object> reference_holders = {py_values, py_indices};
|
||||
OrtMemoryInfo mem_info = GetMemoryInfoPerDeviceType(ort_device);
|
||||
TensorShape values_shape{py_values.size()};
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, values_shape,
|
||||
const_cast<void*>(py_values.data()), mem_info);
|
||||
auto index_span = gsl::make_span(const_cast<int64_t*>(py_indices.data()), py_indices.size());
|
||||
ORT_THROW_IF_ERROR(sparse_tensor->UseCooIndices(index_span));
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor), std::move(reference_holders));
|
||||
} else if (values_type == NPY_UNICODE || values_type == NPY_STRING) {
|
||||
if (ort_device.Type() != OrtDevice::CPU) {
|
||||
throw std::runtime_error("Only CPU based devices are supported for non-numeric datatypes");
|
||||
}
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, GetAllocator());
|
||||
auto mutator = sparse_tensor->MakeCooData(py_values.size(), py_indices.size());
|
||||
CopyDataToTensor(py_values, values_type, mutator.Values());
|
||||
CopyDataToTensor(py_indices, GetNumpyArrayType(py_indices), mutator.Indices());
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor));
|
||||
} else {
|
||||
ORT_THROW("Unsupported values data type: ", values_type);
|
||||
}
|
||||
return result;
|
||||
})
|
||||
// create references to make sure storage does not disappear
|
||||
std::vector<py::object> reference_holders = {py_values, py_indices};
|
||||
OrtMemoryInfo mem_info = GetMemoryInfoPerDeviceType(ort_device);
|
||||
TensorShape values_shape{py_values.size()};
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, values_shape,
|
||||
const_cast<void*>(py_values.data()), mem_info);
|
||||
auto index_span = gsl::make_span(const_cast<int64_t*>(py_indices.data()), py_indices.size());
|
||||
ORT_THROW_IF_ERROR(sparse_tensor->UseCooIndices(index_span));
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor), std::move(reference_holders));
|
||||
} else if (values_type == NPY_UNICODE || values_type == NPY_STRING) {
|
||||
if (ort_device.Type() != OrtDevice::CPU) {
|
||||
throw std::runtime_error("Only CPU based devices are supported for non-numeric datatypes");
|
||||
}
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, GetAllocator());
|
||||
auto mutator = sparse_tensor->MakeCooData(py_values.size(), py_indices.size());
|
||||
CopyDataToTensor(py_values, values_type, mutator.Values());
|
||||
CopyDataToTensor(py_indices, GetNumpyArrayType(py_indices), mutator.Indices());
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor));
|
||||
} else {
|
||||
ORT_THROW("Unsupported values data type: ", values_type);
|
||||
}
|
||||
return result;
|
||||
})
|
||||
// Factory method to create a CSR Sparse Tensor from numpy arrays acting as backing storage.
|
||||
// Numeric arrays memory is used as is with reference count increment. All other supported
|
||||
// types are copied and supported only on CPU.
|
||||
|
|
@ -175,55 +185,61 @@ void addSparseTensorMethods(pybind11::module& m) {
|
|||
// ort_device - where the value and indices buffers are allocated. For non-primitive types,
|
||||
// only cpu device is supported. There is not a way to verify that ort_device
|
||||
// accurately describes the memory that is backing values and indices.
|
||||
.def_static("sparse_csr_from_numpy", [](const std::vector<int64_t>& py_dense_shape, const py::array& py_values, const py::array_t<int64_t>& py_inner_indices, const py::array_t<int64_t>& py_outer_indices, const OrtDevice& ort_device) -> std::unique_ptr<PySparseTensor> {
|
||||
if (1 != py_values.ndim() || 1 != py_inner_indices.ndim() || 1 != py_outer_indices.ndim()) {
|
||||
ORT_THROW("Expecting all data to be 1-D numpy arrays for CSR format.");
|
||||
}
|
||||
.def_static(
|
||||
"sparse_csr_from_numpy",
|
||||
[](const std::vector<int64_t>& py_dense_shape,
|
||||
const py::array& py_values,
|
||||
const py::array_t<int64_t>& py_inner_indices,
|
||||
const py::array_t<int64_t>& py_outer_indices,
|
||||
const OrtDevice& ort_device) -> std::unique_ptr<PySparseTensor> {
|
||||
if (1 != py_values.ndim() || 1 != py_inner_indices.ndim() || 1 != py_outer_indices.ndim()) {
|
||||
ORT_THROW("Expecting all data to be 1-D numpy arrays for CSR format.");
|
||||
}
|
||||
|
||||
TensorShape dense_shape(py_dense_shape);
|
||||
auto values_type = GetNumpyArrayType(py_values);
|
||||
auto ml_type = NumpyToOnnxRuntimeTensorType(values_type);
|
||||
TensorShape dense_shape(py_dense_shape);
|
||||
auto values_type = GetNumpyArrayType(py_values);
|
||||
auto ml_type = NumpyToOnnxRuntimeTensorType(values_type);
|
||||
|
||||
std::unique_ptr<PySparseTensor> result;
|
||||
if (IsNumericNumpyType(values_type)) {
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_values.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of values");
|
||||
}
|
||||
std::unique_ptr<PySparseTensor> result;
|
||||
if (IsNumericNumpyType(values_type)) {
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_values.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of values");
|
||||
}
|
||||
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_inner_indices.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of indices");
|
||||
}
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_inner_indices.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of indices");
|
||||
}
|
||||
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_outer_indices.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of indices");
|
||||
}
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_outer_indices.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of indices");
|
||||
}
|
||||
|
||||
// go ahead and create references to make sure storage does not disappear
|
||||
std::vector<py::object> reference_holders = {py_values, py_inner_indices, py_outer_indices};
|
||||
OrtMemoryInfo mem_info = GetMemoryInfoPerDeviceType(ort_device);
|
||||
TensorShape values_shape{py_values.size()};
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, values_shape,
|
||||
const_cast<void*>(py_values.data()), mem_info);
|
||||
auto inner_span = gsl::make_span<int64_t>(const_cast<int64_t*>(py_inner_indices.data()), py_inner_indices.size());
|
||||
auto outer_span = gsl::make_span<int64_t>(const_cast<int64_t*>(py_outer_indices.data()), py_outer_indices.size());
|
||||
ORT_THROW_IF_ERROR(sparse_tensor->UseCsrIndices(inner_span, outer_span));
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor), std::move(reference_holders));
|
||||
} else if (values_type == NPY_UNICODE || values_type == NPY_STRING) {
|
||||
if (ort_device.Type() != OrtDevice::CPU) {
|
||||
throw std::runtime_error("Only CPU based devices are supported for non-numeric datatypes");
|
||||
}
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, GetAllocator());
|
||||
auto mutator = sparse_tensor->MakeCsrData(py_values.size(), py_inner_indices.size(), py_outer_indices.size());
|
||||
CopyDataToTensor(py_values, values_type, mutator.Values());
|
||||
CopyDataToTensor(py_inner_indices, GetNumpyArrayType(py_inner_indices), mutator.Inner());
|
||||
CopyDataToTensor(py_outer_indices, GetNumpyArrayType(py_outer_indices), mutator.Outer());
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor));
|
||||
} else {
|
||||
ORT_THROW("Unsupported values data type: ", values_type);
|
||||
}
|
||||
// go ahead and create references to make sure storage does not disappear
|
||||
std::vector<py::object> reference_holders = {py_values, py_inner_indices, py_outer_indices};
|
||||
OrtMemoryInfo mem_info = GetMemoryInfoPerDeviceType(ort_device);
|
||||
TensorShape values_shape{py_values.size()};
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, values_shape,
|
||||
const_cast<void*>(py_values.data()), mem_info);
|
||||
auto inner_span = gsl::make_span<int64_t>(const_cast<int64_t*>(py_inner_indices.data()), py_inner_indices.size());
|
||||
auto outer_span = gsl::make_span<int64_t>(const_cast<int64_t*>(py_outer_indices.data()), py_outer_indices.size());
|
||||
ORT_THROW_IF_ERROR(sparse_tensor->UseCsrIndices(inner_span, outer_span));
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor), std::move(reference_holders));
|
||||
} else if (values_type == NPY_UNICODE || values_type == NPY_STRING) {
|
||||
if (ort_device.Type() != OrtDevice::CPU) {
|
||||
throw std::runtime_error("Only CPU based devices are supported for non-numeric datatypes");
|
||||
}
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, GetAllocator());
|
||||
auto mutator = sparse_tensor->MakeCsrData(py_values.size(), py_inner_indices.size(), py_outer_indices.size());
|
||||
CopyDataToTensor(py_values, values_type, mutator.Values());
|
||||
CopyDataToTensor(py_inner_indices, GetNumpyArrayType(py_inner_indices), mutator.Inner());
|
||||
CopyDataToTensor(py_outer_indices, GetNumpyArrayType(py_outer_indices), mutator.Outer());
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor));
|
||||
} else {
|
||||
ORT_THROW("Unsupported values data type: ", values_type);
|
||||
}
|
||||
|
||||
return result;
|
||||
})
|
||||
return result;
|
||||
})
|
||||
// Factory method to create a BlockSparse Tensor from numpy arrays acting as backing storage.
|
||||
// Numeric arrays memory is used as is with reference count increment. All other supported
|
||||
// types are copied and supported only on CPU.
|
||||
|
|
@ -235,44 +251,49 @@ void addSparseTensorMethods(pybind11::module& m) {
|
|||
// ort_device - where the value and indices buffers are allocated. For non-primitive types,
|
||||
// only cpu device is supported. There is not a way to verify that ort_device
|
||||
// accurately describes the memory that is backing values and indices.
|
||||
.def_static("blocksparse_from_numpy", [](const std::vector<int64_t>& py_dense_shape, const py::array& py_values, const py::array_t<int32_t>& py_indices, const OrtDevice& ort_device) -> std::unique_ptr<PySparseTensor> {
|
||||
TensorShape dense_shape(py_dense_shape);
|
||||
TensorShape values_shape = GetShape(py_values);
|
||||
TensorShape index_shape = GetShape(py_indices);
|
||||
auto values_type = GetNumpyArrayType(py_values);
|
||||
auto ml_type = NumpyToOnnxRuntimeTensorType(values_type);
|
||||
.def_static(
|
||||
"blocksparse_from_numpy",
|
||||
[](const std::vector<int64_t>& py_dense_shape,
|
||||
const py::array& py_values,
|
||||
const py::array_t<int32_t>& py_indices,
|
||||
const OrtDevice& ort_device) -> std::unique_ptr<PySparseTensor> {
|
||||
TensorShape dense_shape(py_dense_shape);
|
||||
TensorShape values_shape = GetShape(py_values);
|
||||
TensorShape index_shape = GetShape(py_indices);
|
||||
auto values_type = GetNumpyArrayType(py_values);
|
||||
auto ml_type = NumpyToOnnxRuntimeTensorType(values_type);
|
||||
|
||||
std::unique_ptr<PySparseTensor> result;
|
||||
if (IsNumericNumpyType(values_type)) {
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_values.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of values");
|
||||
}
|
||||
std::unique_ptr<PySparseTensor> result;
|
||||
if (IsNumericNumpyType(values_type)) {
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_values.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of values");
|
||||
}
|
||||
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_indices.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of indices");
|
||||
}
|
||||
if (!PyArray_ISCONTIGUOUS(reinterpret_cast<PyArrayObject*>(py_indices.ptr()))) {
|
||||
throw std::runtime_error("Require contiguous numpy array of indices");
|
||||
}
|
||||
|
||||
// create references to make sure storage does not disappear
|
||||
std::vector<py::object> reference_holders = {py_values, py_indices};
|
||||
OrtMemoryInfo mem_info = GetMemoryInfoPerDeviceType(ort_device);
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, values_shape,
|
||||
const_cast<void*>(py_values.data()), mem_info);
|
||||
ORT_THROW_IF_ERROR(sparse_tensor->UseBlockSparseIndices(index_shape, const_cast<int32_t*>(py_indices.data())));
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor), std::move(reference_holders));
|
||||
} else if (values_type == NPY_UNICODE || values_type == NPY_STRING) {
|
||||
if (ort_device.Type() != OrtDevice::CPU) {
|
||||
throw std::runtime_error("Only CPU based devices are supported for non-numeric datatypes");
|
||||
}
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, GetAllocator());
|
||||
auto mutator = sparse_tensor->MakeBlockSparseData(values_shape, index_shape);
|
||||
CopyDataToTensor(py_values, values_type, mutator.Values());
|
||||
CopyDataToTensor(py_indices, GetNumpyArrayType(py_indices), mutator.Indices());
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor));
|
||||
} else {
|
||||
ORT_THROW("Unsupported values data type: ", values_type);
|
||||
}
|
||||
return result;
|
||||
})
|
||||
// create references to make sure storage does not disappear
|
||||
std::vector<py::object> reference_holders = {py_values, py_indices};
|
||||
OrtMemoryInfo mem_info = GetMemoryInfoPerDeviceType(ort_device);
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, values_shape,
|
||||
const_cast<void*>(py_values.data()), mem_info);
|
||||
ORT_THROW_IF_ERROR(sparse_tensor->UseBlockSparseIndices(index_shape, const_cast<int32_t*>(py_indices.data())));
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor), std::move(reference_holders));
|
||||
} else if (values_type == NPY_UNICODE || values_type == NPY_STRING) {
|
||||
if (ort_device.Type() != OrtDevice::CPU) {
|
||||
throw std::runtime_error("Only CPU based devices are supported for non-numeric datatypes");
|
||||
}
|
||||
auto sparse_tensor = std::make_unique<SparseTensor>(ml_type, dense_shape, GetAllocator());
|
||||
auto mutator = sparse_tensor->MakeBlockSparseData(values_shape, index_shape);
|
||||
CopyDataToTensor(py_values, values_type, mutator.Values());
|
||||
CopyDataToTensor(py_indices, GetNumpyArrayType(py_indices), mutator.Indices());
|
||||
result = std::make_unique<PySparseTensor>(std::move(sparse_tensor));
|
||||
} else {
|
||||
ORT_THROW("Unsupported values data type: ", values_type);
|
||||
}
|
||||
return result;
|
||||
})
|
||||
// Returns a numpy array that is backed by SparseTensor values memory
|
||||
// be aware that it may be on GPU
|
||||
.def("values", [](const PySparseTensor* py_tensor) -> py::array {
|
||||
|
|
@ -352,7 +373,8 @@ void addSparseTensorMethods(pybind11::module& m) {
|
|||
}
|
||||
auto cuda_allocator = GetCudaAllocator(ort_device.Id());
|
||||
auto gpu_transfer = GetGPUDataTransfer();
|
||||
auto dest_tensor = std::make_unique<SparseTensor>(sparse_tensor.DataType(), sparse_tensor.DenseShape(), std::move(cuda_allocator));
|
||||
auto dest_tensor = std::make_unique<SparseTensor>(sparse_tensor.DataType(), sparse_tensor.DenseShape(),
|
||||
std::move(cuda_allocator));
|
||||
ORT_THROW_IF_ERROR(sparse_tensor.Copy(*gpu_transfer, *dest_tensor, 0));
|
||||
auto result = std::make_unique<PySparseTensor>(std::move(dest_tensor));
|
||||
return result;
|
||||
|
|
@ -406,7 +428,8 @@ void addSparseTensorMethods(pybind11::module& m) {
|
|||
throw std::runtime_error("Can't switch on FormatFlags()");
|
||||
}
|
||||
return retval; }, [](PySparseTensor*, OrtSparseFormat) -> void { throw std::runtime_error("This is a readonly property"); });
|
||||
#endif // !defined(DISABLED_SPARSE_TENSORS)
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
} // namespace onnxruntime
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ void GetPyObjFromTensor(const Tensor& rtensor, py::object& obj,
|
|||
PyArray_DATA(reinterpret_cast<PyArrayObject*>(obj.ptr())));
|
||||
|
||||
if (numpy_type != NPY_OBJECT) {
|
||||
//if it is not cpu tensor, need to copy to host
|
||||
// if it is not cpu tensor, need to copy to host
|
||||
auto device_type = rtensor.Location().device.Type();
|
||||
if (device_type != OrtDevice::CPU) {
|
||||
if (!data_transfer_manager && !mem_cpy_to_host_functions)
|
||||
|
|
@ -190,6 +190,7 @@ const char* GetDeviceName(const OrtDevice& device) {
|
|||
}
|
||||
|
||||
py::object GetPyObjectFromSparseTensor(size_t pos, const OrtValue& ort_value, const DataTransferManager* data_transfer_manager) {
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
if (!ort_value.IsSparseTensor()) {
|
||||
ORT_THROW("Must be a sparse tensor");
|
||||
}
|
||||
|
|
@ -215,6 +216,12 @@ py::object GetPyObjectFromSparseTensor(size_t pos, const OrtValue& ort_value, co
|
|||
py::object result = py::cast(py_sparse_tensor.get(), py::return_value_policy::take_ownership);
|
||||
py_sparse_tensor.release();
|
||||
return result;
|
||||
#else
|
||||
ORT_UNUSED_PARAMETER(pos);
|
||||
ORT_UNUSED_PARAMETER(ort_value);
|
||||
ORT_UNUSED_PARAMETER(data_transfer_manager);
|
||||
ORT_THROW("SparseTensor support is disabled in this build.");
|
||||
#endif // !defined(DISABLE_SPARSE_TENSORS)
|
||||
}
|
||||
|
||||
template <>
|
||||
|
|
@ -324,13 +331,13 @@ const CUDAExecutionProviderInfo GetCudaExecutionProviderInfo(ProviderInfo_CUDA*
|
|||
|
||||
#ifdef USE_ROCM
|
||||
const ROCMExecutionProviderInfo GetRocmExecutionProviderInfo(ProviderInfo_ROCM* rocm_provider_info,
|
||||
const ProviderOptionsMap& provider_options_map){
|
||||
const ProviderOptionsMap& provider_options_map) {
|
||||
ORT_ENFORCE(rocm_provider_info);
|
||||
const auto it = provider_options_map.find(kRocmExecutionProvider);
|
||||
ROCMExecutionProviderInfo info;
|
||||
if (it != provider_options_map.end())
|
||||
rocm_provider_info->ROCMExecutionProviderInfo__FromProviderOptions(it->second, info);
|
||||
else{
|
||||
else {
|
||||
info.device_id = cuda_device_id;
|
||||
info.gpu_mem_limit = gpu_mem_limit;
|
||||
info.arena_extend_strategy = arena_extend_strategy;
|
||||
|
|
@ -355,156 +362,156 @@ std::unique_ptr<IExecutionProvider> CreateExecutionProviderInstance(
|
|||
// If the environment variable 'ORT_TENSORRT_UNAVAILABLE' exists, then we do not load TensorRT. This is set by _ld_preload for the manylinux case
|
||||
// as in that case, trying to load the library itself will result in a crash due to the way that auditwheel strips dependencies.
|
||||
if (Env::Default().GetEnvironmentVar("ORT_TENSORRT_UNAVAILABLE").empty()) {
|
||||
std::string calibration_table, cache_path, lib_path;
|
||||
auto it = provider_options_map.find(type);
|
||||
if (it != provider_options_map.end()) {
|
||||
OrtTensorRTProviderOptions params{
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
1000,
|
||||
1,
|
||||
1 << 30,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
0};
|
||||
for (auto option : it->second) {
|
||||
if (option.first == "device_id") {
|
||||
if (!option.second.empty()) {
|
||||
params.device_id = std::stoi(option.second);
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'device_id' should be a number i.e. '0'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_max_partition_iterations") {
|
||||
if (!option.second.empty()) {
|
||||
params.trt_max_partition_iterations = std::stoi(option.second);
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_max_partition_iterations' should be a positive integer number i.e. '1000'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_min_subgraph_size") {
|
||||
if (!option.second.empty()) {
|
||||
params.trt_min_subgraph_size = std::stoi(option.second);
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_min_subgraph_size' should be a positive integer number i.e. '1'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_max_workspace_size") {
|
||||
if (!option.second.empty()) {
|
||||
params.trt_max_workspace_size = std::stoull(option.second);
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_max_workspace_size' should be a number in byte i.e. '1073741824'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_fp16_enable") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_fp16_enable = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_fp16_enable = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_fp16_enable' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_int8_enable") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_int8_enable = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_int8_enable = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_int8_enable' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_int8_calibration_table_name") {
|
||||
if (!option.second.empty()) {
|
||||
calibration_table = option.second;
|
||||
params.trt_int8_calibration_table_name = calibration_table.c_str();
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_int8_calibration_table_name' should be a file name i.e. 'cal_table'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_int8_use_native_calibration_table") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_int8_use_native_calibration_table = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_int8_use_native_calibration_table = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_int8_use_native_calibration_table' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_dla_enable") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_dla_enable = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_dla_enable = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_dla_enable' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_dla_core") {
|
||||
if (!option.second.empty()) {
|
||||
params.trt_dla_core = std::stoi(option.second);
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_dla_core' should be a positive integer number i.e. '0'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_dump_subgraphs") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_dump_subgraphs = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_dump_subgraphs = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_dump_subgraphs' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_engine_cache_enable") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_engine_cache_enable = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_engine_cache_enable = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_engine_cache_enable' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_engine_cache_path") {
|
||||
if (!option.second.empty()) {
|
||||
cache_path = option.second;
|
||||
params.trt_engine_cache_path = cache_path.c_str();
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_engine_cache_path' should be a path string i.e. 'engine_cache'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_engine_decryption_enable") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_engine_decryption_enable = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_engine_decryption_enable = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_engine_decryption_enable' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_engine_decryption_lib_path") {
|
||||
if (!option.second.empty()) {
|
||||
lib_path = option.second;
|
||||
params.trt_engine_decryption_lib_path = lib_path.c_str();
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_engine_decryption_lib_path' should be a path string i.e. 'decryption_lib'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_force_sequential_engine_build") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_force_sequential_engine_build = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_force_sequential_engine_build = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_force_sequential_engine_build' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
std::string calibration_table, cache_path, lib_path;
|
||||
auto it = provider_options_map.find(type);
|
||||
if (it != provider_options_map.end()) {
|
||||
OrtTensorRTProviderOptions params{
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
1000,
|
||||
1,
|
||||
1 << 30,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
0};
|
||||
for (auto option : it->second) {
|
||||
if (option.first == "device_id") {
|
||||
if (!option.second.empty()) {
|
||||
params.device_id = std::stoi(option.second);
|
||||
} else {
|
||||
ORT_THROW("Invalid TensorRT EP option: ", option.first);
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'device_id' should be a number i.e. '0'.\n");
|
||||
}
|
||||
}
|
||||
if (std::shared_ptr<IExecutionProviderFactory> tensorrt_provider_factory = onnxruntime::CreateExecutionProviderFactory_Tensorrt(¶ms)) {
|
||||
return tensorrt_provider_factory->CreateProvider();
|
||||
}
|
||||
} else {
|
||||
if (std::shared_ptr<IExecutionProviderFactory> tensorrt_provider_factory = onnxruntime::CreateExecutionProviderFactory_Tensorrt(cuda_device_id)) {
|
||||
return tensorrt_provider_factory->CreateProvider();
|
||||
} else if (option.first == "trt_max_partition_iterations") {
|
||||
if (!option.second.empty()) {
|
||||
params.trt_max_partition_iterations = std::stoi(option.second);
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_max_partition_iterations' should be a positive integer number i.e. '1000'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_min_subgraph_size") {
|
||||
if (!option.second.empty()) {
|
||||
params.trt_min_subgraph_size = std::stoi(option.second);
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_min_subgraph_size' should be a positive integer number i.e. '1'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_max_workspace_size") {
|
||||
if (!option.second.empty()) {
|
||||
params.trt_max_workspace_size = std::stoull(option.second);
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_max_workspace_size' should be a number in byte i.e. '1073741824'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_fp16_enable") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_fp16_enable = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_fp16_enable = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_fp16_enable' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_int8_enable") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_int8_enable = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_int8_enable = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_int8_enable' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_int8_calibration_table_name") {
|
||||
if (!option.second.empty()) {
|
||||
calibration_table = option.second;
|
||||
params.trt_int8_calibration_table_name = calibration_table.c_str();
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_int8_calibration_table_name' should be a file name i.e. 'cal_table'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_int8_use_native_calibration_table") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_int8_use_native_calibration_table = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_int8_use_native_calibration_table = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_int8_use_native_calibration_table' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_dla_enable") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_dla_enable = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_dla_enable = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_dla_enable' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_dla_core") {
|
||||
if (!option.second.empty()) {
|
||||
params.trt_dla_core = std::stoi(option.second);
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_dla_core' should be a positive integer number i.e. '0'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_dump_subgraphs") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_dump_subgraphs = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_dump_subgraphs = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_dump_subgraphs' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_engine_cache_enable") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_engine_cache_enable = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_engine_cache_enable = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_engine_cache_enable' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_engine_cache_path") {
|
||||
if (!option.second.empty()) {
|
||||
cache_path = option.second;
|
||||
params.trt_engine_cache_path = cache_path.c_str();
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_engine_cache_path' should be a path string i.e. 'engine_cache'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_engine_decryption_enable") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_engine_decryption_enable = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_engine_decryption_enable = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_engine_decryption_enable' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else if (option.first == "trt_engine_decryption_lib_path") {
|
||||
if (!option.second.empty()) {
|
||||
lib_path = option.second;
|
||||
params.trt_engine_decryption_lib_path = lib_path.c_str();
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_engine_decryption_lib_path' should be a path string i.e. 'decryption_lib'.\n");
|
||||
}
|
||||
} else if (option.first == "trt_force_sequential_engine_build") {
|
||||
if (option.second == "True" || option.second == "true") {
|
||||
params.trt_force_sequential_engine_build = true;
|
||||
} else if (option.second == "False" || option.second == "false") {
|
||||
params.trt_force_sequential_engine_build = false;
|
||||
} else {
|
||||
ORT_THROW("[ERROR] [TensorRT] The value for the key 'trt_force_sequential_engine_build' should be a boolean i.e. 'True' or 'False'. Default value is False.\n");
|
||||
}
|
||||
} else {
|
||||
ORT_THROW("Invalid TensorRT EP option: ", option.first);
|
||||
}
|
||||
}
|
||||
if (std::shared_ptr<IExecutionProviderFactory> tensorrt_provider_factory = onnxruntime::CreateExecutionProviderFactory_Tensorrt(¶ms)) {
|
||||
return tensorrt_provider_factory->CreateProvider();
|
||||
}
|
||||
} else {
|
||||
if (std::shared_ptr<IExecutionProviderFactory> tensorrt_provider_factory = onnxruntime::CreateExecutionProviderFactory_Tensorrt(cuda_device_id)) {
|
||||
return tensorrt_provider_factory->CreateProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGS_DEFAULT(WARNING) << "Failed to create " << type << ". Please reference https://onnxruntime.ai/docs/execution-providers/TensorRT-ExecutionProvider.html#requirements to ensure all dependencies are met.";
|
||||
#endif
|
||||
|
|
@ -536,20 +543,17 @@ std::unique_ptr<IExecutionProvider> CreateExecutionProviderInstance(
|
|||
#endif
|
||||
} else if (type == kRocmExecutionProvider) {
|
||||
#ifdef USE_ROCM
|
||||
if(auto* rocm_provider_info = TryGetProviderInfo_ROCM())
|
||||
{
|
||||
if (auto* rocm_provider_info = TryGetProviderInfo_ROCM()) {
|
||||
const ROCMExecutionProviderInfo info = GetRocmExecutionProviderInfo(rocm_provider_info,
|
||||
provider_options_map);
|
||||
|
||||
provider_options_map);
|
||||
|
||||
// This variable is never initialized because the APIs by which is it should be initialized are deprecated, however they still
|
||||
// exist are are in-use. Neverthless, it is used to return ROCMAllocator, hence we must try to initialize it here if we can
|
||||
// since FromProviderOptions might contain external ROCM allocator.
|
||||
external_allocator_info = info.external_allocator_info;
|
||||
return rocm_provider_info->CreateExecutionProviderFactory(info)->CreateProvider();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!Env::Default().GetEnvironmentVar("ROCM_PATH").empty()) {
|
||||
} else {
|
||||
if (!Env::Default().GetEnvironmentVar("ROCM_PATH").empty()) {
|
||||
ORT_THROW("ROCM_PATH is set but ROCM wasn't able to be loaded. Please install the correct version of ROCM and MIOpen as mentioned in the GPU requirements page, make sure they're in the PATH, and that your GPU is supported.");
|
||||
}
|
||||
}
|
||||
|
|
@ -597,14 +601,12 @@ std::unique_ptr<IExecutionProvider> CreateExecutionProviderInstance(
|
|||
} else if (option.first == "blob_dump_path") {
|
||||
blob_dump_path = option.second;
|
||||
params.blob_dump_path = blob_dump_path.c_str();
|
||||
} else if (option.first == "context") {
|
||||
params.context = (void *)(option.second.c_str());
|
||||
} else if (option.first == "context") {
|
||||
params.context = (void*)(option.second.c_str());
|
||||
} else {
|
||||
ORT_THROW("Invalid OpenVINO EP option: ", option.first);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if (std::shared_ptr<IExecutionProviderFactory> openvino_provider_factory = onnxruntime::CreateExecutionProviderFactory_OpenVINO(¶ms)) {
|
||||
auto p = openvino_provider_factory->CreateProvider();
|
||||
|
|
@ -1149,7 +1151,7 @@ Applies to session load, initialization, etc. Default is 0.)pbdoc")
|
|||
.def(
|
||||
"add_session_config_entry",
|
||||
[](PySessionOptions* options, const char* config_key, const char* config_value) -> void {
|
||||
//config_key and config_value will be copied
|
||||
// config_key and config_value will be copied
|
||||
const Status status = options->config_options.AddConfigEntry(config_key, config_value);
|
||||
if (!status.IsOK())
|
||||
throw std::runtime_error(status.ErrorMessage());
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ OrtValue FromDlpack(PyObject* dlpack_tensor, const bool is_bool_tensor) {
|
|||
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
std::unique_ptr<OrtValue> PySparseTensor::AsOrtValue() const {
|
||||
if (instance_) {
|
||||
auto ort_value = std::make_unique<OrtValue>();
|
||||
|
|
@ -108,6 +109,7 @@ PySparseTensor::~PySparseTensor() {
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif // !defined(DISABLE_SPARSE_TENSORS)
|
||||
|
||||
} // namespace python
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ extern onnxruntime::ArenaExtendStrategy arena_extend_strategy;
|
|||
#include "core/providers/shared_library/provider_host_api.h"
|
||||
|
||||
namespace onnxruntime {
|
||||
#ifndef SHARED_PROVIDER
|
||||
#if !defined(SHARED_PROVIDER) && !defined(DISABLE_SPARSE_TENSORS)
|
||||
class SparseTensor;
|
||||
#endif
|
||||
namespace python {
|
||||
|
|
@ -307,6 +307,7 @@ inline AllocatorPtr& GetAllocator() {
|
|||
return alloc;
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_SPARSE_TENSORS)
|
||||
// This class exposes SparseTensor to Python
|
||||
// The class serves two major purposes
|
||||
// - to be able to map numpy arrays memory and use it on input, this serves as a reference holder
|
||||
|
|
@ -387,6 +388,7 @@ class PySparseTensor {
|
|||
// We create a copy of OrtValue when we obtain it from a run method.
|
||||
OrtValue ort_value_;
|
||||
};
|
||||
#endif // !defined(DISABLE_SPARSE_TENSORS)
|
||||
|
||||
class SessionObjectInitializer {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@
|
|||
# 5. Build baseline minimal ORT for Android arm64-v8a including no kernels and disable exceptions.
|
||||
# This step is to report the baseline binary size for Android.
|
||||
# 6. Build full (6a) and extended minimal (6b) ORT with runtime optimizations enabled.
|
||||
# 7. Build with all optional features disabled and no kernels.
|
||||
# 7a: regular build with python enabled checks that the exclusions don't break code paths in a full build.
|
||||
# 7b: minimal build with exceptions and python disabled checks that the exclusions don't break code paths in a
|
||||
# minimal build.
|
||||
|
||||
jobs:
|
||||
- job: Linux_CPU_Minimal_Build_E2E
|
||||
timeoutInMinutes: 120
|
||||
|
|
@ -35,6 +40,8 @@ jobs:
|
|||
script: |
|
||||
# Create a folder for all test data
|
||||
mkdir -p $(test_data_directory)
|
||||
# create empty config used in some parts
|
||||
touch $(test_data_directory)/include_no_operators.config
|
||||
workingDirectory: $(Build.SourcesDirectory)
|
||||
|
||||
- template: templates/get-docker-image-steps.yml
|
||||
|
|
@ -245,6 +252,70 @@ jobs:
|
|||
--cmake_extra_defines onnxruntime_ENABLE_ORT_FORMAT_RUNTIME_GRAPH_OPTIMIZATION=ON
|
||||
workingDirectory: $(Build.SourcesDirectory)
|
||||
|
||||
- script: git checkout -- .
|
||||
displayName: Discard local changes to Git repository files
|
||||
workingDirectory: $(Build.SourcesDirectory)
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: 7a. Regular build with python and all optional features disabled.
|
||||
inputs:
|
||||
script: |
|
||||
docker run --rm \
|
||||
--volume $(Build.SourcesDirectory):/onnxruntime_src \
|
||||
--volume $(Build.BinariesDirectory):/build \
|
||||
--volume $(test_data_directory):/home/onnxruntimedev/.test_data \
|
||||
-e ALLOW_RELEASED_ONNX_OPSET_ONLY=1 \
|
||||
-e NIGHTLY_BUILD \
|
||||
-e BUILD_BUILDNUMBER \
|
||||
onnxruntimecpubuild \
|
||||
/opt/python/cp37-cp37m/bin/python3 /onnxruntime_src/tools/ci_build/build.py \
|
||||
--build_dir /build/7a \
|
||||
--cmake_generator Ninja \
|
||||
--config MinSizeRel \
|
||||
--skip_submodule_sync \
|
||||
--build_shared_lib \
|
||||
--build_wheel \
|
||||
--parallel \
|
||||
--skip_tests \
|
||||
--disable_ml_ops \
|
||||
--include_ops_by_config /home/onnxruntimedev/.test_data/include_no_operators.config \
|
||||
--cmake_extra_defines onnxruntime_DISABLE_SPARSE_TENSORS=ON \
|
||||
onnxruntime_DISABLE_OPTIONAL_TYPE=ON \
|
||||
onnxruntime_ENABLE_ORT_FORMAT_RUNTIME_GRAPH_OPTIMIZATION=OFF \
|
||||
onnxruntime_BUILD_UNIT_TESTS=OFF
|
||||
workingDirectory: $(Build.SourcesDirectory)
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: 7b. Minimal build with all optional features disabled.
|
||||
inputs:
|
||||
script: |
|
||||
docker run --rm \
|
||||
--volume $(Build.SourcesDirectory):/onnxruntime_src \
|
||||
--volume $(Build.BinariesDirectory):/build \
|
||||
--volume $(test_data_directory):/home/onnxruntimedev/.test_data \
|
||||
-e ALLOW_RELEASED_ONNX_OPSET_ONLY=1 \
|
||||
-e NIGHTLY_BUILD \
|
||||
-e BUILD_BUILDNUMBER \
|
||||
onnxruntimecpubuild \
|
||||
/opt/python/cp37-cp37m/bin/python3 /onnxruntime_src/tools/ci_build/build.py \
|
||||
--build_dir /build/7b \
|
||||
--cmake_generator Ninja \
|
||||
--config MinSizeRel \
|
||||
--skip_submodule_sync \
|
||||
--build_shared_lib \
|
||||
--parallel \
|
||||
--minimal_build \
|
||||
--disable_exceptions \
|
||||
--disable_ml_ops \
|
||||
--skip_tests \
|
||||
--enable_reduced_operator_type_support \
|
||||
--include_ops_by_config /home/onnxruntimedev/.test_data/include_no_operators.config \
|
||||
--cmake_extra_defines onnxruntime_DISABLE_SPARSE_TENSORS=ON \
|
||||
onnxruntime_DISABLE_OPTIONAL_TYPE=ON \
|
||||
onnxruntime_ENABLE_ORT_FORMAT_RUNTIME_GRAPH_OPTIMIZATION=OFF \
|
||||
onnxruntime_BUILD_UNIT_TESTS=OFF
|
||||
workingDirectory: $(Build.SourcesDirectory)
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish unit test results'
|
||||
inputs:
|
||||
|
|
|
|||
Loading…
Reference in a new issue