[IE][VPU]: Execution graph via ngraph for VPU plugin (#1572)

* Execution graph via ngraph for VPU plugin
* Enable ExecGraphTests
* Assert throw for multi device in tests
* Assert throw for gna device in tests
This commit is contained in:
Anton Dudchenko authored and GitHub committed 2020-08-20 12:56:12 +03:00
1 parent 920bf23718
commit de8bfae243
8 files changed
+259 -127

No files matched your search

@@ -25,8 +25,6 @@ struct StageMetaInfo final {
std::vector<ie::Precision> outPrecisions;
std::vector<ie::Layout> outLayouts;
int inputsNum = 0;
std::string layerName;
std::string layerType;
@@ -35,6 +33,12 @@ struct StageMetaInfo final {
std::string stageName;
std::string stageType;
std::vector<size_t> parentIndices;
std::vector<ie::Precision> inputPrecisions;
std::vector<ie::SizeVector> inputDims;
size_t childsNum = 0;
int execOrder = -1;
float execTime = 0;
};
@@ -11,8 +11,12 @@
namespace vpu {
InferenceEngine::ICNNNetwork::Ptr buildRuntimeGraphAsIeNet(
GraphMetaInfo& graphMetaInfo,
const std::vector<float>& perfInfo);
InferenceEngine::ICNNNetwork::Ptr buildRuntimeGraph(
GraphMetaInfo &graphMetaInfo,
GraphMetaInfo& graphMetaInfo,
const std::vector<float>& perfInfo);
} // namespace vpu
@@ -80,7 +80,7 @@ void BackEnd::getMetaData(
}
if (stage->origLayer() == nullptr) {
stageMeta.layerName = "<Extra>";
stageMeta.layerName = "";
stageMeta.layerType = "<Extra>";
} else {
const auto& origLayer = stage->origLayer();
@@ -125,13 +125,22 @@ void BackEnd::getMetaData(
}
if (data->usage() != DataUsage::Output) {
size_t prIndex;
if (data->usage() == DataUsage::Input) {
prIndex = stagesMeta.size() - 1;
} else {
prIndex = stageToMetaIndex.find(data->producer())->second;
}
for (const auto &child : data->consumers()) {
auto it = stageToMetaIndex.find(child);
if (it != stageToMetaIndex.end()) {
StageMetaInfo& meta = stagesMeta[it->second];
meta.inputsNum++;
stagesMeta[prIndex].childsNum++;
meta.parentIndices.push_back(prIndex);
meta.inputDims.push_back(dataMeta.desc.getDims());
meta.inputPrecisions.push_back(dataMeta.desc.getPrecision());
dataMeta.childrenIndices.push_back(it->second);
}
}
@@ -4,12 +4,15 @@
#include "vpu/utils/runtime_graph.hpp"
#include <legacy/cnn_network_impl.hpp>
#include "generic_ie.hpp"
#include <legacy/ie_util_internal.hpp>
#include <legacy/ie_ngraph_utils.hpp>
#include <exec_graph_info.hpp>
#include <ngraph/variant.hpp>
#include <vector>
#include <map>
#include <string>
#include <utility>
#include <memory>
@@ -17,129 +20,241 @@ using namespace InferenceEngine;
namespace vpu {
InferenceEngine::ICNNNetwork::Ptr buildRuntimeGraph(GraphMetaInfo &graphMetaInfo, const std::vector<float>& perfInfo) {
auto net = std::make_shared<InferenceEngine::details::CNNNetworkImpl>();
net->setName(graphMetaInfo.graphName);
namespace {
std::map<size_t, CNNLayerPtr> stageMetaIndexToLayer;
std::map<std::string, std::string> extractMeta(const StageMetaInfo&);
auto createLayerFromMeta = [&](const StageMetaInfo &stageMetaInfo) -> CNNLayer::Ptr {
auto layer = std::make_shared<CNNLayer>(LayerParams{stageMetaInfo.stageName,
stageMetaInfo.layerType,
Precision::FP16});
} // namespace
layer->params[ExecGraphInfoSerialization::ORIGINAL_NAMES] = stageMetaInfo.layerName;
layer->params[ExecGraphInfoSerialization::IMPL_TYPE] = stageMetaInfo.stageType;
layer->params[ExecGraphInfoSerialization::EXECUTION_ORDER] = std::to_string(stageMetaInfo.execOrder);
InferenceEngine::ICNNNetwork::Ptr buildRuntimeGraph(GraphMetaInfo& graphMetaInfo, const std::vector<float>& perfInfo) {
std::map<size_t, std::shared_ptr<ngraph::Node>> stageMetaIndexToNode;
std::function<void(size_t)> createNodeFromMeta;
std::stringstream layoutStream;
int ind = 0;
for (auto &outLayout : stageMetaInfo.outLayouts) {
if (ind == 0) {
layoutStream << outLayout;
ind++;
continue;
}
layoutStream << ',' << outLayout;
}
layer->params[ExecGraphInfoSerialization::OUTPUT_LAYOUTS] = layoutStream.str();
ngraph::ResultVector results;
ngraph::ParameterVector params;
std::string outPrecisionsStr;
ind = 0;
for (auto &outPrecision : stageMetaInfo.outPrecisions) {
if (ind == 0) {
outPrecisionsStr += outPrecision.name();
ind++;
continue;
}
outPrecisionsStr += ',' + std::string(outPrecision.name());
}
layer->params[ExecGraphInfoSerialization::OUTPUT_PRECISIONS] = outPrecisionsStr;
//
// Write performance counts
//
if (stageMetaInfo.execOrder < 0) {
layer->params[ExecGraphInfoSerialization::PERF_COUNTER] = "not_executed";
} else {
layer->params[ExecGraphInfoSerialization::PERF_COUNTER] = std::to_string(stageMetaInfo.execTime);
}
const auto deviceTimings = perfInfo.data();
const auto deviceTimingsCount = perfInfo.size();
return layer;
};
if (deviceTimingsCount > 0) {
std::size_t timeIndex = 0;
//
// Write performance counts
//
const auto deviceTimings = perfInfo.data();
auto deviceTimingsCount = perfInfo.size();
if (deviceTimingsCount > 0) {
std::size_t timeIndex = 0;
for (auto &stageMeta : graphMetaInfo.stagesMeta) {
if (stageMeta.status == ie::InferenceEngineProfileInfo::EXECUTED &&
timeIndex < deviceTimingsCount) {
stageMeta.execTime += deviceTimings[timeIndex];
timeIndex++;
}
for (auto &stageMeta : graphMetaInfo.stagesMeta) {
if (stageMeta.status == ie::InferenceEngineProfileInfo::EXECUTED &&
timeIndex < deviceTimingsCount) {
stageMeta.execTime += deviceTimings[timeIndex];
timeIndex++;
}
}
//
// Add all stages to network
//
for (std::size_t i = 0; i < graphMetaInfo.stagesMeta.size(); i++) {
const auto stageMetaData = graphMetaInfo.stagesMeta[i];
if (stageMetaData.status == ie::InferenceEngineProfileInfo::LayerStatus::OPTIMIZED_OUT ||
stageMetaData.stageName == "<Receive-Tensor>" ||
stageMetaData.stageName == "<none>") {
continue;
}
auto layer = createLayerFromMeta(stageMetaData);
stageMetaIndexToLayer.insert(std::make_pair(i, layer));
net->addLayer(layer);
}
//
// Add all edges to network
//
for (const auto &dataMetaData : graphMetaInfo.datasMeta) {
::InferenceEngine::DataPtr data;
auto parent = stageMetaIndexToLayer[dataMetaData.parentIndex];
data = std::make_shared<::InferenceEngine::Data>(dataMetaData.name, dataMetaData.desc);
parent->outData.push_back(data);
getCreatorLayer(data) = parent;
for (auto &childMetaIndex : dataMetaData.childrenIndices) {
auto child = stageMetaIndexToLayer[childMetaIndex];
getInputTo(data)[child->name] = child;
child->insData.push_back(data);
}
}
//
// Specify inputs data
//
for (std::size_t i = 0; i < graphMetaInfo.stagesMeta.size(); i++) {
const auto stageMetaData = graphMetaInfo.stagesMeta[i];
if (stageMetaData.inputsNum != 0 ||
stageMetaData.stageName == "<Receive-Tensor>" ||
stageMetaData.stageName == "<none>") {
continue;
}
auto input = stageMetaIndexToLayer[i];
auto inputInfo = std::make_shared<InputInfo>();
inputInfo->setInputData(input->outData[0]);
net->setInputInfo(inputInfo);
}
return net;
}
auto getInputs = [&](const StageMetaInfo& stageMeta) {
ngraph::OutputVector inputs;
for (int i = 0; i < stageMeta.parentIndices.size(); i++) {
const auto prIndex = stageMeta.parentIndices[i];
const auto dims = stageMeta.inputDims[i];
const auto precision = stageMeta.inputPrecisions[i];
if (stageMetaIndexToNode.count(prIndex) == 0) {
// Create parent node if it doesn't exist
createNodeFromMeta(prIndex);
}
const auto outSize = stageMetaIndexToNode[prIndex]->get_output_size();
stageMetaIndexToNode[prIndex]->set_output_size(outSize + 1);
stageMetaIndexToNode[prIndex]->set_output_type(outSize, InferenceEngine::details::convertPrecision(precision), ngraph::PartialShape(dims));
inputs.push_back(stageMetaIndexToNode[prIndex]->output(outSize));
}
return inputs;
};
createNodeFromMeta = [&](size_t index) {
const auto stageMeta = graphMetaInfo.stagesMeta[index];
const auto inputs = getInputs(stageMeta);
std::shared_ptr<ngraph::Node> node;
if (stageMeta.stageType == "Input") {
params.emplace_back(std::make_shared<ngraph::op::Parameter>());
node = params.back();
} else if (stageMeta.childsNum == 0) {
results.emplace_back(std::make_shared<ngraph::op::Result>(inputs.back()));
node = results.back();
} else {
node = std::make_shared<ExecGraphInfoSerialization::ExecutionNode>(inputs, 0);
}
node->set_friendly_name(stageMeta.stageName);
const auto metaData = extractMeta(stageMeta);
for (const auto& meta : metaData) {
node->get_rt_info()[meta.first] = std::make_shared<::ngraph::VariantWrapper<std::string>>(meta.second);
}
stageMetaIndexToNode[index] = node;
};
//
// Add stages to graph
//
for (std::size_t i = 0; i < graphMetaInfo.stagesMeta.size(); i++) {
const auto stageMeta = graphMetaInfo.stagesMeta[i];
if (stageMeta.status == ie::InferenceEngineProfileInfo::LayerStatus::OPTIMIZED_OUT ||
stageMetaIndexToNode.count(i) != 0 ||
stageMeta.stageName == "<Receive-Tensor>" ||
stageMeta.stageName == "<none>") {
continue;
}
createNodeFromMeta(i);
}
auto ngraph = std::make_shared<ngraph::Function>(results, params, graphMetaInfo.graphName);
InferenceEngine::CNNNetwork net(ngraph);
return net;
}
InferenceEngine::ICNNNetwork::Ptr buildRuntimeGraphAsIeNet(GraphMetaInfo& graphMetaInfo, const std::vector<float>& perfInfo) {
auto net = std::make_shared<InferenceEngine::details::CNNNetworkImpl>();
net->setName(graphMetaInfo.graphName);
std::map<size_t, CNNLayerPtr> stageMetaIndexToLayer;
auto createLayerFromMeta = [&](const StageMetaInfo &stageMetaInfo) -> CNNLayer::Ptr {
auto layer = std::make_shared<CNNLayer>(LayerParams{stageMetaInfo.stageName,
stageMetaInfo.layerType,
Precision::FP16});
const auto metaData = extractMeta(stageMetaInfo);
for (const auto& meta : metaData) {
layer->params[meta.first] = meta.second;
}
return layer;
};
//
// Write performance counts
//
const auto deviceTimings = perfInfo.data();
auto deviceTimingsCount = perfInfo.size();
if (deviceTimingsCount > 0) {
std::size_t timeIndex = 0;
for (auto &stageMeta : graphMetaInfo.stagesMeta) {
if (stageMeta.status == ie::InferenceEngineProfileInfo::EXECUTED &&
timeIndex < deviceTimingsCount) {
stageMeta.execTime += deviceTimings[timeIndex];
timeIndex++;
}
}
}
//
// Add all stages to network
//
for (std::size_t i = 0; i < graphMetaInfo.stagesMeta.size(); i++) {
const auto stageMetaData = graphMetaInfo.stagesMeta[i];
if (stageMetaData.status == ie::InferenceEngineProfileInfo::LayerStatus::OPTIMIZED_OUT ||
stageMetaData.stageName == "<Receive-Tensor>" ||
stageMetaData.stageName == "<none>") {
continue;
}
auto layer = createLayerFromMeta(stageMetaData);
stageMetaIndexToLayer.insert(std::make_pair(i, layer));
net->addLayer(layer);
}
//
// Add all edges to network
//
for (const auto &dataMetaData : graphMetaInfo.datasMeta) {
::InferenceEngine::DataPtr data;
auto parent = stageMetaIndexToLayer[dataMetaData.parentIndex];
data = std::make_shared<::InferenceEngine::Data>(dataMetaData.name, dataMetaData.desc);
parent->outData.push_back(data);
getCreatorLayer(data) = parent;
for (auto &childMetaIndex : dataMetaData.childrenIndices) {
auto child = stageMetaIndexToLayer[childMetaIndex];
getInputTo(data)[child->name] = child;
child->insData.push_back(data);
}
}
//
// Specify inputs data
//
for (std::size_t i = 0; i < graphMetaInfo.stagesMeta.size(); i++) {
const auto stageMetaData = graphMetaInfo.stagesMeta[i];
if (stageMetaData.layerType != "Input" ||
stageMetaData.stageName == "<Receive-Tensor>" ||
stageMetaData.stageName == "<none>") {
continue;
}
auto input = stageMetaIndexToLayer[i];
auto inputInfo = std::make_shared<InputInfo>();
inputInfo->setInputData(input->outData[0]);
net->setInputInfo(inputInfo);
}
return net;
}
namespace {
std::map<std::string, std::string> extractMeta(const StageMetaInfo& stageMeta) {
std::map<std::string, std::string> serializationInfo;
serializationInfo[ExecGraphInfoSerialization::ORIGINAL_NAMES] = stageMeta.layerName;
serializationInfo[ExecGraphInfoSerialization::IMPL_TYPE] = stageMeta.stageType;
serializationInfo[ExecGraphInfoSerialization::EXECUTION_ORDER] = std::to_string(stageMeta.execOrder);
serializationInfo[ExecGraphInfoSerialization::LAYER_TYPE] = stageMeta.layerType;
if (stageMeta.execOrder < 0 || stageMeta.execTime == 0) {
serializationInfo[ExecGraphInfoSerialization::PERF_COUNTER] = "not_executed";
} else {
serializationInfo[ExecGraphInfoSerialization::PERF_COUNTER] = std::to_string(stageMeta.execTime);
}
std::stringstream layoutStream;
int ind = 0;
for (auto &outLayout : stageMeta.outLayouts) {
if (ind == 0) {
layoutStream << outLayout;
ind++;
continue;
}
layoutStream << ',' << outLayout;
}
serializationInfo[ExecGraphInfoSerialization::OUTPUT_LAYOUTS] = layoutStream.str();
std::string outPrecisionsStr;
ind = 0;
for (auto &outPrecision : stageMeta.outPrecisions) {
if (ind == 0) {
outPrecisionsStr += outPrecision.name();
ind++;
continue;
}
outPrecisionsStr += ',' + std::string(outPrecision.name());
}
serializationInfo[ExecGraphInfoSerialization::OUTPUT_PRECISIONS] = outPrecisionsStr;
return serializationInfo;
}
} // namespace
} // namespace vpu
@@ -184,7 +184,7 @@ void ExecutableNetwork::GetMetric(const std::string &name, Parameter &result, Re
}
}
void ExecutableNetwork::GetExecGraphInfo(InferenceEngine::ICNNNetwork::Ptr &graphPtr) {
void ExecutableNetwork::GetExecGraphInfo(InferenceEngine::ICNNNetwork::Ptr& graphPtr) {
auto perfInfo = _executor->getPerfTimeInfo(_graphDesc._graphHandle);
graphPtr = buildRuntimeGraph(_graphMetaData, perfInfo);
}
@@ -7,6 +7,7 @@
using namespace BehaviorTestsDefinitions;
namespace {
const std::vector<InferenceEngine::Precision> netPrecisions = {
InferenceEngine::Precision::FP32,
InferenceEngine::Precision::FP16
};
@@ -15,7 +15,6 @@ std::vector<std::string> disabledTestPatterns() {
".*ActivationLayerTest\\.CompareWithRefs/Log.*netPRC=FP32.*",
".*ActivationLayerTest\\.CompareWithRefs/Sigmoid.*netPRC=FP32.*",
".*ActivationLayerTest\\.CompareWithRefs/Relu.*netPRC=FP32.*",
".*Behavior.*ExecGraphTests.*",
// TODO: Issue: 26268
".*ConcatLayerTest.*axis=0.*",
// TODO: Issue 31197
@@ -41,7 +41,7 @@ TEST_P(ExecGraphTests, CheckExecGraphInfoBeforeExecution) {
// Create CNNNetwork from ngrpah::Function
InferenceEngine::CNNNetwork cnnNet(function);
InferenceEngine::CNNNetwork execGraph;
if (targetDevice == CommonTestUtils::DEVICE_CPU || targetDevice == CommonTestUtils::DEVICE_GPU) {
if (targetDevice != CommonTestUtils::DEVICE_MULTI && targetDevice != CommonTestUtils::DEVICE_GNA) {
// Load CNNNetwork to target plugins
auto execNet = ie->LoadNetwork(cnnNet, targetDevice);
ASSERT_NO_THROW(execGraph = execNet.GetExecGraphInfo());
@@ -128,7 +128,7 @@ TEST_P(ExecGraphTests, CheckExecGraphInfoAfterExecution) {
// Create CNNNetwork from ngrpah::Function
InferenceEngine::CNNNetwork cnnNet(function);
InferenceEngine::CNNNetwork execGraph;
if (targetDevice == CommonTestUtils::DEVICE_CPU || targetDevice == CommonTestUtils::DEVICE_GPU) {
if (targetDevice != CommonTestUtils::DEVICE_MULTI && targetDevice != CommonTestUtils::DEVICE_GNA) {
// Load CNNNetwork to target plugins
auto execNet = ie->LoadNetwork(cnnNet, targetDevice);
ASSERT_NO_THROW(execGraph = execNet.GetExecGraphInfo());
@@ -228,7 +228,7 @@ TEST_P(ExecGraphTests, CheckExecGraphInfoSerialization) {
// Create CNNNetwork from ngrpah::Function
InferenceEngine::CNNNetwork cnnNet(function);
InferenceEngine::CNNNetwork execGraph;
if (targetDevice == CommonTestUtils::DEVICE_CPU || targetDevice == CommonTestUtils::DEVICE_GPU) {
if (targetDevice != CommonTestUtils::DEVICE_MULTI && targetDevice != CommonTestUtils::DEVICE_GNA) {
// Load CNNNetwork to target plugins
auto execNet = ie->LoadNetwork(cnnNet, targetDevice);
ASSERT_NO_THROW(execGraph = execNet.GetExecGraphInfo());