blob: 5905ba521564a3a6c00a08784caeddd60dac6dd0 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Ramy Elgammald2d93612022-12-22 15:21:03 +00002 * Copyright (c) 2016-2023 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 },
Ramy Elgammald2d93612022-12-22 15:21:03 +000038 _valid_region{ Coordinates(), _tensor_shape }, _padding{ 0 }, _quantization_info(), _data_layout(DataLayout::NCHW), _are_values_constant(true), _id(invalid_tensor_id), _lock_paddings(false)
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();
SiCong Li5a2bc012023-01-12 12:54:49 +000059 _id = info.id();
Ramy Elgammald2d93612022-12-22 15:21:03 +000060 _lock_paddings = info.lock_paddings();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010061}
62
SiCong Lif44bbc52022-08-29 18:25:51 +010063TensorInfo::TensorInfo(const TensorInfo &info)
64 : TensorInfo()
65{
66 _total_size = info.total_size();
67 _offset_first_element_in_bytes = info.offset_first_element_in_bytes();
68 _strides_in_bytes = info.strides_in_bytes();
69 _num_channels = info.num_channels();
70 _tensor_shape = info.tensor_shape();
71 _dims_state = info.tensor_dims_state();
72 _data_type = info.data_type();
73 _format = info.format();
74 _is_resizable = info.is_resizable();
75 _valid_region = info.valid_region();
76 _padding = info.padding();
77 _quantization_info = info.quantization_info();
78 _data_layout = info.data_layout();
79 _are_values_constant = info.are_values_constant();
SiCong Li5a2bc012023-01-12 12:54:49 +000080 _id = info.id();
Ramy Elgammald2d93612022-12-22 15:21:03 +000081 _lock_paddings = false;
SiCong Lif44bbc52022-08-29 18:25:51 +010082}
Anthony Barbier6ff3b192017-09-04 18:44:23 +010083TensorInfo::TensorInfo(Format format)
84 : TensorInfo(TensorShape(), format)
85{
86}
87
88TensorInfo::TensorInfo(unsigned int width, unsigned int height, Format format)
89 : TensorInfo(TensorShape(width, height), format)
90{
91}
92
93TensorInfo::TensorInfo(const TensorShape &tensor_shape, Format format)
94 : TensorInfo()
95{
96 init(tensor_shape, format);
97}
98
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010099TensorInfo::TensorInfo(size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100100 : TensorInfo()
101{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100102 init(TensorShape(), num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100103}
104
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100105TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100106 : TensorInfo()
107{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100108 init(tensor_shape, num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100109}
110
Michel Iwaniec00633802017-10-12 14:14:15 +0100111TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, QuantizationInfo quantization_info)
112 : TensorInfo()
113{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100114 init(tensor_shape, num_channels, data_type);
Michalis Spyrou18574c12019-06-05 10:51:07 +0100115 _quantization_info = std::move(quantization_info);
Michel Iwaniec00633802017-10-12 14:14:15 +0100116}
117
Manuel Bottini581f1782019-11-13 17:24:43 +0000118TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, DataLayout data_layout)
119 : TensorInfo()
120{
121 init(tensor_shape, num_channels, data_type);
122 _data_layout = data_layout;
123}
124
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100125void TensorInfo::init(Format format)
126{
127 init(TensorShape(), format);
128}
129
130void TensorInfo::init(const TensorShape &tensor_shape, Format format)
131{
132 size_t num_channels = num_channels_from_format(format);
133 const DataType type = data_type_from_format(format);
134
135 init(tensor_shape, num_channels, type);
136
137 _format = format;
138}
139
140void TensorInfo::init(const TensorShape &tensor_shape, Format format,
141 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
142 size_t total_size_in_bytes)
143{
144 size_t num_channels = num_channels_from_format(format);
145 const DataType type = data_type_from_format(format);
146
147 init(tensor_shape, num_channels, type, strides_in_bytes, offset_first_element_in_bytes, total_size_in_bytes);
148
149 _format = format;
150}
151
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100152void TensorInfo::init(size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100153{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100154 init(TensorShape(), num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100155}
156
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100157void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100158{
159 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100160
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100161 _data_type = data_type;
162 _num_channels = num_channels;
163 _format = Format::UNKNOWN;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100164
165 set_tensor_shape(tensor_shape);
166}
167
168void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type,
169 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100170 size_t total_size_in_bytes)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100171{
172 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100173
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100174 _data_type = data_type;
175 _num_channels = num_channels;
176 _format = Format::UNKNOWN;
177 _tensor_shape = tensor_shape;
178 _offset_first_element_in_bytes = offset_first_element_in_bytes;
179 _strides_in_bytes = strides_in_bytes;
180 _total_size = total_size_in_bytes;
181
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000182 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100183}
184
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100185size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, Format format)
186{
187 const size_t num_channels = num_channels_from_format(format);
188 const DataType type = data_type_from_format(format);
189 size_t total_size = init_auto_padding(tensor_shape, num_channels, type);
190
191 _format = format;
192
193 return total_size;
194}
195
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100196size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100197{
198 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100199
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100200 _data_type = data_type;
201 _num_channels = num_channels;
202 _format = Format::UNKNOWN;
203 _tensor_shape = tensor_shape;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100204
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000205 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100206
207 auto_padding();
208
209 return _total_size;
210}
211
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100212bool TensorInfo::auto_padding()
213{
214 ARM_COMPUTE_ERROR_ON(!_is_resizable);
215
216 // Some kernels compute 32 elements at the time, worst case scenario they
217 // will read 32 values after the last element
218 const size_t extra_pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 32;
219 const size_t pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 4;
220 const size_t pad_y = _tensor_shape.num_dimensions() < 2 ? 0 : 4;
221
222 return extend_padding(PaddingSize(pad_y, pad_x + extra_pad_x, pad_y, pad_x));
223}
224
225std::tuple<Strides, size_t, size_t> TensorInfo::calculate_padding_requirements(const PaddingSize &padding)
226{
227 // Calculate resulting stride for the X, Y and Z dimension
228 const size_t stride_x = element_size();
229 const size_t stride_y = (padding.left + _tensor_shape[0] + padding.right) * stride_x;
230 const size_t stride_z = (padding.top + _tensor_shape[1] + padding.bottom) * stride_y;
231
232 Strides required_strides;
233 size_t required_total_size = 0;
234 const size_t required_offset_first_element = padding.left * stride_x + padding.top * stride_y;
235
236 switch(_tensor_shape.num_dimensions())
237 {
238 case 0:
239 {
240 if(_tensor_shape.total_size() > 0)
241 {
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100242 required_strides = Strides(stride_x, stride_x);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100243 required_total_size = stride_z;
244 }
245 break;
246 }
247 case 1:
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100248 required_strides = compute_strides(*this, stride_x, stride_y);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100249 required_total_size = stride_z;
250 break;
251 case 2:
252 required_strides = compute_strides(*this, stride_x, stride_y);
253 required_total_size = stride_z;
254 break;
255 default:
256 {
257 required_strides = compute_strides(*this, stride_x, stride_y, stride_z);
258
259 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
260
Sheri Zhanga3e6b6d2020-08-18 10:07:35 +0100261 required_total_size = static_cast<size_t>(_tensor_shape[idx_last_dimension]) * required_strides[idx_last_dimension];
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100262 break;
263 }
264 }
265
266 return std::make_tuple(required_strides, required_offset_first_element, required_total_size);
267}
268
Ramy Elgammald2d93612022-12-22 15:21:03 +0000269ITensorInfo &TensorInfo::set_lock_paddings(bool flag)
270{
271 _lock_paddings = flag;
272 return *this;
273}
274
275bool TensorInfo::lock_paddings() const
276{
277 return _lock_paddings;
278}
279
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100280bool TensorInfo::extend_padding(const PaddingSize &padding)
281{
Ramy Elgammald2d93612022-12-22 15:21:03 +0000282 ARM_COMPUTE_ERROR_ON(_lock_paddings);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100283 ARM_COMPUTE_ERROR_ON(!_is_resizable);
284
285 bool updated = false;
286
287 if(padding.top > _padding.top)
288 {
289 _padding.top = padding.top;
290 updated = true;
291 }
292
293 if(padding.right > _padding.right)
294 {
295 _padding.right = padding.right;
296 updated = true;
297 }
298
299 if(padding.bottom > _padding.bottom)
300 {
301 _padding.bottom = padding.bottom;
302 updated = true;
303 }
304
305 if(padding.left > _padding.left)
306 {
307 _padding.left = padding.left;
308 updated = true;
309 }
310
311 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
312
313 return updated;
314}
315
Georgios Pinitas283c1792017-11-10 18:14:06 +0000316std::unique_ptr<ITensorInfo> TensorInfo::clone() const
317{
Georgios Pinitas40f51a62020-11-21 03:04:18 +0000318 return std::make_unique<TensorInfo>(*this);
Georgios Pinitas283c1792017-11-10 18:14:06 +0000319}
320
321ITensorInfo &TensorInfo::set_data_type(DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100322{
323 _data_type = data_type;
324 _format = Format::UNKNOWN;
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100325 return set_tensor_shape(tensor_shape()); // Force total size and strides to update
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100326}
327
Georgios Pinitas283c1792017-11-10 18:14:06 +0000328ITensorInfo &TensorInfo::set_num_channels(int num_channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100329{
330 _num_channels = num_channels;
331 _format = Format::UNKNOWN;
Georgios Pinitas283c1792017-11-10 18:14:06 +0000332 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100333}
334
Georgios Pinitas283c1792017-11-10 18:14:06 +0000335ITensorInfo &TensorInfo::set_format(Format format)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100336{
337 _format = format;
338
339 if(_data_type == DataType::UNKNOWN)
340 {
341 _num_channels = num_channels_from_format(format);
342 _data_type = data_type_from_format(format);
343 }
344 else
345 {
346 ARM_COMPUTE_ERROR_ON(num_channels_from_format(format) != _num_channels);
347 ARM_COMPUTE_ERROR_ON(data_type_from_format(format) != _data_type);
348 }
Georgios Pinitas283c1792017-11-10 18:14:06 +0000349 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100350}
351
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000352ITensorInfo &TensorInfo::set_tensor_shape(const TensorShape &shape)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100353{
354 _tensor_shape = shape;
355 _offset_first_element_in_bytes = 0;
356 _strides_in_bytes = compute_strides(*this);
357
358 if(_tensor_shape.num_dimensions() == 0)
359 {
360 _total_size = _strides_in_bytes[0];
361 }
362 else
363 {
364 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
Sheri Zhanga3e6b6d2020-08-18 10:07:35 +0100365 _total_size = static_cast<size_t>(_tensor_shape[idx_last_dimension]) * _strides_in_bytes[idx_last_dimension];
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100366 }
367
Georgios Pinitas652bde52018-01-10 15:33:28 +0000368 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
369
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000370 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Georgios Pinitas283c1792017-11-10 18:14:06 +0000371 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100372}
373
Georgios Pinitasb14a0f02021-01-08 03:14:31 +0000374ITensorInfo &TensorInfo::set_tensor_dims_state(const TensorDimsState &state)
375{
376 _dims_state = state;
377 return *this;
378}
379
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000380ITensorInfo &TensorInfo::set_quantization_info(const QuantizationInfo &quantization_info)
Georgios Pinitas283c1792017-11-10 18:14:06 +0000381{
382 _quantization_info = quantization_info;
383 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100384}
385
Isabella Gottardid17a6772018-02-27 17:41:55 +0000386ITensorInfo &TensorInfo::set_data_layout(const DataLayout &data_layout)
387{
388 _data_layout = data_layout;
389 return *this;
390}
391
Georgios Pinitas30902ed2017-11-14 15:32:57 +0000392ITensorInfo &TensorInfo::reset_padding()
393{
394 _padding = PaddingSize();
395 if(((_format != Format::UNKNOWN) || (_data_type != DataType::UNKNOWN)) && _total_size != 0)
396 {
397 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
398 }
399 return *this;
400}
401
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100402int32_t TensorInfo::offset_element_in_bytes(const Coordinates &pos) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100403{
404 ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());
405
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100406 int32_t offset = _offset_first_element_in_bytes;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100407
408 for(size_t i = 0; i < _tensor_shape.num_dimensions(); ++i)
409 {
410 offset += pos[i] * _strides_in_bytes[i];
411 }
412
413 return offset;
414}
Giorgio Arena63e0beb2021-09-24 14:04:27 +0100415} // namespace arm_compute