blob: b86a4cf9241c29d49c50af4536ba0b6e2be3e330 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Matthew Bentham92046462020-03-07 22:15:55 +00002 * Copyright (c) 2016-2020 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"
27#include "arm_compute/core/HOGInfo.h"
28#include "arm_compute/core/Helpers.h"
Michel Iwaniec00633802017-10-12 14:14:15 +010029#include "arm_compute/core/TensorInfo.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010030#include "arm_compute/core/Validate.h"
Matthew Bentham92046462020-03-07 22:15:55 +000031#include "support/MemorySupport.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010032
33using namespace arm_compute;
34
35TensorInfo::TensorInfo()
Georgios Pinitas49be2e32019-09-02 13:18:55 +010036 : _total_size(0), _offset_first_element_in_bytes(0), _strides_in_bytes(), _num_channels(0), _tensor_shape(), _data_type(DataType::UNKNOWN), _format(Format::UNKNOWN), _is_resizable{ true }, _is_dynamic{ false },
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010037 _valid_region{ Coordinates(), _tensor_shape }, _padding{ 0 }, _quantization_info(), _data_layout(DataLayout::NCHW)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010038{
39}
40
41TensorInfo::TensorInfo(const ITensorInfo &info)
42 : TensorInfo()
43{
44 _total_size = info.total_size();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010045 _offset_first_element_in_bytes = info.offset_first_element_in_bytes();
46 _strides_in_bytes = info.strides_in_bytes();
47 _num_channels = info.num_channels();
48 _tensor_shape = info.tensor_shape();
49 _data_type = info.data_type();
50 _format = info.format();
51 _is_resizable = info.is_resizable();
Georgios Pinitas49be2e32019-09-02 13:18:55 +010052 _is_dynamic = info.is_dynamic();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010053 _valid_region = info.valid_region();
54 _padding = info.padding();
Georgios Pinitas30902ed2017-11-14 15:32:57 +000055 _quantization_info = info.quantization_info();
Isabella Gottardid17a6772018-02-27 17:41:55 +000056 _data_layout = info.data_layout();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010057}
58
59TensorInfo::TensorInfo(Format format)
60 : TensorInfo(TensorShape(), format)
61{
62}
63
64TensorInfo::TensorInfo(unsigned int width, unsigned int height, Format format)
65 : TensorInfo(TensorShape(width, height), format)
66{
67}
68
69TensorInfo::TensorInfo(const TensorShape &tensor_shape, Format format)
70 : TensorInfo()
71{
72 init(tensor_shape, format);
73}
74
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010075TensorInfo::TensorInfo(size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010076 : TensorInfo()
77{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010078 init(TensorShape(), num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010079}
80
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010081TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010082 : TensorInfo()
83{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010084 init(tensor_shape, num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010085}
86
Michel Iwaniec00633802017-10-12 14:14:15 +010087TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, QuantizationInfo quantization_info)
88 : TensorInfo()
89{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010090 init(tensor_shape, num_channels, data_type);
Michalis Spyrou18574c12019-06-05 10:51:07 +010091 _quantization_info = std::move(quantization_info);
Michel Iwaniec00633802017-10-12 14:14:15 +010092}
93
Manuel Bottini581f1782019-11-13 17:24:43 +000094TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, DataLayout data_layout)
95 : TensorInfo()
96{
97 init(tensor_shape, num_channels, data_type);
98 _data_layout = data_layout;
99}
100
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100101TensorInfo::TensorInfo(const HOGInfo &hog_info, unsigned int width, unsigned int height)
102 : TensorInfo()
103{
104 init(hog_info, width, height);
105}
106
107void TensorInfo::init(Format format)
108{
109 init(TensorShape(), format);
110}
111
112void TensorInfo::init(const TensorShape &tensor_shape, Format format)
113{
114 size_t num_channels = num_channels_from_format(format);
115 const DataType type = data_type_from_format(format);
116
117 init(tensor_shape, num_channels, type);
118
119 _format = format;
120}
121
122void TensorInfo::init(const TensorShape &tensor_shape, Format format,
123 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
124 size_t total_size_in_bytes)
125{
126 size_t num_channels = num_channels_from_format(format);
127 const DataType type = data_type_from_format(format);
128
129 init(tensor_shape, num_channels, type, strides_in_bytes, offset_first_element_in_bytes, total_size_in_bytes);
130
131 _format = format;
132}
133
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100134void TensorInfo::init(size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100135{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100136 init(TensorShape(), num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100137}
138
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100139void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100140{
141 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100142
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100143 _data_type = data_type;
144 _num_channels = num_channels;
145 _format = Format::UNKNOWN;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100146
147 set_tensor_shape(tensor_shape);
148}
149
150void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type,
151 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100152 size_t total_size_in_bytes)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100153{
154 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100155
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100156 _data_type = data_type;
157 _num_channels = num_channels;
158 _format = Format::UNKNOWN;
159 _tensor_shape = tensor_shape;
160 _offset_first_element_in_bytes = offset_first_element_in_bytes;
161 _strides_in_bytes = strides_in_bytes;
162 _total_size = total_size_in_bytes;
163
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000164 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100165}
166
167void TensorInfo::init(const HOGInfo &hog_info, unsigned int width, unsigned int height)
168{
169 // Number of cells for each block
170 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
171
John Richardson684cb0f2018-01-09 11:17:00 +0000172 // Tensor Size = (Number of horizontal block positions) * (Number of vertical block positions)
173 const Size2D num_block_positions_per_img = hog_info.num_block_positions_per_image(Size2D(width, height));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100174
175 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
176 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
177
John Richardson684cb0f2018-01-09 11:17:00 +0000178 init(TensorShape(num_block_positions_per_img.width, num_block_positions_per_img.height), num_channels, DataType::F32);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100179}
180
181size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, Format format)
182{
183 const size_t num_channels = num_channels_from_format(format);
184 const DataType type = data_type_from_format(format);
185 size_t total_size = init_auto_padding(tensor_shape, num_channels, type);
186
187 _format = format;
188
189 return total_size;
190}
191
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100192size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100193{
194 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100195
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100196 _data_type = data_type;
197 _num_channels = num_channels;
198 _format = Format::UNKNOWN;
199 _tensor_shape = tensor_shape;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100200
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000201 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100202
203 auto_padding();
204
205 return _total_size;
206}
207
208size_t TensorInfo::init_auto_padding(const HOGInfo &hog_info, unsigned int width, unsigned int height)
209{
210 // Number of cells for each block
211 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
212
John Richardson684cb0f2018-01-09 11:17:00 +0000213 // Tensor Size = (Number of horizontal block positions) * (Number of vertical block positions)
214 const Size2D num_block_positions_per_img = hog_info.num_block_positions_per_image(Size2D(width, height));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100215
216 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
217 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
218
John Richardson684cb0f2018-01-09 11:17:00 +0000219 return init_auto_padding(TensorShape(num_block_positions_per_img.width, num_block_positions_per_img.height), num_channels, DataType::F32);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100220}
221
222bool TensorInfo::auto_padding()
223{
224 ARM_COMPUTE_ERROR_ON(!_is_resizable);
225
226 // Some kernels compute 32 elements at the time, worst case scenario they
227 // will read 32 values after the last element
228 const size_t extra_pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 32;
229 const size_t pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 4;
230 const size_t pad_y = _tensor_shape.num_dimensions() < 2 ? 0 : 4;
231
232 return extend_padding(PaddingSize(pad_y, pad_x + extra_pad_x, pad_y, pad_x));
233}
234
235std::tuple<Strides, size_t, size_t> TensorInfo::calculate_padding_requirements(const PaddingSize &padding)
236{
237 // Calculate resulting stride for the X, Y and Z dimension
238 const size_t stride_x = element_size();
239 const size_t stride_y = (padding.left + _tensor_shape[0] + padding.right) * stride_x;
240 const size_t stride_z = (padding.top + _tensor_shape[1] + padding.bottom) * stride_y;
241
242 Strides required_strides;
243 size_t required_total_size = 0;
244 const size_t required_offset_first_element = padding.left * stride_x + padding.top * stride_y;
245
246 switch(_tensor_shape.num_dimensions())
247 {
248 case 0:
249 {
250 if(_tensor_shape.total_size() > 0)
251 {
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100252 required_strides = Strides(stride_x, stride_x);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100253 required_total_size = stride_z;
254 }
255 break;
256 }
257 case 1:
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100258 required_strides = compute_strides(*this, stride_x, stride_y);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100259 required_total_size = stride_z;
260 break;
261 case 2:
262 required_strides = compute_strides(*this, stride_x, stride_y);
263 required_total_size = stride_z;
264 break;
265 default:
266 {
267 required_strides = compute_strides(*this, stride_x, stride_y, stride_z);
268
269 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
270
271 required_total_size = _tensor_shape[idx_last_dimension] * required_strides[idx_last_dimension];
272 break;
273 }
274 }
275
276 return std::make_tuple(required_strides, required_offset_first_element, required_total_size);
277}
278
279bool TensorInfo::extend_padding(const PaddingSize &padding)
280{
281 ARM_COMPUTE_ERROR_ON(!_is_resizable);
282
283 bool updated = false;
284
285 if(padding.top > _padding.top)
286 {
287 _padding.top = padding.top;
288 updated = true;
289 }
290
291 if(padding.right > _padding.right)
292 {
293 _padding.right = padding.right;
294 updated = true;
295 }
296
297 if(padding.bottom > _padding.bottom)
298 {
299 _padding.bottom = padding.bottom;
300 updated = true;
301 }
302
303 if(padding.left > _padding.left)
304 {
305 _padding.left = padding.left;
306 updated = true;
307 }
308
309 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
310
311 return updated;
312}
313
Georgios Pinitas283c1792017-11-10 18:14:06 +0000314std::unique_ptr<ITensorInfo> TensorInfo::clone() const
315{
316 return support::cpp14::make_unique<TensorInfo>(*this);
317}
318
319ITensorInfo &TensorInfo::set_data_type(DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100320{
321 _data_type = data_type;
322 _format = Format::UNKNOWN;
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100323 return set_tensor_shape(tensor_shape()); // Force total size and strides to update
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100324}
325
Georgios Pinitas283c1792017-11-10 18:14:06 +0000326ITensorInfo &TensorInfo::set_num_channels(int num_channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100327{
328 _num_channels = num_channels;
329 _format = Format::UNKNOWN;
Georgios Pinitas283c1792017-11-10 18:14:06 +0000330 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100331}
332
Georgios Pinitas283c1792017-11-10 18:14:06 +0000333ITensorInfo &TensorInfo::set_format(Format format)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100334{
335 _format = format;
336
337 if(_data_type == DataType::UNKNOWN)
338 {
339 _num_channels = num_channels_from_format(format);
340 _data_type = data_type_from_format(format);
341 }
342 else
343 {
344 ARM_COMPUTE_ERROR_ON(num_channels_from_format(format) != _num_channels);
345 ARM_COMPUTE_ERROR_ON(data_type_from_format(format) != _data_type);
346 }
Georgios Pinitas283c1792017-11-10 18:14:06 +0000347 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100348}
349
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000350ITensorInfo &TensorInfo::set_tensor_shape(const TensorShape &shape)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100351{
352 _tensor_shape = shape;
353 _offset_first_element_in_bytes = 0;
354 _strides_in_bytes = compute_strides(*this);
355
356 if(_tensor_shape.num_dimensions() == 0)
357 {
358 _total_size = _strides_in_bytes[0];
359 }
360 else
361 {
362 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
363 _total_size = _tensor_shape[idx_last_dimension] * _strides_in_bytes[idx_last_dimension];
364 }
365
Georgios Pinitas652bde52018-01-10 15:33:28 +0000366 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
367
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000368 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Georgios Pinitas283c1792017-11-10 18:14:06 +0000369 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100370}
371
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000372ITensorInfo &TensorInfo::set_quantization_info(const QuantizationInfo &quantization_info)
Georgios Pinitas283c1792017-11-10 18:14:06 +0000373{
374 _quantization_info = quantization_info;
375 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100376}
377
Isabella Gottardid17a6772018-02-27 17:41:55 +0000378ITensorInfo &TensorInfo::set_data_layout(const DataLayout &data_layout)
379{
380 _data_layout = data_layout;
381 return *this;
382}
383
Georgios Pinitas30902ed2017-11-14 15:32:57 +0000384ITensorInfo &TensorInfo::reset_padding()
385{
386 _padding = PaddingSize();
387 if(((_format != Format::UNKNOWN) || (_data_type != DataType::UNKNOWN)) && _total_size != 0)
388 {
389 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
390 }
391 return *this;
392}
393
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100394int32_t TensorInfo::offset_element_in_bytes(const Coordinates &pos) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100395{
396 ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());
397
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100398 int32_t offset = _offset_first_element_in_bytes;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100399
400 for(size_t i = 0; i < _tensor_shape.num_dimensions(); ++i)
401 {
402 offset += pos[i] * _strides_in_bytes[i];
403 }
404
405 return offset;
406}