Skip to content

Commit

Permalink
rewrite import model using custom memory buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
akuporos committed Nov 7, 2024
1 parent 4e58bdf commit 5366eac
Showing 1 changed file with 74 additions and 68 deletions.
142 changes: 74 additions & 68 deletions src/bindings/python/src/pyopenvino/core/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,37 @@

namespace py = pybind11;

class stringbuf : public std::streambuf {
public:
stringbuf(char* data, std::size_t size) {
setg(data, data, data + size);
}

protected:
pos_type seekoff(off_type off,
std::ios_base::seekdir dir,
std::ios_base::openmode which = std::ios_base::in) override {
switch (dir) {
case std::ios_base::beg:
setg(eback(), eback() + off, egptr());
break;
case std::ios_base::end:
setg(eback(), egptr() + off, egptr());
break;
case std::ios_base::cur:
setg(eback(), gptr() + off, egptr());
break;
default:
return pos_type(off_type(-1));
}
return (gptr() < eback() || gptr() > egptr()) ? pos_type(off_type(-1)) : pos_type(gptr() - eback());
}

pos_type seekpos(pos_type pos, std::ios_base::openmode which) override {
return seekoff(pos, std::ios_base::beg, which);
}
};

void regclass_Core(py::module m) {
py::class_<ov::Core, std::shared_ptr<ov::Core>> cls(m, "Core");
cls.doc() =
Expand Down Expand Up @@ -503,87 +534,62 @@ void regclass_Core(py::module m) {
const std::string& device_name,
const std::map<std::string, py::object>& properties) {
const auto _properties = Common::utils::properties_to_any_map(properties);
if (!(py::isinstance(model_stream, pybind11::module::import("io").attr("BytesIO"))) && !py::isinstance<py::bytes>(model_stream)) {
if (!(py::isinstance(model_stream, pybind11::module::import("io").attr("BytesIO"))) &&
!py::isinstance<py::bytes>(model_stream)) {
throw py::type_error("CompiledModel.import_model(model_stream) incompatible function argument: "
"`model_stream` must be an io.BytesIO object or bytes but " +
(std::string)(py::repr(model_stream)) + "` provided");
}
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> distr(1000, 9999);
std::string filename = "model_stream_" + std::to_string(distr(gen)) + ".txt";
std::fstream _stream(filename, std::ios::out | std::ios::binary);
if (_stream.is_open()) {
py::bytes data;
if (py::isinstance(model_stream, pybind11::module::import("io").attr("BytesIO"))) {
model_stream.attr("seek")(0); // Always rewind stream!
data = model_stream.attr("read")();
} else {
data = model_stream;
}
// convert the Python bytes object to C++ string
char* buffer;
Py_ssize_t length;
PYBIND11_BYTES_AS_STRING_AND_SIZE(data.ptr(), &buffer, &length);
_stream.write(buffer, length);
_stream.close();
} else {
OPENVINO_THROW("Failed to open temporary file for model stream");
}
py::buffer_info info;

ov::CompiledModel result;
std::fstream _fstream(filename, std::ios::in | std::ios::binary);
if (_fstream.is_open()) {
py::gil_scoped_release release;
result = self.import_model(_fstream, device_name, _properties);
_fstream.close();
if (std::remove(filename.c_str()) != 0) {
const std::string abs_path =
py::module_::import("os").attr("getcwd")().cast<std::string>() + "/" + filename;
const std::string warning_message = "Temporary file " + abs_path + " failed to delete!";
PyErr_WarnEx(PyExc_RuntimeWarning, warning_message.c_str(), 1);
}
if (py::isinstance(model_stream, pybind11::module::import("io").attr("BytesIO"))) {
model_stream.attr("seek")(0);
info = py::buffer(model_stream.attr("getbuffer")()).request();
} else {
OPENVINO_THROW("Failed to open temporary file for model stream");
info = py::buffer(model_stream).request();
}

return result;
stringbuf mb(reinterpret_cast<char*>(info.ptr), info.size);
std::istream stream(&mb);

py::gil_scoped_release release;
return self.import_model(stream, device_name, _properties);
},
py::arg("model_stream"),
py::arg("device_name"),
py::arg("properties"),
R"(
Imports a compiled model from a previously exported one.
Advanced version of `import_model`. It utilizes, streams from standard
Python library `io`.
GIL is released while running this function.
:param model_stream: Input stream, containing a model previously exported, using export_model method.
:type model_stream: Union[io.BytesIO, bytes]
:param device_name: Name of device to which compiled model is imported.
Note: if device_name is not used to compile the original model, an exception is thrown.
:type device_name: str
:param properties: Optional map of pairs: (property name, property value) relevant only for this load operation.
:type properties: dict, optional
:return: A compiled model.
:rtype: openvino.runtime.CompiledModel
:Example:
.. code-block:: python
user_stream = io.BytesIO()
compiled.export_model(user_stream)
with open('./my_model', 'wb') as f:
f.write(user_stream.getvalue()) # or read() if seek(0) was applied before
# ...
new_compiled = core.import_model(user_stream, "CPU")
)");
- Imports a compiled model from a previously exported one.
-
- Advanced version of `import_model`. It utilizes, streams from standard
- Python library `io`.
-
- GIL is released while running this function.
-
-
- :param model_stream: Input stream, containing a model previously exported, using export_model method.
- :type model_stream: Union[io.BytesIO, bytes]
- :param device_name: Name of device to which compiled model is imported.
- Note: if device_name is not used to compile the original model, an exception is thrown.
- :type device_name: str
- :param properties: Optional map of pairs: (property name, property value) relevant only for this load operation.
- :type properties: dict, optional
- :return: A compiled model.
- :rtype: openvino.runtime.CompiledModel
-
- :Example:
- .. code-block:: python
-
- user_stream = io.BytesIO()
- compiled.export_model(user_stream)
-
- with open('./my_model', 'wb') as f:
- f.write(user_stream.getvalue()) # or read() if seek(0) was applied before
-
- # ...
-
- new_compiled = core.import_model(user_stream, "CPU")
- )");

cls.def(
"register_plugin",
Expand Down

0 comments on commit 5366eac

Please sign in to comment.