blob: e441ddb3a2c53a8738e87bfcb123ddf86a165d70 [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
Giorgio Arena63e0beb2021-09-24 14:04:27 +010034namespace 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 },
Giorgio Arena63e0beb2021-09-24 14:04:27 +010038 _valid_region{ Coordinates(), _tensor_shape }, _padding{ 0 }, _quantization_info(), _data_layout(DataLayout::NCHW), _are_values_constant(true)
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();
Giorgio Arena63e0beb2021-09-24 14:04:27 +010058 _are_values_constant = info.are_values_constant();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010059}
60
61TensorInfo::TensorInfo(Format format)
62 : TensorInfo(TensorShape(), format)
63{
64}
65
66TensorInfo::TensorInfo(unsigned int width, unsigned int height, Format format)
67 : TensorInfo(TensorShape(width, height), format)
68{
69}
70
71TensorInfo::TensorInfo(const TensorShape &tensor_shape, Format format)
72 : TensorInfo()
73{
74 init(tensor_shape, format);
75}
76
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010077TensorInfo::TensorInfo(size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010078 : TensorInfo()
79{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010080 init(TensorShape(), num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010081}
82
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010083TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010084 : TensorInfo()
85{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010086 init(tensor_shape, num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010087}
88
Michel Iwaniec00633802017-10-12 14:14:15 +010089TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, QuantizationInfo quantization_info)
90 : TensorInfo()
91{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010092 init(tensor_shape, num_channels, data_type);
Michalis Spyrou18574c12019-06-05 10:51:07 +010093 _quantization_info = std::move(quantization_info);
Michel Iwaniec00633802017-10-12 14:14:15 +010094}
95
Manuel Bottini581f1782019-11-13 17:24:43 +000096TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, DataLayout data_layout)
97 : TensorInfo()
98{
99 init(tensor_shape, num_channels, data_type);
100 _data_layout = data_layout;
101}
102
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100103void TensorInfo::init(Format format)
104{
105 init(TensorShape(), format);
106}
107
108void TensorInfo::init(const TensorShape &tensor_shape, Format format)
109{
110 size_t num_channels = num_channels_from_format(format);
111 const DataType type = data_type_from_format(format);
112
113 init(tensor_shape, num_channels, type);
114
115 _format = format;
116}
117
118void TensorInfo::init(const TensorShape &tensor_shape, Format format,
119 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
120 size_t total_size_in_bytes)
121{
122 size_t num_channels = num_channels_from_format(format);
123 const DataType type = data_type_from_format(format);
124
125 init(tensor_shape, num_channels, type, strides_in_bytes, offset_first_element_in_bytes, total_size_in_bytes);
126
127 _format = format;
128}
129
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100130void TensorInfo::init(size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100131{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100132 init(TensorShape(), num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100133}
134
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100135void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100136{
137 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100138
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100139 _data_type = data_type;
140 _num_channels = num_channels;
141 _format = Format::UNKNOWN;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100142
143 set_tensor_shape(tensor_shape);
144}
145
146void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type,
147 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100148 size_t total_size_in_bytes)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100149{
150 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100151
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100152 _data_type = data_type;
153 _num_channels = num_channels;
154 _format = Format::UNKNOWN;
155 _tensor_shape = tensor_shape;
156 _offset_first_element_in_bytes = offset_first_element_in_bytes;
157 _strides_in_bytes = strides_in_bytes;
158 _total_size = total_size_in_bytes;
159
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000160 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100161}
162
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100163size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, Format format)
164{
165 const size_t num_channels = num_channels_from_format(format);
166 const DataType type = data_type_from_format(format);
167 size_t total_size = init_auto_padding(tensor_shape, num_channels, type);
168
169 _format = format;
170
171 return total_size;
172}
173
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100174size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100175{
176 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100177
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100178 _data_type = data_type;
179 _num_channels = num_channels;
180 _format = Format::UNKNOWN;
181 _tensor_shape = tensor_shape;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100182
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000183 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100184
185 auto_padding();
186
187 return _total_size;
188}
189
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100190bool TensorInfo::auto_padding()
191{
192 ARM_COMPUTE_ERROR_ON(!_is_resizable);
193
194 // Some kernels compute 32 elements at the time, worst case scenario they
195 // will read 32 values after the last element
196 const size_t extra_pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 32;
197 const size_t pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 4;
198 const size_t pad_y = _tensor_shape.num_dimensions() < 2 ? 0 : 4;
199
200 return extend_padding(PaddingSize(pad_y, pad_x + extra_pad_x, pad_y, pad_x));
201}
202
203std::tuple<Strides, size_t, size_t> TensorInfo::calculate_padding_requirements(const PaddingSize &padding)
204{
205 // Calculate resulting stride for the X, Y and Z dimension
206 const size_t stride_x = element_size();
207 const size_t stride_y = (padding.left + _tensor_shape[0] + padding.right) * stride_x;
208 const size_t stride_z = (padding.top + _tensor_shape[1] + padding.bottom) * stride_y;
209
210 Strides required_strides;
211 size_t required_total_size = 0;
212 const size_t required_offset_first_element = padding.left * stride_x + padding.top * stride_y;
213
214 switch(_tensor_shape.num_dimensions())
215 {
216 case 0:
217 {
218 if(_tensor_shape.total_size() > 0)
219 {
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100220 required_strides = Strides(stride_x, stride_x);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100221 required_total_size = stride_z;
222 }
223 break;
224 }
225 case 1:
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100226 required_strides = compute_strides(*this, stride_x, stride_y);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100227 required_total_size = stride_z;
228 break;
229 case 2:
230 required_strides = compute_strides(*this, stride_x, stride_y);
231 required_total_size = stride_z;
232 break;
233 default:
234 {
235 required_strides = compute_strides(*this, stride_x, stride_y, stride_z);
236
237 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
238
Sheri Zhanga3e6b6d2020-08-18 10:07:35 +0100239 required_total_size = static_cast<size_t>(_tensor_shape[idx_last_dimension]) * required_strides[idx_last_dimension];
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100240 break;
241 }
242 }
243
244 return std::make_tuple(required_strides, required_offset_first_element, required_total_size);
245}
246
247bool TensorInfo::extend_padding(const PaddingSize &padding)
248{
249 ARM_COMPUTE_ERROR_ON(!_is_resizable);
250
251 bool updated = false;
252
253 if(padding.top > _padding.top)
254 {
255 _padding.top = padding.top;
256 updated = true;
257 }
258
259 if(padding.right > _padding.right)
260 {
261 _padding.right = padding.right;
262 updated = true;
263 }
264
265 if(padding.bottom > _padding.bottom)
266 {
267 _padding.bottom = padding.bottom;
268 updated = true;
269 }
270
271 if(padding.left > _padding.left)
272 {
273 _padding.left = padding.left;
274 updated = true;
275 }
276
277 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
278
279 return updated;
280}
281
Georgios Pinitas283c1792017-11-10 18:14:06 +0000282std::unique_ptr<ITensorInfo> TensorInfo::clone() const
283{
Georgios Pinitas40f51a62020-11-21 03:04:18 +0000284 return std::make_unique<TensorInfo>(*this);
Georgios Pinitas283c1792017-11-10 18:14:06 +0000285}
286
287ITensorInfo &TensorInfo::set_data_type(DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100288{
289 _data_type = data_type;
290 _format = Format::UNKNOWN;
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100291 return set_tensor_shape(tensor_shape()); // Force total size and strides to update
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100292}
293
Georgios Pinitas283c1792017-11-10 18:14:06 +0000294ITensorInfo &TensorInfo::set_num_channels(int num_channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100295{
296 _num_channels = num_channels;
297 _format = Format::UNKNOWN;
Georgios Pinitas283c1792017-11-10 18:14:06 +0000298 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100299}
300
Georgios Pinitas283c1792017-11-10 18:14:06 +0000301ITensorInfo &TensorInfo::set_format(Format format)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100302{
303 _format = format;
304
305 if(_data_type == DataType::UNKNOWN)
306 {
307 _num_channels = num_channels_from_format(format);
308 _data_type = data_type_from_format(format);
309 }
310 else
311 {
312 ARM_COMPUTE_ERROR_ON(num_channels_from_format(format) != _num_channels);
313 ARM_COMPUTE_ERROR_ON(data_type_from_format(format) != _data_type);
314 }
Georgios Pinitas283c1792017-11-10 18:14:06 +0000315 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100316}
317
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000318ITensorInfo &TensorInfo::set_tensor_shape(const TensorShape &shape)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100319{
320 _tensor_shape = shape;
321 _offset_first_element_in_bytes = 0;
322 _strides_in_bytes = compute_strides(*this);
323
324 if(_tensor_shape.num_dimensions() == 0)
325 {
326 _total_size = _strides_in_bytes[0];
327 }
328 else
329 {
330 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
Sheri Zhanga3e6b6d2020-08-18 10:07:35 +0100331 _total_size = static_cast<size_t>(_tensor_shape[idx_last_dimension]) * _strides_in_bytes[idx_last_dimension];
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100332 }
333
Georgios Pinitas652bde52018-01-10 15:33:28 +0000334 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
335
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000336 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Georgios Pinitas283c1792017-11-10 18:14:06 +0000337 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100338}
339
Georgios Pinitasb14a0f02021-01-08 03:14:31 +0000340ITensorInfo &TensorInfo::set_tensor_dims_state(const TensorDimsState &state)
341{
342 _dims_state = state;
343 return *this;
344}
345
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000346ITensorInfo &TensorInfo::set_quantization_info(const QuantizationInfo &quantization_info)
Georgios Pinitas283c1792017-11-10 18:14:06 +0000347{
348 _quantization_info = quantization_info;
349 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100350}
351
Isabella Gottardid17a6772018-02-27 17:41:55 +0000352ITensorInfo &TensorInfo::set_data_layout(const DataLayout &data_layout)
353{
354 _data_layout = data_layout;
355 return *this;
356}
357
Georgios Pinitas30902ed2017-11-14 15:32:57 +0000358ITensorInfo &TensorInfo::reset_padding()
359{
360 _padding = PaddingSize();
361 if(((_format != Format::UNKNOWN) || (_data_type != DataType::UNKNOWN)) && _total_size != 0)
362 {
363 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
364 }
365 return *this;
366}
367
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100368int32_t TensorInfo::offset_element_in_bytes(const Coordinates &pos) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100369{
370 ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());
371
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100372 int32_t offset = _offset_first_element_in_bytes;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100373
374 for(size_t i = 0; i < _tensor_shape.num_dimensions(); ++i)
375 {
376 offset += pos[i] * _strides_in_bytes[i];
377 }
378
379 return offset;
380}
Giorgio Arena63e0beb2021-09-24 14:04:27 +0100381} // namespace arm_compute