/**************************************************************************** * * Copyright (c) 2020-2024 Vivante Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * *****************************************************************************/ #include #include #include #include #include #include #include #include "vx/ovx_executor.hpp" #include "vx/utils.hpp" namespace vsi::nbg_runner::python { namespace py = pybind11; namespace fs = std::filesystem; PYBIND11_MODULE(_nbg_runner, m) { using namespace vsi::nbg_runner::vx; // clang-format off py::class_(m, "OVXExecutor") .def(py::init()) .def(py::init([](const py::buffer& nbg_buffer) { auto buffer_info = nbg_buffer.request(false); return std::make_unique(reinterpret_cast(buffer_info.ptr), buffer_info.size); })) .def("init", &OVXExecutor::init) .def("get_num_inputs", &OVXExecutor::get_num_inputs) .def("get_num_outputs", &OVXExecutor::get_num_outputs) .def("get_input_info", &OVXExecutor::get_input_info) .def("get_output_info", &OVXExecutor::get_output_info) .def("set_input", [](OVXExecutor* executor, size_t index, const py::buffer& buffer) { auto buffer_info = buffer.request(false); std::array vx_shape = {0}; std::array vx_strides = {0}; std::reverse_copy(buffer_info.shape.cbegin(), buffer_info.shape.cend(), vx_shape.begin()); std::reverse_copy(buffer_info.strides.cbegin(), buffer_info.strides.cend(), vx_strides.begin()); executor->copy_to_input( index, buffer_info.ptr, buffer_info.ndim, vx_shape.data(), vx_strides.data() ); }) .def("get_output", [](OVXExecutor* executor, size_t index) -> py::array { auto tensor_info = executor->get_output_info(index); auto np_dtype = py::dtype(get_vx_dtype_str(tensor_info.data_type).data()); auto np_shape = std::vector(tensor_info.rank); std::reverse_copy(tensor_info.shape.data(), tensor_info.shape.data() + tensor_info.rank, np_shape.begin()); auto np_tensor = py::array(np_dtype, np_shape); auto buffer_info = np_tensor.request(true); std::array vx_strides = {0}; std::reverse_copy(buffer_info.strides.cbegin(), buffer_info.strides.cend(), vx_strides.begin()); executor->copy_from_output( index, buffer_info.ptr, tensor_info.rank, tensor_info.shape.data(), vx_strides.data() ); return np_tensor; }) .def("run", &OVXExecutor::run) ; py::class_(m, "OVXTensorInfo") .def_readonly("rank", &OVXTensorInfo::rank) .def_property_readonly("shape", [](OVXTensorInfo* tensor_info) -> py::tuple { size_t rank = tensor_info->rank; auto shape_tuple = py::tuple(rank); for (size_t i = 0; i < rank; i++){ shape_tuple[i] = tensor_info->shape[rank - i - 1]; } return shape_tuple; }) .def_property_readonly("dtype", [](OVXTensorInfo* tensor_info) -> std::string_view { return get_vx_dtype_str(tensor_info->data_type); }) .def_property_readonly("qtype", [](OVXTensorInfo* tensor_info) -> std::string_view { return get_vx_qtype_str(tensor_info->quant_type); }) .def_property_readonly("scale", [](OVXTensorInfo* tensor_info) -> float { return tensor_info->quant_type == VX_QUANT_AFFINE_SCALE ? tensor_info->quant_param.affine.scale : 0.0F; }) .def_property_readonly("zero_point", [](OVXTensorInfo* tensor_info) -> int32_t { return tensor_info->quant_type == VX_QUANT_AFFINE_SCALE ? tensor_info->quant_param.affine.zeroPoint : 0; }) .def_property_readonly("fixed_point_pos", [](OVXTensorInfo* tensor_info) -> int8_t { return tensor_info->quant_type == VX_QUANT_DYNAMIC_FIXED_POINT ? tensor_info->quant_param.dfp.fixed_point_pos : static_cast(0); }) ; // clang-format on } } // namespace vsi::nbg_runner::python