ie_reshape_launcher.cpp 13.4 KB
Newer Older
1
// Copyright (C) 2018-2019 Intel Corporation
openvino-pushbot's avatar
openvino-pushbot committed
2 3 4 5 6 7 8 9 10 11
// SPDX-License-Identifier: Apache-2.0
//

#include <ie_layers.h>
#include <ie_layer_validators.hpp>
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <set>
12
#include <details/ie_exception.hpp>
13
#include <shape_infer/const_infer/ie_const_infer_holder.hpp>
openvino-pushbot's avatar
openvino-pushbot committed
14 15
#include "shape_infer/ie_reshape_launcher.hpp"
#include "shape_infer/ie_reshape_io_controllers.hpp"
16 17 18
#include "ie_reshape_launcher.hpp"

#include "built-in/ie_tensor_iterator_shape_infer.hpp"
openvino-pushbot's avatar
openvino-pushbot committed
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

using namespace InferenceEngine;
using namespace ShapeInfer;

void DefaultInitializer::check(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl) {
    std::string errorBase = "Failed to init reshape launcher: ";
    if (!layer) THROW_IE_EXCEPTION << errorBase + " pointer to the layer is null";
    if (!impl) THROW_IE_EXCEPTION << errorBase + " shape infer implementation is null";
}

InputController* DefaultInitializer::createInputController(const CNNLayer* layer) {
    std::vector<DataPtr> data;
    for (auto const& insData : layer->insData) {
        data.push_back(insData.lock());
    }
Alexey Suhov's avatar
Alexey Suhov committed
34
    return new InputController(data, layer->name);
openvino-pushbot's avatar
openvino-pushbot committed
35 36 37
}

OutputController* DefaultInitializer::createOutputController(const CNNLayer* layer) {
Alexey Suhov's avatar
Alexey Suhov committed
38
    return new OutputController(layer->outData, layer->name);
openvino-pushbot's avatar
openvino-pushbot committed
39 40 41
}

ReshapeLauncher::ReshapeLauncher(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl,
42
                                 const DefaultInitializer::Ptr& initializer) : _layer(layer), _reshapeImpl(impl) {
openvino-pushbot's avatar
openvino-pushbot committed
43
    initializer->check(layer, impl);
44 45
    ConstInferHolder holder;
    if (layer) _inferImpl = holder.getConstInferImpl(layer->type);
46 47 48 49 50 51 52 53 54
    try {
        _iController = initializer->createInputController(layer);
        _oController = initializer->createOutputController(layer);
    } catch (...) {
        auto exception = std::current_exception();
        delete _iController;
        delete _oController;
        std::rethrow_exception(exception);
    }
openvino-pushbot's avatar
openvino-pushbot committed
55 56 57 58 59 60 61 62 63 64 65 66 67
}

ReshapeLauncher::~ReshapeLauncher() {
    delete _iController;
    delete _oController;
    _iController = nullptr;
    _oController = nullptr;
}

void ReshapeLauncher::setShapeByName(const SizeVector& shape, const std::string& dataName) {
    _iController->setShapeByName(shape, dataName);
}

68 69 70 71 72 73 74 75
void ReshapeLauncher::setBlobByName(const Blob::CPtr& blob, const std::string& dataName) {
    _iController->setBlobByName(blob, dataName);
}

SizeVector ReshapeLauncher::getShapeByName(const std::string& dataName) {
    return _oController->getShapeByName(dataName);
}

