1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
5 #include <vpu/sw/post_op_stage.hpp>
9 #include <vpu/model/edges.hpp>
10 #include <vpu/model/data.hpp>
14 DataMap<float> PostOpStage::propagateScaleFactorsImpl(
15 const DataMap<float>&,
16 ScalePropagationStep) {
17 IE_ASSERT(!_inputEdges.empty());
18 IE_ASSERT(_outputEdges.size() == 1);
20 auto output = _outputEdges[0]->output();
24 // By default, assume no scale propagation.
25 for (const auto& inEdge : _inputEdges) {
26 out[inEdge->input()] = 1.0f;
33 DataMap<DimsOrder> PostOpStage::propagateDataOrderImpl() const {
34 IE_ASSERT(!_inputEdges.empty());
35 IE_ASSERT(_outputEdges.size() == 1);
37 // Non-zero-port inputs are constant (scales/biases).
38 for (const auto& inEdge : _inputEdges) {
39 if (inEdge->portInd() > 0) {
40 IE_ASSERT(inEdge->input()->usage() == DataUsage::Const);
44 auto input = _inputEdges[0]->input();
45 auto output = _outputEdges[0]->output();
47 DataMap<DimsOrder> out;
49 auto inDimsOrder = input->desc().dimsOrder();
51 // TODO: support HCW on firmware side
52 if (inDimsOrder.dimInd(Dim::C) == 1) {
53 inDimsOrder = inDimsOrder.createMovedDim(Dim::C, 2); // CHW
54 out[input] = inDimsOrder;
57 out[output] = inDimsOrder;
62 DataMap<StridesRequirement> PostOpStage::getDataStridesRequirementsImpl() const {
63 IE_ASSERT(!_inputEdges.empty());
64 IE_ASSERT(_outputEdges.size() == 1);
66 // Non-zero-port inputs are constant (scales/biases).
67 for (const auto& inEdge : _inputEdges) {
68 if (inEdge->portInd() > 0) {
69 IE_ASSERT(inEdge->input()->usage() == DataUsage::Const);
73 auto input = _inputEdges[0]->input();
74 auto output = _outputEdges[0]->output();
76 DataMap<StridesRequirement> out;
78 StridesRequirement reqs;
80 // Current PostOp implementation requires Compact major stride.
81 reqs.add(2, DimStride::Compact);
83 if (input->desc().dim(Dim::N, 1) > 1) {
84 // To merge batch into previous dimension.
85 reqs.add(input->desc().dimsOrder().dimInd(Dim::N), DimStride::Compact);
94 void PostOpStage::finalizeDataLayoutImpl() {
97 DataMap<BatchSupport> PostOpStage::getBatchSupportInfoImpl() const {
98 IE_ASSERT(!_inputEdges.empty());
99 IE_ASSERT(_outputEdges.size() == 1);
101 // Non-zero-port inputs are constant (scales/biases).
102 for (const auto& inEdge : _inputEdges) {
103 if (inEdge->portInd() > 0) {
104 IE_ASSERT(inEdge->input()->usage() == DataUsage::Const);
108 auto mainDesc = _inputEdges[0]->input()->desc();
110 DataMap<BatchSupport> out;
112 // PostOp will support batch by merging it with previous dimension.
113 for (const auto& inEdge : _inputEdges) {
114 auto input = inEdge->input();
116 if (inEdge->portInd() == 0)
119 if (input->desc().dimsOrder().dimInd(Dim::C) == input->desc().numDims() - 2) {
120 IE_ASSERT(input->desc().totalDimSize() == input->desc().dim(Dim::C));
121 out[input] = BatchSupport::ReplicateConstContent;
128 StageSHAVEsRequirements PostOpStage::getSHAVEsRequirementsImpl() const {
129 // TODO: more SHAVEs leads to hang on public MTCNN network with U8 input
130 return StageSHAVEsRequirements::TwoOrOne;
133 void PostOpStage::finalCheckImpl() const {
136 void PostOpStage::serializeDataImpl(BlobSerializer& serializer) const {
137 IE_ASSERT(!_inputEdges.empty());
138 IE_ASSERT(_outputEdges.size() == 1);
139 IE_ASSERT(_tempBufferEdges.empty());
141 auto input = _inputEdges[0]->input();
142 auto output = _outputEdges[0]->output();
144 if (input->desc().dimsOrder() == DimsOrder::NC) {
145 input->serializeOldBuffer(
154 output->serializeOldBuffer(
162 } else if (input->desc().dim(Dim::N, 1) > 1) {
163 auto perm = input->desc().dimsOrder().toPermutation();
164 IE_ASSERT(perm.size() == 4);
166 input->serializeOldBuffer(
171 {Dim::H, {perm[2], perm[3]}},
176 output->serializeOldBuffer(
181 {Dim::H, {perm[2], perm[3]}},
186 input->serializeOldBuffer(handle_from_this(), serializer);
188 output->serializeOldBuffer(handle_from_this(), serializer);
191 for (int i = 1; i < _inputEdges.size(); ++i) {
192 _inputEdges[i]->input()->serializeOldBuffer(handle_from_this(), serializer);