blob: c471615ee8a74a8d713cae11e8fd5b629c79cc79 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Georgios Pinitasb14a0f02021-01-08 03:14:31 +00002 * Copyright (c) 2016-2021 Arm Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "arm_compute/core/TensorInfo.h"
25
26#include "arm_compute/core/Error.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010027#include "arm_compute/core/Helpers.h"
Michel Iwaniec00633802017-10-12 14:14:15 +010028#include "arm_compute/core/TensorInfo.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010029#include "arm_compute/core/Validate.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010030#include "src/core/helpers/Utils.h"
Georgios Pinitas40f51a62020-11-21 03:04:18 +000031
32#include <memory>
Anthony Barbier6ff3b192017-09-04 18:44:23 +010033
Pablo Marquez Tello9ac7b992021-09-15 10:14:20 +010034using namespace arm_compute;
35
Anthony Barbier6ff3b192017-09-04 18:44:23 +010036TensorInfo::TensorInfo()
Georgios Pinitasb14a0f02021-01-08 03:14:31 +000037 : _total_size(0), _offset_first_element_in_bytes(0), _strides_in_bytes(), _num_channels(0), _tensor_shape(), _dims_state(), _data_type(DataType::UNKNOWN), _format(Format::UNKNOWN), _is_resizable{ true },
Pablo Marquez Tello9ac7b992021-09-15 10:14:20 +010038 _valid_region{ Coordinates(), _tensor_shape }, _padding{ 0 }, _quantization_info(), _data_layout(DataLayout::NCHW)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010039{
40}
41
42TensorInfo::TensorInfo(const ITensorInfo &info)
43 : TensorInfo()
44{
45 _total_size = info.total_size();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010046 _offset_first_element_in_bytes = info.offset_first_element_in_bytes();
47 _strides_in_bytes = info.strides_in_bytes();
48 _num_channels = info.num_channels();
49 _tensor_shape = info.tensor_shape();
Georgios Pinitasb14a0f02021-01-08 03:14:31 +000050 _dims_state = info.tensor_dims_state();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010051 _data_type = info.data_type();
52 _format = info.format();
53 _is_resizable = info.is_resizable();
54 _valid_region = info.valid_region();
55 _padding = info.padding();
Georgios Pinitas30902ed2017-11-14 15:32:57 +000056 _quantization_info = info.quantization_info();
Isabella Gottardid17a6772018-02-27 17:41:55 +000057 _data_layout = info.data_layout();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010058}
59
60TensorInfo::TensorInfo(Format format)
61 : TensorInfo(TensorShape(), format)
62{
63}
64
65TensorInfo::TensorInfo(unsigned int width, unsigned int height, Format format)
66 : TensorInfo(TensorShape(width, height), format)
67{
68}
69
70TensorInfo::TensorInfo(const TensorShape &tensor_shape, Format format)
71 : TensorInfo()
72{
73 init(tensor_shape, format);
74}
75
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010076TensorInfo::TensorInfo(size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010077 : TensorInfo()
78{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010079 init(TensorShape(), num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010080}
81
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010082TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010083 : TensorInfo()
84{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010085 init(tensor_shape, num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010086}
87
Michel Iwaniec00633802017-10-12 14:14:15 +010088TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, QuantizationInfo quantization_info)
89 : TensorInfo()
90{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010091 init(tensor_shape, num_channels, data_type);
Michalis Spyrou18574c12019-06-05 10:51:07 +010092 _quantization_info = std::move(quantization_info);
Michel Iwaniec00633802017-10-12 14:14:15 +010093}
94
Manuel Bottini581f1782019-11-13 17:24:43 +000095TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, DataLayout data_layout)
96 : TensorInfo()
97{
98 init(tensor_shape, num_channels, data_type);
99 _data_layout = data_layout;
100}
101
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100102void TensorInfo::init(Format format)
103{
104 init(TensorShape(), format);
105}
106
107void TensorInfo::init(const TensorShape &tensor_shape, Format format)
108{
109 size_t num_channels = num_channels_from_format(format);
110 const DataType type = data_type_from_format(format);
111
112 init(tensor_shape, num_channels, type);
113
114 _format = format;
115}
116
117void TensorInfo::init(const TensorShape &tensor_shape, Format format,
118 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
119 size_t total_size_in_bytes)
120{
121 size_t num_channels = num_channels_from_format(format);
122 const DataType type = data_type_from_format(format);
123
124 init(tensor_shape, num_channels, type, strides_in_bytes, offset_first_element_in_bytes, total_size_in_bytes);
125
126 _format = format;
127}
128
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100129void TensorInfo::init(size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100130{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100131 init(TensorShape(), num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100132}
133
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100134void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100135{
136 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100137
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100138 _data_type = data_type;
139 _num_channels = num_channels;
140 _format = Format::UNKNOWN;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100141
142 set_tensor_shape(tensor_shape);
143}
144
145void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type,
146 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100147 size_t total_size_in_bytes)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100148{
149 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100150
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100151 _data_type = data_type;
152 _num_channels = num_channels;
153 _format = Format::UNKNOWN;
154 _tensor_shape = tensor_shape;
155 _offset_first_element_in_bytes = offset_first_element_in_bytes;
156 _strides_in_bytes = strides_in_bytes;
157 _total_size = total_size_in_bytes;
158
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000159 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100160}
161
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100162size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, Format format)
163{
164 const size_t num_channels = num_channels_from_format(format);
165 const DataType type = data_type_from_format(format);
166 size_t total_size = init_auto_padding(tensor_shape, num_channels, type);
167
168 _format = format;
169
170 return total_size;
171}
172
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100173size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100174{
175 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100176
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100177 _data_type = data_type;
178 _num_channels = num_channels;
179 _format = Format::UNKNOWN;
180 _tensor_shape = tensor_shape;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100181
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000182 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100183
184 auto_padding();
185
186 return _total_size;
187}
188
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100189bool TensorInfo::auto_padding()
190{
191 ARM_COMPUTE_ERROR_ON(!_is_resizable);
192
193 // Some kernels compute 32 elements at the time, worst case scenario they
194 // will read 32 values after the last element
195 const size_t extra_pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 32;
196 const size_t pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 4;
197 const size_t pad_y = _tensor_shape.num_dimensions() < 2 ? 0 : 4;
198
199 return extend_padding(PaddingSize(pad_y, pad_x + extra_pad_x, pad_y, pad_x));
200}
201
202std::tuple<Strides, size_t, size_t> TensorInfo::calculate_padding_requirements(const PaddingSize &padding)
203{
204 // Calculate resulting stride for the X, Y and Z dimension
205 const size_t stride_x = element_size();
206 const size_t stride_y = (padding.left + _tensor_shape[0] + padding.right) * stride_x;
207 const size_t stride_z = (padding.top + _tensor_shape[1] + padding.bottom) * stride_y;
208
209 Strides required_strides;
210 size_t required_total_size = 0;
211 const size_t required_offset_first_element = padding.left * stride_x + padding.top * stride_y;
212
213 switch(_tensor_shape.num_dimensions())
214 {
215 case 0:
216 {
217 if(_tensor_shape.total_size() > 0)
218 {
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100219 required_strides = Strides(stride_x, stride_x);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100220 required_total_size = stride_z;
221 }
222 break;
223 }
224 case 1:
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100225 required_strides = compute_strides(*this, stride_x, stride_y);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100226 required_total_size = stride_z;
227 break;
228 case 2:
229 required_strides = compute_strides(*this, stride_x, stride_y);
230 required_total_size = stride_z;
231 break;
232 default:
233 {
234 required_strides = compute_strides(*this, stride_x, stride_y, stride_z);
235
236 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
237
Sheri Zhanga3e6b6d2020-08-18 10:07:35 +0100238 required_total_size = static_cast<size_t>(_tensor_shape[idx_last_dimension]) * required_strides[idx_last_dimension];
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100239 break;
240 }
241 }
242
243 return std::make_tuple(required_strides, required_offset_first_element, required_total_size);
244}
245
246bool TensorInfo::extend_padding(const PaddingSize &padding)
247{
248 ARM_COMPUTE_ERROR_ON(!_is_resizable);
249
250 bool updated = false;
251
252 if(padding.top > _padding.top)
253 {
254 _padding.top = padding.top;
255 updated = true;
256 }
257
258 if(padding.right > _padding.right)
259 {
260 _padding.right = padding.right;
261 updated = true;
262 }
263
264 if(padding.bottom > _padding.bottom)
265 {
266 _padding.bottom = padding.bottom;
267 updated = true;
268 }
269
270 if(padding.left > _padding.left)
271 {
272 _padding.left = padding.left;
273 updated = true;
274 }
275
276 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
277
278 return updated;
279}
280
Georgios Pinitas283c1792017-11-10 18:14:06 +0000281std::unique_ptr<ITensorInfo> TensorInfo::clone() const
282{
Georgios Pinitas40f51a62020-11-21 03:04:18 +0000283 return std::make_unique<TensorInfo>(*this);
Georgios Pinitas283c1792017-11-10 18:14:06 +0000284}
285
286ITensorInfo &TensorInfo::set_data_type(DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100287{
288 _data_type = data_type;
289 _format = Format::UNKNOWN;
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100290 return set_tensor_shape(tensor_shape()); // Force total size and strides to update
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100291}
292
Georgios Pinitas283c1792017-11-10 18:14:06 +0000293ITensorInfo &TensorInfo::set_num_channels(int num_channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100294{
295 _num_channels = num_channels;
296 _format = Format::UNKNOWN;
Georgios Pinitas283c1792017-11-10 18:14:06 +0000297 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100298}
299
Georgios Pinitas283c1792017-11-10 18:14:06 +0000300ITensorInfo &TensorInfo::set_format(Format format)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100301{
302 _format = format;
303
304 if(_data_type == DataType::UNKNOWN)
305 {
306 _num_channels = num_channels_from_format(format);
307 _data_type = data_type_from_format(format);
308 }
309 else
310 {
311 ARM_COMPUTE_ERROR_ON(num_channels_from_format(format) != _num_channels);
312 ARM_COMPUTE_ERROR_ON(data_type_from_format(format) != _data_type);
313 }
Georgios Pinitas283c1792017-11-10 18:14:06 +0000314 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100315}
316
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000317ITensorInfo &TensorInfo::set_tensor_shape(const TensorShape &shape)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100318{
319 _tensor_shape = shape;
320 _offset_first_element_in_bytes = 0;
321 _strides_in_bytes = compute_strides(*this);
322
323 if(_tensor_shape.num_dimensions() == 0)
324 {
325 _total_size = _strides_in_bytes[0];
326 }
327 else
328 {
329 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
Sheri Zhanga3e6b6d2020-08-18 10:07:35 +0100330 _total_size = static_cast<size_t>(_tensor_shape[idx_last_dimension]) * _strides_in_bytes[idx_last_dimension];
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100331 }
332
Georgios Pinitas652bde52018-01-10 15:33:28 +0000333 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
334
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000335 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Georgios Pinitas283c1792017-11-10 18:14:06 +0000336 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100337}
338
Georgios Pinitasb14a0f02021-01-08 03:14:31 +0000339ITensorInfo &TensorInfo::set_tensor_dims_state(const TensorDimsState &state)
340{
341 _dims_state = state;
342 return *this;
343}
344
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000345ITensorInfo &TensorInfo::set_quantization_info(const QuantizationInfo &quantization_info)
Georgios Pinitas283c1792017-11-10 18:14:06 +0000346{
347 _quantization_info = quantization_info;
348 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100349}
350
Isabella Gottardid17a6772018-02-27 17:41:55 +0000351ITensorInfo &TensorInfo::set_data_layout(const DataLayout &data_layout)
352{
353 _data_layout = data_layout;
354 return *this;
355}
356
Georgios Pinitas30902ed2017-11-14 15:32:57 +0000357ITensorInfo &TensorInfo::reset_padding()
358{
359 _padding = PaddingSize();
360 if(((_format != Format::UNKNOWN) || (_data_type != DataType::UNKNOWN)) && _total_size != 0)
361 {
362 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
363 }
364 return *this;
365}
366
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100367int32_t TensorInfo::offset_element_in_bytes(const Coordinates &pos) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100368{
369 ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());
370
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100371 int32_t offset = _offset_first_element_in_bytes;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100372
373 for(size_t i = 0; i < _tensor_shape.num_dimensions(); ++i)
374 {
375 offset += pos[i] * _strides_in_bytes[i];
376 }
377
378 return offset;
379}