openvino-pushbot's avatar
openvino-pushbot committed
76 77 78
void ReshapeLauncher::reshape(const std::set<ReshapeLauncher::Ptr>& launchers) {
    ResponseDesc resp;
    std::vector<SizeVector> outShapes;
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93

    // TODO: TensorIterator strongly required original layer instance because body is not presented
    //       in params map. Original subnetwork body is required for internal shape infer
    TensorIteratorShapeProp *TI_shaper = dynamic_cast<TensorIteratorShapeProp*>(_reshapeImpl.get());
    if (TI_shaper) {
        TI_shaper->setOriginalLayer(_layer);
    }

    // try to call new API with input blobs
    auto sts = _reshapeImpl->inferShapes(_iController->getBlobs(true), _layer->params, _layer->blobs, outShapes, &resp);
    // in case of old custom shape infer function call old API
    if (sts == NOT_IMPLEMENTED) {
        sts = _reshapeImpl->inferShapes(_iController->getShapes(true), _layer->params, _layer->blobs, outShapes,
                                        &resp);
    }
openvino-pushbot's avatar
openvino-pushbot committed
94 95
    _oController->setShapes(outShapes);
    if (sts != OK)
96 97 98
        THROW_IE_EXCEPTION <<
                           "Failed to infer shapes for " + _layer->type + " layer (" + _layer->name + ") with error: " +
                           resp.msg;
openvino-pushbot's avatar
openvino-pushbot committed
99 100 101 102 103 104 105
    _oController->propagateShapes(launchers);
}

void ReshapeLauncher::applyChanges(CNNLayer* layer) {
    checkLayer(layer);
    _iController->applyChanges();
    _oController->applyChanges();
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122

    // TODO: Need to finalize result of internal body shape infer and apply
    //       new shapes to body subnetwork
    TensorIteratorShapeProp *TI_shaper = dynamic_cast<TensorIteratorShapeProp*>(_reshapeImpl.get());
    if (TI_shaper) TI_shaper->apply();
}

void ReshapeLauncher::constInfer(const std::set<ReshapeLauncher::Ptr>& launchers) {
    if (_iController->isDataAvailable() || _layer->type == "Const" || _layer->type == "Shape") {
        auto outBlobs = _oController->createBlobs();
        _oController->setBlobs(outBlobs);
        if (!_inferImpl)
            THROW_IE_EXCEPTION << "Failed to find reference implementation for `"
                                  + _layer->name + "` Layer with `" + _layer->type + "` Type on constant propagation";
        _inferImpl->infer(_iController->getBlobs(false), _layer->params, _layer->blobs, outBlobs);
        _oController->propagateBlobs(launchers);
    }
openvino-pushbot's avatar
openvino-pushbot committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
}

void ReshapeLauncher::reset() {
    _iController->reset();
    _oController->reset();
}

std::string ReshapeLauncher::getLayerName() const {
    return _layer->name;
}

std::string ReshapeLauncher::getLayerType() const {
    return _layer->type;
}

void ReshapeLauncher::checkLayer(CNNLayer* layer) {
    if ((nullptr == _layer || layer == nullptr)) {
        THROW_IE_EXCEPTION << "Can't apply changes for empty layer";
    }
    auto oldParams = _layer->params;
    auto newParams = layer->params;
    if ((!oldParams.empty() && !newParams.empty() && !std::equal(oldParams.begin(), oldParams.end(), newParams.begin()))
        || (_layer->name != layer->name) || (_layer->type != layer->type) || oldParams.size() != newParams.size()) {
        THROW_IE_EXCEPTION << "Can't apply changes for layer with another params";
    }
}

void ReshapeLauncher::setIRShapeByName(const std::string& dataName) {
    SizeVector foundShape = _iController->getIRShapeByName(dataName);
    _iController->setShapeByName(foundShape, dataName);
}

void ReshapeLauncher::setShapeInferImpl(const IShapeInferImpl::Ptr& impl) {
156
    _reshapeImpl = impl;
openvino-pushbot's avatar
openvino-pushbot committed
157 158 159 160 161 162 163 164 165 166 167
}

const CNNLayer* ReshapeLauncher::getLayer() const {
    return _layer;
}

InputController* FakeInitializer::createInputController(const CNNLayer* layer) {
    std::vector<DataPtr> outData;
    for (auto const& insData : layer->insData) {
        outData.push_back(insData.lock());
    }
Alexey Suhov's avatar
Alexey Suhov committed
168
    return new InputController(outData, layer->name);
openvino-pushbot's avatar
openvino-pushbot committed
169 170 171 172 173 174 175 176
}

