blob: b77a47e3e133deb00b2cee142299279d1aa0e014 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Georgios Pinitas652bde52018-01-10 15:33:28 +00002 * Copyright (c) 2016-2018 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"
Georgios Pinitas283c1792017-11-10 18:14:06 +000031#include "support/ToolchainSupport.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010032
33using namespace arm_compute;
34
35TensorInfo::TensorInfo()
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +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 },
37 _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();
52 _valid_region = info.valid_region();
53 _padding = info.padding();
Georgios Pinitas30902ed2017-11-14 15:32:57 +000054 _quantization_info = info.quantization_info();
Isabella Gottardid17a6772018-02-27 17:41:55 +000055 _data_layout = info.data_layout();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010056}
57
58TensorInfo::TensorInfo(Format format)
59 : TensorInfo(TensorShape(), format)
60{
61}
62
63TensorInfo::TensorInfo(unsigned int width, unsigned int height, Format format)
64 : TensorInfo(TensorShape(width, height), format)
65{
66}
67
68TensorInfo::TensorInfo(const TensorShape &tensor_shape, Format format)
69 : TensorInfo()
70{
71 init(tensor_shape, format);
72}
73
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010074TensorInfo::TensorInfo(size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010075 : TensorInfo()
76{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010077 init(TensorShape(), num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010078}
79
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010080TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010081 : TensorInfo()
82{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010083 init(tensor_shape, num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010084}
85
Michel Iwaniec00633802017-10-12 14:14:15 +010086TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, QuantizationInfo quantization_info)
87 : TensorInfo()
88{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010089 init(tensor_shape, num_channels, data_type);
Michel Iwaniec00633802017-10-12 14:14:15 +010090 _quantization_info = quantization_info;
91}
92
Anthony Barbier6ff3b192017-09-04 18:44:23 +010093TensorInfo::TensorInfo(const HOGInfo &hog_info, unsigned int width, unsigned int height)
94 : TensorInfo()
95{
96 init(hog_info, width, height);
97}
98
99void TensorInfo::init(Format format)
100{
101 init(TensorShape(), format);
102}
103
104void TensorInfo::init(const TensorShape &tensor_shape, Format format)
105{
106 size_t num_channels = num_channels_from_format(format);
107 const DataType type = data_type_from_format(format);
108
109 init(tensor_shape, num_channels, type);
110
111 _format = format;
112}
113
114void TensorInfo::init(const TensorShape &tensor_shape, Format format,
115 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
116 size_t total_size_in_bytes)
117{
118 size_t num_channels = num_channels_from_format(format);
119 const DataType type = data_type_from_format(format);
120
121 init(tensor_shape, num_channels, type, strides_in_bytes, offset_first_element_in_bytes, total_size_in_bytes);
122
123 _format = format;
124}
125
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100126void TensorInfo::init(size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100127{
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100128 init(TensorShape(), num_channels, data_type);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100129}
130
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100131void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100132{
133 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100134
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100135 _data_type = data_type;
136 _num_channels = num_channels;
137 _format = Format::UNKNOWN;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100138
139 set_tensor_shape(tensor_shape);
140}
141
142void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type,
143 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100144 size_t total_size_in_bytes)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100145{
146 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100147
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100148 _data_type = data_type;
149 _num_channels = num_channels;
150 _format = Format::UNKNOWN;
151 _tensor_shape = tensor_shape;
152 _offset_first_element_in_bytes = offset_first_element_in_bytes;
153 _strides_in_bytes = strides_in_bytes;
154 _total_size = total_size_in_bytes;
155
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000156 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100157}
158
159void TensorInfo::init(const HOGInfo &hog_info, unsigned int width, unsigned int height)
160{
161 // Number of cells for each block
162 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
163
John Richardson684cb0f2018-01-09 11:17:00 +0000164 // Tensor Size = (Number of horizontal block positions) * (Number of vertical block positions)
165 const Size2D num_block_positions_per_img = hog_info.num_block_positions_per_image(Size2D(width, height));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100166
167 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
168 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
169
John Richardson684cb0f2018-01-09 11:17:00 +0000170 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 +0100171}
172
173size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, Format format)
174{
175 const size_t num_channels = num_channels_from_format(format);
176 const DataType type = data_type_from_format(format);
177 size_t total_size = init_auto_padding(tensor_shape, num_channels, type);
178
179 _format = format;
180
181 return total_size;
182}
183
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100184size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, size_t num_channels, DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100185{
186 ARM_COMPUTE_ERROR_ON(num_channels == 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100187
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100188 _data_type = data_type;
189 _num_channels = num_channels;
190 _format = Format::UNKNOWN;
191 _tensor_shape = tensor_shape;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100192
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000193 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100194
195 auto_padding();
196
197 return _total_size;
198}
199
200size_t TensorInfo::init_auto_padding(const HOGInfo &hog_info, unsigned int width, unsigned int height)
201{
202 // Number of cells for each block
203 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
204
John Richardson684cb0f2018-01-09 11:17:00 +0000205 // Tensor Size = (Number of horizontal block positions) * (Number of vertical block positions)
206 const Size2D num_block_positions_per_img = hog_info.num_block_positions_per_image(Size2D(width, height));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100207
208 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
209 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
210
John Richardson684cb0f2018-01-09 11:17:00 +0000211 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 +0100212}
213
214bool TensorInfo::auto_padding()
215{
216 ARM_COMPUTE_ERROR_ON(!_is_resizable);
217
218 // Some kernels compute 32 elements at the time, worst case scenario they
219 // will read 32 values after the last element
220 const size_t extra_pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 32;
221 const size_t pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 4;
222 const size_t pad_y = _tensor_shape.num_dimensions() < 2 ? 0 : 4;
223
224 return extend_padding(PaddingSize(pad_y, pad_x + extra_pad_x, pad_y, pad_x));
225}
226
227std::tuple<Strides, size_t, size_t> TensorInfo::calculate_padding_requirements(const PaddingSize &padding)
228{
229 // Calculate resulting stride for the X, Y and Z dimension
230 const size_t stride_x = element_size();
231 const size_t stride_y = (padding.left + _tensor_shape[0] + padding.right) * stride_x;
232 const size_t stride_z = (padding.top + _tensor_shape[1] + padding.bottom) * stride_y;
233
234 Strides required_strides;
235 size_t required_total_size = 0;
236 const size_t required_offset_first_element = padding.left * stride_x + padding.top * stride_y;
237
238 switch(_tensor_shape.num_dimensions())
239 {
240 case 0:
241 {
242 if(_tensor_shape.total_size() > 0)
243 {
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100244 required_strides = Strides(stride_x, stride_x);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100245 required_total_size = stride_z;
246 }
247 break;
248 }
249 case 1:
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100250 required_strides = compute_strides(*this, stride_x, stride_y);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100251 required_total_size = stride_z;
252 break;
253 case 2:
254 required_strides = compute_strides(*this, stride_x, stride_y);
255 required_total_size = stride_z;
256 break;
257 default:
258 {
259 required_strides = compute_strides(*this, stride_x, stride_y, stride_z);
260
261 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
262
263 required_total_size = _tensor_shape[idx_last_dimension] * required_strides[idx_last_dimension];
264 break;
265 }
266 }
267
268 return std::make_tuple(required_strides, required_offset_first_element, required_total_size);
269}
270
271bool TensorInfo::extend_padding(const PaddingSize &padding)
272{
273 ARM_COMPUTE_ERROR_ON(!_is_resizable);
274
275 bool updated = false;
276
277 if(padding.top > _padding.top)
278 {
279 _padding.top = padding.top;
280 updated = true;
281 }
282
283 if(padding.right > _padding.right)
284 {
285 _padding.right = padding.right;
286 updated = true;
287 }
288
289 if(padding.bottom > _padding.bottom)
290 {
291 _padding.bottom = padding.bottom;
292 updated = true;
293 }
294
295 if(padding.left > _padding.left)
296 {
297 _padding.left = padding.left;
298 updated = true;
299 }
300
301 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
302
303 return updated;
304}
305
Georgios Pinitas283c1792017-11-10 18:14:06 +0000306std::unique_ptr<ITensorInfo> TensorInfo::clone() const
307{
308 return support::cpp14::make_unique<TensorInfo>(*this);
309}
310
311ITensorInfo &TensorInfo::set_data_type(DataType data_type)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100312{
313 _data_type = data_type;
314 _format = Format::UNKNOWN;
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100315 return set_tensor_shape(tensor_shape()); // Force total size and strides to update
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100316}
317
Georgios Pinitas283c1792017-11-10 18:14:06 +0000318ITensorInfo &TensorInfo::set_num_channels(int num_channels)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100319{
320 _num_channels = num_channels;
321 _format = Format::UNKNOWN;
Georgios Pinitas283c1792017-11-10 18:14:06 +0000322 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100323}
324
Georgios Pinitas283c1792017-11-10 18:14:06 +0000325ITensorInfo &TensorInfo::set_format(Format format)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100326{
327 _format = format;
328
329 if(_data_type == DataType::UNKNOWN)
330 {
331 _num_channels = num_channels_from_format(format);
332 _data_type = data_type_from_format(format);
333 }
334 else
335 {
336 ARM_COMPUTE_ERROR_ON(num_channels_from_format(format) != _num_channels);
337 ARM_COMPUTE_ERROR_ON(data_type_from_format(format) != _data_type);
338 }
Georgios Pinitas283c1792017-11-10 18:14:06 +0000339 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100340}
341
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000342ITensorInfo &TensorInfo::set_tensor_shape(const TensorShape &shape)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100343{
344 _tensor_shape = shape;
345 _offset_first_element_in_bytes = 0;
346 _strides_in_bytes = compute_strides(*this);
347
348 if(_tensor_shape.num_dimensions() == 0)
349 {
350 _total_size = _strides_in_bytes[0];
351 }
352 else
353 {
354 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
355 _total_size = _tensor_shape[idx_last_dimension] * _strides_in_bytes[idx_last_dimension];
356 }
357
Georgios Pinitas652bde52018-01-10 15:33:28 +0000358 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
359
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000360 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Georgios Pinitas283c1792017-11-10 18:14:06 +0000361 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100362}
363
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000364ITensorInfo &TensorInfo::set_quantization_info(const QuantizationInfo &quantization_info)
Georgios Pinitas283c1792017-11-10 18:14:06 +0000365{
366 _quantization_info = quantization_info;
367 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100368}
369
Isabella Gottardid17a6772018-02-27 17:41:55 +0000370ITensorInfo &TensorInfo::set_data_layout(const DataLayout &data_layout)
371{
372 _data_layout = data_layout;
373 return *this;
374}
375
Georgios Pinitas30902ed2017-11-14 15:32:57 +0000376ITensorInfo &TensorInfo::reset_padding()
377{
378 _padding = PaddingSize();
379 if(((_format != Format::UNKNOWN) || (_data_type != DataType::UNKNOWN)) && _total_size != 0)
380 {
381 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
382 }
383 return *this;
384}
385
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100386size_t TensorInfo::offset_element_in_bytes(const Coordinates &pos) const
387{
388 ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());
389
390 size_t offset = _offset_first_element_in_bytes;
391
392 for(size_t i = 0; i < _tensor_shape.num_dimensions(); ++i)
393 {
394 offset += pos[i] * _strides_in_bytes[i];
395 }
396
397 return offset;
398}