blob: 91a35315dcd49da8454d7a8ad2c5345ad91fb564 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
2 * Copyright (c) 2016, 2017 ARM Limited.
3 *
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"
29#include "arm_compute/core/Validate.h"
30
31using namespace arm_compute;
32
33TensorInfo::TensorInfo()
34 : _total_size(0), _fixed_point_position(0), _offset_first_element_in_bytes(0), _strides_in_bytes(), _num_channels(0), _tensor_shape(), _data_type(DataType::UNKNOWN), _format(Format::UNKNOWN),
35 _is_resizable{ true }, _valid_region{ Coordinates(), _tensor_shape }, _padding{ 0 }
36{
37}
38
39TensorInfo::TensorInfo(const ITensorInfo &info)
40 : TensorInfo()
41{
42 _total_size = info.total_size();
43 _fixed_point_position = info.fixed_point_position();
44 _offset_first_element_in_bytes = info.offset_first_element_in_bytes();
45 _strides_in_bytes = info.strides_in_bytes();
46 _num_channels = info.num_channels();
47 _tensor_shape = info.tensor_shape();
48 _data_type = info.data_type();
49 _format = info.format();
50 _is_resizable = info.is_resizable();
51 _valid_region = info.valid_region();
52 _padding = info.padding();
53}
54
55TensorInfo::TensorInfo(Format format)
56 : TensorInfo(TensorShape(), format)
57{
58}
59
60TensorInfo::TensorInfo(unsigned int width, unsigned int height, Format format)
61 : TensorInfo(TensorShape(width, height), format)
62{
63}
64
65TensorInfo::TensorInfo(const TensorShape &tensor_shape, Format format)
66 : TensorInfo()
67{
68 init(tensor_shape, format);
69}
70
71TensorInfo::TensorInfo(size_t num_channels, DataType data_type, size_t fixed_point_position)
72 : TensorInfo()
73{
74 init(TensorShape(), num_channels, data_type, fixed_point_position);
75}
76
77TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, int fixed_point_position)
78 : TensorInfo()
79{
80 init(tensor_shape, num_channels, data_type, fixed_point_position);
81}
82
83TensorInfo::TensorInfo(const HOGInfo &hog_info, unsigned int width, unsigned int height)
84 : TensorInfo()
85{
86 init(hog_info, width, height);
87}
88
89void TensorInfo::init(Format format)
90{
91 init(TensorShape(), format);
92}
93
94void TensorInfo::init(const TensorShape &tensor_shape, Format format)
95{
96 size_t num_channels = num_channels_from_format(format);
97 const DataType type = data_type_from_format(format);
98
99 init(tensor_shape, num_channels, type);
100
101 _format = format;
102}
103
104void TensorInfo::init(const TensorShape &tensor_shape, Format format,
105 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
106 size_t total_size_in_bytes)
107{
108 size_t num_channels = num_channels_from_format(format);
109 const DataType type = data_type_from_format(format);
110
111 init(tensor_shape, num_channels, type, strides_in_bytes, offset_first_element_in_bytes, total_size_in_bytes);
112
113 _format = format;
114}
115
116void TensorInfo::init(size_t num_channels, DataType data_type, size_t fixed_point_position)
117{
118 init(TensorShape(), num_channels, data_type, fixed_point_position);
119}
120
121void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, int fixed_point_position)
122{
123 ARM_COMPUTE_ERROR_ON(num_channels == 0);
124 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
125 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
126
127 _fixed_point_position = fixed_point_position;
128 _data_type = data_type;
129 _num_channels = num_channels;
130 _format = Format::UNKNOWN;
131
132 set_tensor_shape(tensor_shape);
133}
134
135void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type,
136 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
137 size_t total_size_in_bytes, int fixed_point_position)
138{
139 ARM_COMPUTE_ERROR_ON(num_channels == 0);
140 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
141 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
142
143 _fixed_point_position = fixed_point_position;
144 _data_type = data_type;
145 _num_channels = num_channels;
146 _format = Format::UNKNOWN;
147 _tensor_shape = tensor_shape;
148 _offset_first_element_in_bytes = offset_first_element_in_bytes;
149 _strides_in_bytes = strides_in_bytes;
150 _total_size = total_size_in_bytes;
151
152 Coordinates coordinates;
153 coordinates.set_num_dimensions(_tensor_shape.num_dimensions());
154 _valid_region = ValidRegion{ coordinates, _tensor_shape };
155}
156
157void TensorInfo::init(const HOGInfo &hog_info, unsigned int width, unsigned int height)
158{
159 // Number of cells for each block
160 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
161
162 // Tensor Size = (Number of horizontal blocks) * (Number of vertical blocks )
163 const Size2D num_blocks_per_img = hog_info.num_blocks_per_image(Size2D(width, height));
164
165 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
166 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
167
168 init(TensorShape(num_blocks_per_img.width, num_blocks_per_img.height), num_channels, DataType::F32);
169}
170
171size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, Format format)
172{
173 const size_t num_channels = num_channels_from_format(format);
174 const DataType type = data_type_from_format(format);
175 size_t total_size = init_auto_padding(tensor_shape, num_channels, type);
176
177 _format = format;
178
179 return total_size;
180}
181
182size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, int fixed_point_position)
183{
184 ARM_COMPUTE_ERROR_ON(num_channels == 0);
185 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
186 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
187
188 _fixed_point_position = fixed_point_position;
189 _data_type = data_type;
190 _num_channels = num_channels;
191 _format = Format::UNKNOWN;
192 _tensor_shape = tensor_shape;
193
194 Coordinates coordinates;
195 coordinates.set_num_dimensions(_tensor_shape.num_dimensions());
196 _valid_region = ValidRegion{ coordinates, _tensor_shape };
197
198 auto_padding();
199
200 return _total_size;
201}
202
203size_t TensorInfo::init_auto_padding(const HOGInfo &hog_info, unsigned int width, unsigned int height)
204{
205 // Number of cells for each block
206 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
207
208 // Tensor Size = (Number of horizontal blocks) * (Number of vertical blocks )
209 const Size2D num_blocks_per_img = hog_info.num_blocks_per_image(Size2D(width, height));
210
211 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
212 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
213
214 return init_auto_padding(TensorShape(num_blocks_per_img.width, num_blocks_per_img.height), num_channels, DataType::F32);
215}
216
217bool TensorInfo::auto_padding()
218{
219 ARM_COMPUTE_ERROR_ON(!_is_resizable);
220
221 // Some kernels compute 32 elements at the time, worst case scenario they
222 // will read 32 values after the last element
223 const size_t extra_pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 32;
224 const size_t pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 4;
225 const size_t pad_y = _tensor_shape.num_dimensions() < 2 ? 0 : 4;
226
227 return extend_padding(PaddingSize(pad_y, pad_x + extra_pad_x, pad_y, pad_x));
228}
229
230std::tuple<Strides, size_t, size_t> TensorInfo::calculate_padding_requirements(const PaddingSize &padding)
231{
232 // Calculate resulting stride for the X, Y and Z dimension
233 const size_t stride_x = element_size();
234 const size_t stride_y = (padding.left + _tensor_shape[0] + padding.right) * stride_x;
235 const size_t stride_z = (padding.top + _tensor_shape[1] + padding.bottom) * stride_y;
236
237 Strides required_strides;
238 size_t required_total_size = 0;
239 const size_t required_offset_first_element = padding.left * stride_x + padding.top * stride_y;
240
241 switch(_tensor_shape.num_dimensions())
242 {
243 case 0:
244 {
245 if(_tensor_shape.total_size() > 0)
246 {
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100247 required_strides = Strides(stride_x, stride_x);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100248 required_total_size = stride_z;
249 }
250 break;
251 }
252 case 1:
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100253 required_strides = compute_strides(*this, stride_x, stride_y);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100254 required_total_size = stride_z;
255 break;
256 case 2:
257 required_strides = compute_strides(*this, stride_x, stride_y);
258 required_total_size = stride_z;
259 break;
260 default:
261 {
262 required_strides = compute_strides(*this, stride_x, stride_y, stride_z);
263
264 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
265
266 required_total_size = _tensor_shape[idx_last_dimension] * required_strides[idx_last_dimension];
267 break;
268 }
269 }
270
271 return std::make_tuple(required_strides, required_offset_first_element, required_total_size);
272}
273
274bool TensorInfo::extend_padding(const PaddingSize &padding)
275{
276 ARM_COMPUTE_ERROR_ON(!_is_resizable);
277
278 bool updated = false;
279
280 if(padding.top > _padding.top)
281 {
282 _padding.top = padding.top;
283 updated = true;
284 }
285
286 if(padding.right > _padding.right)
287 {
288 _padding.right = padding.right;
289 updated = true;
290 }
291
292 if(padding.bottom > _padding.bottom)
293 {
294 _padding.bottom = padding.bottom;
295 updated = true;
296 }
297
298 if(padding.left > _padding.left)
299 {
300 _padding.left = padding.left;
301 updated = true;
302 }
303
304 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
305
306 return updated;
307}
308
309void TensorInfo::set_data_type(DataType data_type)
310{
311 _data_type = data_type;
312 _format = Format::UNKNOWN;
313}
314
315void TensorInfo::set_num_channels(int num_channels)
316{
317 _num_channels = num_channels;
318 _format = Format::UNKNOWN;
319}
320
321void TensorInfo::set_format(Format format)
322{
323 _format = format;
324
325 if(_data_type == DataType::UNKNOWN)
326 {
327 _num_channels = num_channels_from_format(format);
328 _data_type = data_type_from_format(format);
329 }
330 else
331 {
332 ARM_COMPUTE_ERROR_ON(num_channels_from_format(format) != _num_channels);
333 ARM_COMPUTE_ERROR_ON(data_type_from_format(format) != _data_type);
334 }
335}
336
337void TensorInfo::set_tensor_shape(TensorShape shape)
338{
339 _tensor_shape = shape;
340 _offset_first_element_in_bytes = 0;
341 _strides_in_bytes = compute_strides(*this);
342
343 if(_tensor_shape.num_dimensions() == 0)
344 {
345 _total_size = _strides_in_bytes[0];
346 }
347 else
348 {
349 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
350 _total_size = _tensor_shape[idx_last_dimension] * _strides_in_bytes[idx_last_dimension];
351 }
352
353 Coordinates coordinates;
354 coordinates.set_num_dimensions(_tensor_shape.num_dimensions());
355 _valid_region = ValidRegion{ coordinates, _tensor_shape };
356}
357
358void TensorInfo::set_fixed_point_position(int fixed_point_position)
359{
360 ARM_COMPUTE_ERROR_ON(_data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
361 ARM_COMPUTE_ERROR_ON(_data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
362 _fixed_point_position = fixed_point_position;
363}
364
365size_t TensorInfo::offset_element_in_bytes(const Coordinates &pos) const
366{
367 ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());
368
369 size_t offset = _offset_first_element_in_bytes;
370
371 for(size_t i = 0; i < _tensor_shape.num_dimensions(); ++i)
372 {
373 offset += pos[i] * _strides_in_bytes[i];
374 }
375
376 return offset;
377}