void FakeInitializer::check(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl) {
    std::string errorBase = "Failed to init reshape launcher: ";
    if (!layer) THROW_IE_EXCEPTION << errorBase + " pointer to the layer is null";
}

OutputController* FakeInitializer::createOutputController(const CNNLayer* layer) {
Alexey Suhov's avatar
Alexey Suhov committed
177
    return new OutputController(layer->outData, layer->name);
openvino-pushbot's avatar
openvino-pushbot committed
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
}

FakeReshapeLauncher::FakeReshapeLauncher(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl)
        : ReshapeLauncher(layer, impl, std::make_shared<FakeInitializer>()) {
}

void FakeReshapeLauncher::reshape(const std::set<ReshapeLauncher::Ptr>& launchers) {
    auto iShapesIR = _iController->getIRShapes();
    auto oShapesIR = _oController->getIRShapes();
    auto iShapes = _iController->getShapes(true);

    for (int i = 0; i < iShapes.size(); i++) {
        auto newInShape = iShapes[i];
        auto irInShape = iShapesIR[i];
        bool equal = std::equal(newInShape.begin(), newInShape.end(), irInShape.begin());
        if (!equal) {
Alexey Suhov's avatar
Alexey Suhov committed
194
            THROW_IE_EXCEPTION
openvino-pushbot's avatar
openvino-pushbot committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
                    << "Failed to infer shapes for layer with type: " << _layer->type
                    << ". Use @IShapeInferExtension class to register shape infer function for this layer";
        }
    }

    _oController->setShapes(oShapesIR);
    _oController->propagateShapes(launchers);
}

void OutputOnlyInitializer::check(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl) {
    std::string errorBase = "Failed to init reshape launcher: ";
    if (!layer) THROW_IE_EXCEPTION << errorBase + " pointer to the layer is null";
    if (!layer->insData.empty())
        THROW_IE_EXCEPTION << "Failed to init reshape launcher: "
                           << "layer type (`" + layer->type + "`) is supposed to not have inputs, but actually it has";
}

InputController* OutputOnlyInitializer::createInputController(const CNNLayer* layer) {
    return nullptr;
}

OutputController* OutputOnlyInitializer::createOutputController(const CNNLayer* layer) {
Alexey Suhov's avatar
Alexey Suhov committed
217
    return new OutputController(layer->outData, layer->name);
openvino-pushbot's avatar
openvino-pushbot committed
218 219 220 221 222 223 224 225 226 227
}

OutputOnlyReshapeLauncher::OutputOnlyReshapeLauncher(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl,
                                                     const OutputOnlyInitializer::Ptr& initializer)
        : ReshapeLauncher(layer, impl, initializer) {}

void OutputOnlyReshapeLauncher::setShapeByName(const SizeVector& shape, const std::string& dataName) {
    _oController->setShapeByName(shape, dataName);
}

228 229 230 231
void OutputOnlyReshapeLauncher::setBlobByName(const Blob::CPtr& blob, const std::string& dataName) {
    _oController->setBlobByName(blob, dataName);
}

openvino-pushbot's avatar
openvino-pushbot committed
232 233 234 235 236 237 238 239 240 241 242 243 244 245
void OutputOnlyReshapeLauncher::setIRShapeByName(const std::string& dataName) {
    SizeVector foundShape = _oController->getIRShapeByName(dataName);
    _oController->setShapeByName(foundShape, dataName);
}

void OutputOnlyReshapeLauncher::applyChanges(CNNLayer* layer) {
    checkLayer(layer);
    _oController->applyChanges();
}

void OutputOnlyReshapeLauncher::reset() {
    _oController->reset();
}

246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
void OutputOnlyReshapeLauncher::constInfer(const std::set<ReshapeLauncher::Ptr>& launchers) {
    if (_layer->type == "Const") {
        auto outBlobs = _oController->createBlobs();
        _oController->setBlobs(outBlobs);
        if (!_inferImpl)
            THROW_IE_EXCEPTION << "Failed to find reference implementation for `"
                                  + _layer->name + "` Layer with `" + _layer->type + "` Type on constant propagation";
        _inferImpl->infer({}, _layer->params, _layer->blobs, outBlobs);
        auto shapes = _oController->getShapes(true);
        for (int i = 0; i < outBlobs.size(); i++) {
            outBlobs[i]->Reshape(SizeVector(shapes[i].rbegin(), shapes[i].rend()), TensorDesc::getLayoutByDims(shapes[i]));
        }
        _oController->setBlobs(outBlobs);
        _oController->propagateBlobs(launchers);
    }
}

