updated readme file due to moving CMake scripts to the root folder
[platform/upstream/dldt.git] / inference-engine / src / vpu / graph_transformer / src / hw / utility.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <vpu/hw/utility.hpp>
6
7 #include <string>
8 #include <unordered_map>
9 #include <algorithm>
10
11 #include <ie_parallel.hpp>
12
13 #include <vpu/model/stage.hpp>
14 #include <vpu/utils/numeric.hpp>
15 #include <vpu/utils/profiling.hpp>
16
17 namespace vpu {
18
19 //
20 // HwDescriptors
21 //
22
23 void printTo(std::ostream& os, const HwOpList& hwOps) {
24     os << "[" << std::endl;
25     os << "size=" << hwOps.vec.size() << std::endl;
26     os << "]";
27 }
28
29 void printTo(DotLabel& lbl, const HwOpList& hwOps) {
30     DotLabel subLbl(lbl);
31     subLbl.appendPair("size", hwOps.vec.size());
32 }
33
34 //
35 // HwPaddingInfo
36 //
37
38 HwPaddingInfo getHwPaddingInfo(
39         const DimValues& inDims, const DimValues& outDims,
40         int kernelDimX, int kernelDimY,
41         int kernelStrideX, int kernelStrideY,
42         int padLeft, int padTop) {
43     auto pad_along_x = (outDims[Dim::W] - 1) * kernelStrideX + kernelDimX - inDims[Dim::W];
44     auto pad_along_y = (outDims[Dim::H] - 1) * kernelStrideY + kernelDimY - inDims[Dim::H];
45
46     HwPaddingInfo pad;
47
48     pad.left   = padLeft;
49     pad.right  = std::max(0, pad_along_x - pad.left);
50     pad.top    = padTop;
51     pad.bottom = std::max(0, pad_along_y - pad.top);
52
53     pad.enable = pad.left || pad.right || pad.top || pad.bottom;
54
55     return pad;
56 }
57
58 void printTo(std::ostream& os, const HwPaddingInfo& hwPad) {
59     os << "[" << std::endl;
60     os << "enable=" << hwPad.enable << std::endl;
61     if (hwPad.enable) {
62         os << "left=" << hwPad.left << std::endl;
63         os << "right=" << hwPad.right << std::endl;
64         os << "top=" << hwPad.top << std::endl;
65         os << "bottom=" << hwPad.bottom << std::endl;
66     }
67     os << "]";
68 }
69
70 void printTo(DotLabel& lbl, const HwPaddingInfo& hwPad) {
71     DotLabel subLbl(lbl);
72     subLbl.appendPair("enable", hwPad.enable);
73     if (hwPad.enable) {
74         subLbl.appendPair("left", hwPad.left);
75         subLbl.appendPair("right", hwPad.right);
76         subLbl.appendPair("top", hwPad.top);
77         subLbl.appendPair("bottom", hwPad.bottom);
78     }
79 }
80
81 //
82 // HwWeightsContent
83 //
84
85 HwWeightsContent::HwWeightsContent(const DataContent::Ptr& origContent,
86         const DataDesc& origWeightsDesc,
87         int numInputChannels,
88         int channelStartIndex) :
89         CalculatedDataContent({origContent}),
90         _origWeightsDesc(origWeightsDesc),
91         _numInputChannels(numInputChannels),
92         _channelStartIndex(channelStartIndex) {
93 }
94
95 void HwWeightsContent::fillTempBuf(const SmallVector<DataContent::Ptr, 2>& baseContents, void* tempBuf) const {
96     VPU_PROFILE(HwWeightsContent);
97
98     IE_ASSERT(desc().type() == DataType::FP16);
99     IE_ASSERT(baseContents.size() == 1);
100
101     auto KX = _origWeightsDesc.dim(Dim::W);
102     auto KY = _origWeightsDesc.dim(Dim::H);
103     auto IC = _origWeightsDesc.dim(Dim::C);
104     auto OC = _origWeightsDesc.dim(Dim::N);
105     auto origTotalSize = _origWeightsDesc.totalDimSize();
106
107     auto HW_OC_inner = desc().dim(Dim::W);
108     auto HW_OC_outer = desc().dim(Dim::N);
109     IE_ASSERT(HW_OC_outer * HW_OC_inner >= OC);
110
111     auto HW_K = desc().dim(Dim::H);
112     IE_ASSERT(HW_K == KX * KY);
113
114     IE_ASSERT(_channelStartIndex < IC);
115     auto HW_IC = desc().dim(Dim::C);
116     auto HW_IC_real = std::min(_numInputChannels, IC - _channelStartIndex);
117
118     auto srcData = baseContents[0]->get<fp16_t>();
119     IE_ASSERT(srcData != nullptr);
120
121     auto dstData = static_cast<fp16_t*>(tempBuf);
122
123     IE_ASSERT((_channelStartIndex + HW_IC_real) * HW_K + (OC - 1) * HW_K * IC - 1 < origTotalSize);
124     IE_ASSERT((OC - 1) % HW_OC_inner +
125               (HW_K - 1) * HW_OC_inner +
126               (HW_IC_real - 1) * HW_OC_inner * HW_K +
127               ((OC - 1) / 8) * HW_OC_inner * HW_K * HW_IC < desc().totalDimSize());
128
129     if (KX == 1 && KY == 1) {
130         ie::parallel_for(OC, [=](int oc) {
131             auto oc_inner = oc % HW_OC_inner;
132             auto oc_outer = oc / HW_OC_inner;
133             for (int ic = 0; ic < HW_IC_real; ++ic) {
134                 auto srcInd =
135                         (_channelStartIndex + ic) +
136                         oc * IC;
137                 auto dstInd =
138                         oc_inner +
139                         ic * HW_OC_inner * HW_K +
140                         oc_outer * HW_OC_inner * HW_K * HW_IC;
141
142                 dstData[dstInd] = srcData[srcInd];
143             }
144         });
145     } else {
146         ie::parallel_for(OC, [=](int oc) {
147             auto oc_inner = oc % HW_OC_inner;
148             auto oc_outer = oc / HW_OC_inner;
149             for (int ic = 0; ic < HW_IC_real; ++ic) {
150                 for (int ky = 0; ky < KY; ++ky) {
151                     for (int kx = 0; kx < KX; ++kx) {
152                         auto srcInd =
153                                 (kx + ky * KX) +
154                                 (_channelStartIndex + ic) * HW_K +
155                                 oc * HW_K * IC;
156                         auto dstInd =
157                                 oc_inner +
158                                 (ky * KX + kx) * HW_OC_inner +
159                                 ic * HW_OC_inner * HW_K +
160                                 oc_outer * HW_OC_inner * HW_K * HW_IC;
161
162                         dstData[dstInd] = srcData[srcInd];
163                     }
164                 }
165             }
166         });
167     }
168 }
169 //
170 // calculateHwBufferSize
171 //
172
173 int calculateHwBufferSize(const DimValues& dims, DimsOrder order) {
174     if (order.empty()) {
175         order = DimsOrder::fromNumDims(dims.size());
176     }
177
178     DataDesc desc(DataType::FP16, order, dims);
179
180     if (desc.numDims() > 2) {
181         return calcTotalByteSize(desc, calcStrides(desc, StridesRequirement().add(1, DimStride::Aligned)));
182     } else {
183         IE_ASSERT(desc.dimsOrder() == DimsOrder::NC);
184
185         return calcTotalByteSize(desc, calcStrides(desc, StridesRequirement().add(0, DimStride::Aligned)));
186     }
187 }
188
189 }  // namespace vpu