1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
7 #include "ie_layouts.h"
10 using namespace InferenceEngine;
12 IE_SUPPRESS_DEPRECATED_START
14 static const std::map<Layout, SizeVector> DIM_POSITIONS = {
15 { NCHW, { I_W, I_H, I_C, I_N } },
16 { NHWC, { I_C, I_W, I_H, I_N } }
19 LayoutOffsetCounter::LayoutOffsetCounter(Layout layout, SizeVector dims) : _layout(layout), _dims(dims), _dims_count(dims.size()), _muls(dims.size(), -1) {
21 for (size_t i = 0; i < _dims_count; i++) {
22 size_t index = DIM_POSITIONS.at(layout)[i];
28 LayoutOffsetCounter::LayoutOffsetCounter(const LayoutOffsetCounter & l) {
31 _dims_count = l._dims_count;
35 LayoutOffsetCounter & LayoutOffsetCounter::operator = (const LayoutOffsetCounter & l) {
38 _dims_count = l._dims_count;
44 LayoutOffsetCounter::~LayoutOffsetCounter() {
47 size_t LayoutOffsetCounter::Offset(SizeVector pos) {
49 for (size_t i = 0; i < _dims_count; i++) {
50 res += pos[i] * _muls[i];
56 IE_SUPPRESS_DEPRECATED_END
58 TensorDesc::TensorDesc(const Precision& precision, SizeVector dims, Layout layout): blockingDesc(dims, layout),
59 precision(precision) {
61 this->layout = layout;
64 TensorDesc::TensorDesc(const Precision& precision, Layout layout): blockingDesc(), precision(precision) {
65 this->layout = layout;
68 TensorDesc::TensorDesc(const Precision &precision, SizeVector dims, const BlockingDesc &blockDesc)
69 : dims(dims), blockingDesc(blockDesc), precision(precision) {
70 if (dims.size() != *std::max_element(blockDesc.getOrder().begin(), blockDesc.getOrder().end()) + 1)
71 THROW_IE_EXCEPTION << "Cannot create TensorDesc! Blocked dims are inconsistent with original dims.";
73 layout = Layout::BLOCKED;
74 if (dims.size() == blockingDesc.getBlockDims().size()) {
75 switch (dims.size()) {
77 layout = Layout::SCALAR;
83 if (blockingDesc.getOrder()[0] == 0 && blockingDesc.getOrder()[1] == 1)
89 if (blockingDesc.getOrder()[0] == 0 && blockingDesc.getOrder()[1] == 1 &&
90 blockingDesc.getOrder()[2] == 2) {
95 if (blockingDesc.getOrder()[0] == 0 && blockingDesc.getOrder()[1] == 1 &&
96 blockingDesc.getOrder()[2] == 2 && blockingDesc.getOrder()[3] == 3) {
97 layout = Layout::NCHW;
98 } else if (blockingDesc.getOrder()[0] == 0 && blockingDesc.getOrder()[1] == 2 &&
99 blockingDesc.getOrder()[2] == 3 && blockingDesc.getOrder()[3] == 1) {
100 layout = Layout::NHWC;
104 if (blockingDesc.getOrder()[0] == 0 && blockingDesc.getOrder()[1] == 1 &&
105 blockingDesc.getOrder()[2] == 2 && blockingDesc.getOrder()[3] == 3 &&
106 blockingDesc.getOrder()[4] == 4) {
107 layout = Layout::NCDHW;
108 } else if (blockingDesc.getOrder()[0] == 0 && blockingDesc.getOrder()[1] == 2 &&
109 blockingDesc.getOrder()[2] == 3 && blockingDesc.getOrder()[3] == 4 &&
110 blockingDesc.getOrder()[4] == 1) {
111 layout = Layout::NDHWC;
120 TensorDesc::TensorDesc() {
121 this->layout = Layout::ANY;
122 precision = Precision::UNSPECIFIED;
125 void TensorDesc::setDims(const SizeVector &dims) {
127 if (layout == Layout::BLOCKED) {
128 auto newDims = blockingDesc.getBlockDims();
129 auto newOrder = blockingDesc.getOrder();
130 if (newDims.empty()) newDims = dims;
131 if (newOrder.empty()) {
132 for (size_t i = 0; i < newDims.size(); i++) {
133 newOrder.push_back(i);
136 blockingDesc = BlockingDesc(newDims, newOrder);
138 blockingDesc = BlockingDesc(dims, layout);
142 bool TensorDesc::operator==(const TensorDesc &rhs) const {
143 return blockingDesc == rhs.blockingDesc &&
144 precision == rhs.precision &&
145 layout == rhs.layout &&
149 bool TensorDesc::operator!=(const TensorDesc &rhs) const {
150 return !(*this == rhs);
153 Layout TensorDesc::getLayoutByDims(SizeVector dims) {
154 switch (dims.size()) {
156 return Layout::SCALAR;
166 return Layout::NCDHW;
168 return Layout::BLOCKED;
172 size_t TensorDesc::offset(const SizeVector& v) const {
173 if (layout == Layout::ANY)
174 THROW_IE_EXCEPTION << "Cannot calculate offset for any format!";
176 SizeVector off_v = v;
177 const SizeVector& blockedDims = blockingDesc.getBlockDims();
178 const SizeVector& strides = blockingDesc.getStrides();
179 const SizeVector& order = blockingDesc.getOrder();
181 size_t n_blocked_dims = order.size();
182 if (blockedDims.size() != n_blocked_dims || strides.size() != n_blocked_dims) {
183 THROW_IE_EXCEPTION << "Cannot calculate offset. Incorrect primitive descriptor!";
185 SizeVector blockedShift(n_blocked_dims);
186 for (size_t i = 1; i <= n_blocked_dims; i++) {
187 blockedShift[n_blocked_dims - i] = off_v[order[n_blocked_dims - i]] % blockedDims[n_blocked_dims - i];
188 off_v[order[n_blocked_dims - i]] /= blockedDims[n_blocked_dims - i];
190 size_t offset = blockingDesc.getOffsetPadding();
191 for (int d = 0; d < n_blocked_dims; ++d) {
192 const size_t p = blockedShift[d] + blockingDesc.getOffsetPaddingToData()[d];
193 offset += p * strides[d];
198 size_t TensorDesc::offset(size_t l) const {
199 size_t n_dims = dims.size();
200 SizeVector pos(n_dims);
201 for (int rd = 1; rd <= n_dims; ++rd) {
202 const size_t d = n_dims - rd;
203 const size_t cur_dim = dims[d];
204 pos[d] = l % cur_dim;
210 void TensorDesc::reshape(const SizeVector &dims, Layout layout) {
211 for (auto &padd : blockingDesc.getOffsetPaddingToData()) {
213 THROW_IE_EXCEPTION << "Cannot reshape a non-packaged blob!";
215 if (layout != Layout::ANY) {
216 blockingDesc = BlockingDesc(dims, layout);
217 this->layout = layout;
219 blockingDesc = BlockingDesc(dims, this->layout);
224 void TensorDesc::reshape(const SizeVector &dims, const BlockingDesc &blockDesc) {
225 blockingDesc = blockDesc;
227 this->layout = Layout::BLOCKED;
230 BlockingDesc::BlockingDesc(const SizeVector& block_dims, const SizeVector & order): offsetPadding(0) {
232 if (block_dims.empty() || order.empty()) return;
233 fillDesc(block_dims, order);
236 BlockingDesc::BlockingDesc(): BlockingDesc({}, Layout::ANY) {}
238 BlockingDesc::BlockingDesc(const SizeVector &blocked_dims, const SizeVector &order,
239 size_t offset): BlockingDesc(blocked_dims, order) {
240 this->offsetPadding = offset;
243 BlockingDesc::BlockingDesc(const SizeVector &blocked_dims, const SizeVector &order, size_t offset,
244 SizeVector dimOffsets): BlockingDesc(blocked_dims, order) {
245 this->offsetPadding = offset;
246 if (blocked_dims.size() != dimOffsets.size())
247 THROW_IE_EXCEPTION << "Offsets are not initialized for all dimensions.";
248 this->offsetPaddingToData = dimOffsets;
251 BlockingDesc::BlockingDesc(const SizeVector &blocked_dims, const SizeVector &order, size_t offset,
252 SizeVector dimOffsets, SizeVector strides): BlockingDesc(blocked_dims, order) {
253 this->offsetPadding = offset;
254 if (blocked_dims.size() != strides.size())
255 THROW_IE_EXCEPTION << "Strides are not initialized for all dimensions.";
256 this->strides = strides;
257 if (blocked_dims.size() != dimOffsets.size())
258 THROW_IE_EXCEPTION << "Offsets are not initialized for all dimensions.";
259 this->offsetPaddingToData = dimOffsets;
262 BlockingDesc::BlockingDesc(const SizeVector& dims, Layout layout): offsetPadding(0) {
267 auto checkDims = [](size_t r_size, size_t e_size) {
268 if (r_size != e_size)
269 THROW_IE_EXCEPTION << "Dims and format are inconsistent.";
278 checkDims(dims.size(), 1);
284 checkDims(dims.size(), 4);
285 l_order = {0, 1, 2, 3};
289 checkDims(dims.size(), 5);
290 l_order = {0, 1, 2, 3, 4};
294 checkDims(dims.size(), 4);
295 l_order = {0, 2, 3, 1};
296 l_dims = {dims[0], dims[2], dims[3], dims[1]};
299 checkDims(dims.size(), 5);
300 l_order = {0, 2, 3, 4, 1};
304 checkDims(dims.size(), 3);
309 checkDims(dims.size(), 2);
311 l_dims = {dims[1], dims[2]};
315 checkDims(dims.size(), 2);
319 case Layout::BLOCKED:
321 for (size_t i = 0; i < dims.size(); i++)
322 l_order.push_back(i);
327 fillDesc(l_dims, l_order);
330 void BlockingDesc::fillDesc(const SizeVector& blocked_dims, const SizeVector &order) {
331 if (order.size() != blocked_dims.size())
332 THROW_IE_EXCEPTION << "Cannot fill descriptor. Size of dimensions and order vector don't match.";
333 if (blocked_dims.empty() || order.empty())
334 THROW_IE_EXCEPTION << "Cannot fill descriptor. Dimensions and order vector are empty.";
336 this->blockedDims = blocked_dims;
338 offsetPaddingToData.resize(order.size());
339 strides.resize(order.size());
340 strides[strides.size() - 1] = 1;
341 offsetPaddingToData[offsetPaddingToData.size() - 1] = 0;
342 for (size_t i = 2; i <= order.size(); i++) {
343 offsetPaddingToData[offsetPaddingToData.size() - i] = 0;
344 strides[strides.size() - i] = strides[strides.size() - (i - 1)] * blocked_dims[blocked_dims.size() - (i - 1)];
350 bool BlockingDesc::operator==(const BlockingDesc &rhs) const {
351 return blockedDims == rhs.blockedDims &&
352 strides == rhs.strides &&
353 offsetPaddingToData == rhs.offsetPaddingToData &&
354 order == rhs.order &&
355 offsetPadding == rhs.offsetPadding;
358 bool BlockingDesc::operator!=(const BlockingDesc &rhs) const {
359 return !(*this == rhs);