Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IE PYTHON] FIX InputInfoCPtr, DataPtr and CDataPtr deallocation #5730

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0

from .cimport ie_api_impl_defs as C
from .ie_api_impl_defs cimport CBlob, CTensorDesc, InputInfo, CPreProcessChannel, CPreProcessInfo
from .ie_api_impl_defs cimport CBlob, CTensorDesc, InputInfo, CPreProcessChannel, CPreProcessInfo, CExecutableNetwork

import os

Expand Down Expand Up @@ -43,6 +43,7 @@ cdef class InferRequest:

cdef class IENetwork:
cdef C.IENetwork impl
cdef shared_ptr[CExecutableNetwork] _ptr_plugin
ilya-lavrenov marked this conversation as resolved.
Show resolved Hide resolved

cdef class ExecutableNetwork:
cdef unique_ptr[C.IEExecNetwork] impl
Expand All @@ -64,9 +65,11 @@ cdef class IECore:
cdef class DataPtr:
cdef C.DataPtr _ptr
cdef C.IENetwork * _ptr_network
cdef shared_ptr[CExecutableNetwork] _ptr_plugin

cdef class CDataPtr:
cdef C.CDataPtr _ptr
cdef shared_ptr[CExecutableNetwork] _ptr_plugin

cdef class TensorDesc:
cdef C.CTensorDesc impl
Expand All @@ -77,6 +80,7 @@ cdef class InputInfoPtr:

cdef class InputInfoCPtr:
cdef InputInfo.CPtr _ptr
cdef shared_ptr[CExecutableNetwork] _ptr_plugin

cdef class PreProcessInfo:
cdef CPreProcessInfo* _ptr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,7 @@ cdef class InputInfoCPtr:
cdef C.DataPtr c_data_ptr = deref(self._ptr).getInputData()
data_ptr = DataPtr()
data_ptr._ptr = c_data_ptr
data_ptr._ptr_plugin = self._ptr_plugin
return data_ptr

## tensor_desc of this input
Expand Down Expand Up @@ -918,6 +919,7 @@ cdef class ExecutableNetwork:
for in_ in c_inputs:
input_info_ptr = InputInfoCPtr()
input_info_ptr._ptr = in_.second
input_info_ptr._ptr_plugin = deref(self.impl).getPluginLink()
inputs[in_.first.decode()] = input_info_ptr
return inputs

Expand All @@ -937,6 +939,7 @@ cdef class ExecutableNetwork:
for in_ in c_inputs:
data_ptr = DataPtr()
data_ptr._ptr = in_.second
data_ptr._ptr_plugin = deref(self.impl).getPluginLink()
inputs[in_.first.decode()] = data_ptr
return inputs

Expand All @@ -949,6 +952,7 @@ cdef class ExecutableNetwork:
for in_ in c_outputs:
data_ptr = CDataPtr()
data_ptr._ptr = in_.second
data_ptr._ptr_plugin = deref(self.impl).getPluginLink()
outputs[in_.first.decode()] = data_ptr
return outputs

Expand All @@ -965,6 +969,7 @@ cdef class ExecutableNetwork:
def get_exec_graph_info(self):
ie_network = IENetwork()
ie_network.impl = deref(self.impl).GetExecGraphInfo()
ie_network._ptr_plugin = deref(self.impl).getPluginLink()
return ie_network

## Gets general runtime metric for an executable network. It can be network name, actual device ID on
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,23 +324,23 @@ void InferenceEnginePython::IEExecNetwork::infer() {
}

InferenceEnginePython::IENetwork InferenceEnginePython::IEExecNetwork::GetExecGraphInfo() {
return IENetwork(std::make_shared<InferenceEngine::CNNNetwork>(actual.GetExecGraphInfo()));
return IENetwork(std::make_shared<InferenceEngine::CNNNetwork>(actual->GetExecGraphInfo()));
}

PyObject* InferenceEnginePython::IEExecNetwork::getMetric(const std::string& metric_name) {
return parse_parameter(actual.GetMetric(metric_name));
return parse_parameter(actual->GetMetric(metric_name));
}

PyObject* InferenceEnginePython::IEExecNetwork::getConfig(const std::string& name) {
return parse_parameter(actual.GetConfig(name));
return parse_parameter(actual->GetConfig(name));
}

void InferenceEnginePython::IEExecNetwork::exportNetwork(const std::string& model_file) {
actual.Export(model_file);
actual->Export(model_file);
}