openvino-pushbot's avatar
openvino-pushbot committed
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
void InputInitializer::check(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl) {
    OutputOnlyInitializer::check(layer, impl);
    std::string errorBase = "Failed to init reshape launcher: layer type (`" + layer->type + "`) is not";
    if (details::equal(layer->type, "memory")) {
        if (!layer->GetParamAsInt("index"))
            THROW_IE_EXCEPTION << errorBase << " `Memory`(as input)";
    } else if (!::details::equal(layer->type, "input")) {
        THROW_IE_EXCEPTION << errorBase << " `Input`";
    }
}

InputReshapeLauncher::InputReshapeLauncher(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl,
                                           const DefaultInitializer::Ptr& initializer)
        : OutputOnlyReshapeLauncher(layer, impl, initializer) {}

void InputReshapeLauncher::reshape(const std::set<ReshapeLauncher::Ptr>& launchers) {
    auto oShapes = _oController->getShapes(false);
    auto oIRShapes = _oController->getIRShapes();
    for (size_t i = 0; i < oShapes.size(); i++) {
        if (oShapes[i].empty()) {
            _oController->setShapeByIndex(oIRShapes[i], i);
        }
    }
    _oController->propagateShapes(launchers);
}

void ConstInitializer::check(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl) {
    OutputOnlyInitializer::check(layer, impl);
    if (!::details::equal(layer->type, "const"))
        THROW_IE_EXCEPTION << "Failed to init reshape launcher: layer type (`" + layer->type + "`) is not `Const`";
}

ConstReshapeLauncher::ConstReshapeLauncher(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl)
        : OutputOnlyReshapeLauncher(layer, impl, std::make_shared<ConstInitializer>()) {}

void ConstReshapeLauncher::reshape(const std::set<ReshapeLauncher::Ptr>& launchers) {
    auto oShapesIR = _oController->getIRShapes();
    auto oShapes = _oController->getShapes(false);

    if (oShapes.empty()) {
        _oController->setShapes(oShapesIR);
    }
    if (oShapes != oShapesIR) {
        THROW_IE_EXCEPTION << "Failed to set different shapes for Const layer,"
                           << " original shapes:" << details::dumpVec(oShapesIR)
                           << " new shapes:" << details::dumpVec(oShapes);
    }
    _oController->propagateShapes(launchers);
}

void OutMemoryInitializer::check(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl) {
    std::string errorBase = "Failed to init reshape launcher: ";
    if (!layer) THROW_IE_EXCEPTION << errorBase + " pointer to the layer is null";
    int index = layer->GetParamAsInt("index");
    if (!::details::equal(layer->type, "memory") && index)
        THROW_IE_EXCEPTION
                << "Failed to init reshape launcher: layer type (`" + layer->type + "`) is not `Memory` as output";
    if (!layer->outData.empty())
        THROW_IE_EXCEPTION << "Failed to init reshape launcher: "
                           << "layer type (`" + layer->type +
                              "`) is supposed to not have outputs, but actually it has";
}

OutputController* OutMemoryInitializer::createOutputController(const CNNLayer* layer) {
    return nullptr;
}

OutMemoryReshapeLauncher::OutMemoryReshapeLauncher(const CNNLayer* layer, const IShapeInferImpl::Ptr& impl)
        : ReshapeLauncher(layer, impl, std::make_shared<OutMemoryInitializer>()) {
}

void OutMemoryReshapeLauncher::applyChanges(CNNLayer* layer) {
    checkLayer(layer);
    _iController->applyChanges();
}

void OutMemoryReshapeLauncher::reset() {
    _iController->reset();
}