std::map<std::string, InferenceEngine::DataPtr> InferenceEnginePython::IEExecNetwork::getInputs() {
InferenceEngine::ConstInputsDataMap inputsDataMap = actual.GetInputsInfo();
InferenceEngine::ConstInputsDataMap inputsDataMap = actual->GetInputsInfo();
std::map<std::string, InferenceEngine::DataPtr> pyInputs;
for (const auto& item : inputsDataMap) {
pyInputs[item.first] = item.second->getInputData();
Expand All @@ -349,7 +349,7 @@ std::map<std::string, InferenceEngine::DataPtr> InferenceEnginePython::IEExecNet
}

std::map<std::string, InferenceEngine::InputInfo::CPtr> InferenceEnginePython::IEExecNetwork::getInputsInfo() {
InferenceEngine::ConstInputsDataMap inputsDataMap = actual.GetInputsInfo();
InferenceEngine::ConstInputsDataMap inputsDataMap = actual->GetInputsInfo();
std::map<std::string, InferenceEngine::InputInfo::CPtr> pyInputs;
for (const auto& item : inputsDataMap) {
pyInputs[item.first] = item.second;
Expand All @@ -358,14 +358,18 @@ std::map<std::string, InferenceEngine::InputInfo::CPtr> InferenceEnginePython::I
}

std::map<std::string, InferenceEngine::CDataPtr> InferenceEnginePython::IEExecNetwork::getOutputs() {
InferenceEngine::ConstOutputsDataMap outputsDataMap = actual.GetOutputsInfo();
InferenceEngine::ConstOutputsDataMap outputsDataMap = actual->GetOutputsInfo();
std::map<std::string, InferenceEngine::CDataPtr> pyOutputs;
for (const auto& item : outputsDataMap) {
pyOutputs[item.first] = item.second;
}
return pyOutputs;
}

std::shared_ptr<InferenceEngine::ExecutableNetwork> InferenceEnginePython::IEExecNetwork::getPluginLink(){
return actual;
}

void InferenceEnginePython::InferRequestWrap::setBlob(const std::string& blob_name,
const InferenceEngine::Blob::Ptr& blob_ptr) {
request_ptr.SetBlob(blob_name.c_str(), blob_ptr);
Expand Down Expand Up @@ -512,7 +516,7 @@ int InferenceEnginePython::IdleInferRequestQueue::getIdleRequestId() {

void InferenceEnginePython::IEExecNetwork::createInferRequests(int num_requests) {
if (0 == num_requests) {
num_requests = getOptimalNumberOfRequests(actual);
num_requests = getOptimalNumberOfRequests(*actual);
}
infer_requests.resize(num_requests);

Expand All @@ -521,7 +525,7 @@ void InferenceEnginePython::IEExecNetwork::createInferRequests(int num_requests)
infer_request.index = i;
request_queue_ptr->setRequestIdle(i);
infer_request.request_queue_ptr = request_queue_ptr;
infer_request.request_ptr = actual.CreateInferRequest();
infer_request.request_ptr = actual->CreateInferRequest();

infer_request.request_ptr.SetCompletionCallback<std::function<void(InferenceEngine::InferRequest r,
InferenceEngine::StatusCode)>>(
Expand Down Expand Up @@ -564,7 +568,7 @@ std::unique_ptr<InferenceEnginePython::IEExecNetwork> InferenceEnginePython::IEC
const std::map<std::string, std::string>& config,
int num_requests) {
auto exec_network = InferenceEnginePython::make_unique<InferenceEnginePython::IEExecNetwork>(network.name, num_requests);
exec_network->actual = actual.LoadNetwork(*network.actual, deviceName, config);
exec_network->actual = std::make_shared<InferenceEngine::ExecutableNetwork>(actual.LoadNetwork(*network.actual, deviceName, config));
exec_network->createInferRequests(num_requests);

return exec_network;
Expand All @@ -575,7 +579,7 @@ std::unique_ptr<InferenceEnginePython::IEExecNetwork> InferenceEnginePython::IEC
const std::map<std::string, std::string>& config,
int num_requests) {
auto exec_network = InferenceEnginePython::make_unique<InferenceEnginePython::IEExecNetwork>(modelPath, num_requests);
exec_network->actual = actual.LoadNetwork(modelPath, deviceName, config);
exec_network->actual = std::make_shared<InferenceEngine::ExecutableNetwork>(actual.LoadNetwork(modelPath, deviceName, config));
exec_network->createInferRequests(num_requests);

return exec_network;
Expand All @@ -585,7 +589,7 @@ std::unique_ptr<InferenceEnginePython::IEExecNetwork> InferenceEnginePython::IEC
const std::map<std::string, std::string>& config,
int num_requests) {
auto exec_network = InferenceEnginePython::make_unique<InferenceEnginePython::IEExecNetwork>(EXPORTED_NETWORK_NAME, num_requests);
exec_network->actual = actual.ImportNetwork(modelFIle, deviceName, config);
exec_network->actual = std::make_shared<InferenceEngine::ExecutableNetwork>(actual.ImportNetwork(modelFIle, deviceName, config));
exec_network->createInferRequests(num_requests);

return exec_network;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,9 @@ struct InferRequestWrap {
std::vector<InferenceEnginePython::CVariableState> queryState();
};


struct IEExecNetwork {
InferenceEngine::ExecutableNetwork actual;
std::shared_ptr<InferenceEngine::ExecutableNetwork> actual;
std::vector<InferRequestWrap> infer_requests;
std::string name;
IdleInferRequestQueue::Ptr request_queue_ptr;
Expand All @@ -158,6 +159,9 @@ struct IEExecNetwork {
int getIdleRequestId();

void createInferRequests(int num_requests);

//binds plugin to InputInfo and Data, so that they can be destroyed before plugin (ussue 28996)
std::shared_ptr<InferenceEngine::ExecutableNetwork> getPluginLink();
};

struct IECore {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ from libc.stdint cimport int64_t, uint8_t
cdef extern from "<inference_engine.hpp>" namespace "InferenceEngine":
ctypedef vector[size_t] SizeVector

cdef cppclass CExecutableNetwork "InferenceEngine::ExecutableNetwork"

cdef cppclass TBlob[T]:
ctypedef shared_ptr[TBlob[T]] Ptr

Expand Down Expand Up @@ -160,6 +162,7 @@ cdef extern from "ie_api_impl.hpp" namespace "InferenceEnginePython":
object getConfig(const string & metric_name) except +
int wait(int num_requests, int64_t timeout)
int getIdleRequestId()
shared_ptr[CExecutableNetwork] getPluginLink() except +

cdef cppclass IENetwork:
IENetwork() except +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,3 +304,38 @@ def test_get_config(device):
exec_net = ie_core.load_network(net, device)
config = exec_net.get_config("PERF_COUNT")
assert config == "NO"


# issue 28996
# checks that objects can deallocate in this order, if not - segfault happends
def test_input_info_deallocation(device):
ie_core = ie.IECore()
net = ie_core.read_network(model=test_net_xml, weights=test_net_bin)
exec_net = ie_core.load_network(net, device)
input_info = exec_net.input_info["data"]
del ie_core
del exec_net
del input_info


def test_outputs_deallocation(device):
ie_core = ie.IECore()
net = ie_core.read_network(model=test_net_xml, weights=test_net_bin)
exec_net = ie_core.load_network(net, device)
output = exec_net.outputs["fc_out"]
del ie_core
del exec_net
del output


def test_exec_graph_info_deallocation(device):
ie_core = ie.IECore()
if device == "CPU":
if ie_core.get_metric(device, "FULL_DEVICE_NAME") == "arm_compute::NEON":
pytest.skip("Can't run on ARM plugin due-to get_exec_graph_info method isn't implemented")
net = ie_core.read_network(model=test_net_xml, weights=test_net_bin)
exec_net = ie_core.load_network(net, device)
exec_graph_info = exec_net.get_exec_graph_info()
del ie_core
del exec_net
del exec_graph_info
18 changes: 18 additions & 0 deletions inference-engine/ie_bridges/python/tests/test_InputInfoCPtr.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def test_name(device):
exec_net = ie.load_network(net, device, num_requests=5)
assert isinstance(exec_net.input_info['data'], InputInfoCPtr)
assert exec_net.input_info['data'].name == "data", "Incorrect name"
del ie
del exec_net


Expand All @@ -25,6 +26,7 @@ def test_precision(device):
exec_net = ie.load_network(net, device, num_requests=5)
assert isinstance(exec_net.input_info['data'], InputInfoCPtr)
assert exec_net.input_info['data'].precision == "FP32", "Incorrect precision"
del ie
del exec_net


Expand All @@ -36,6 +38,7 @@ def test_no_precision_setter(device):
exec_net.input_info['data'].precision = "I8"
assert "attribute 'precision' of 'openvino.inference_engine.ie_api.InputInfoCPtr' " \
"objects is not writable" in str(e.value)
del ie
del exec_net


Expand All @@ -45,9 +48,24 @@ def test_input_data(device):
exec_net = ie.load_network(net, device, num_requests=5)
assert isinstance(exec_net.input_info['data'], InputInfoCPtr)
assert isinstance(exec_net.input_info['data'].input_data, DataPtr), "Incorrect precision for layer 'fc_out'"
del ie
del exec_net


# issue 28996
# checks that objects can deallocate in this order, if not - segfault happends
def test_input_data_deallocation(device):
ie = IECore()
net = ie.read_network(model=test_net_xml, weights=test_net_bin)
exec_net = ie.load_network(net, device)
input_info = exec_net.input_info['data']
input_data = input_info.input_data
del ie
del exec_net
del input_info
del input_data


def test_tensor_desc(device):
ie = IECore()
net = ie.read_network(model=test_net_xml, weights=test_net_bin)
Expand Down