blob: 676938a23113d81fcaec16823c1ad063ab9c2368 [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()
36 : _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),
Isabella Gottardid17a6772018-02-27 17:41:55 +000037 _is_resizable{ true }, _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();
45 _fixed_point_position = info.fixed_point_position();
46 _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();
50 _data_type = info.data_type();
51 _format = info.format();
52 _is_resizable = info.is_resizable();
53 _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
75TensorInfo::TensorInfo(size_t num_channels, DataType data_type, size_t fixed_point_position)
76 : TensorInfo()
77{
78 init(TensorShape(), num_channels, data_type, fixed_point_position);
79}
80
81TensorInfo::TensorInfo(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, int fixed_point_position)
82 : TensorInfo()
83{
84 init(tensor_shape, num_channels, data_type, fixed_point_position);
85}
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{
90 init(tensor_shape, num_channels, data_type, 0);
91 _quantization_info = quantization_info;
92}
93
Anthony Barbier6ff3b192017-09-04 18:44:23 +010094TensorInfo::TensorInfo(const HOGInfo &hog_info, unsigned int width, unsigned int height)
95 : TensorInfo()
96{
97 init(hog_info, width, height);
98}
99
100void TensorInfo::init(Format format)
101{
102 init(TensorShape(), format);
103}
104
105void TensorInfo::init(const TensorShape &tensor_shape, Format format)
106{
107 size_t num_channels = num_channels_from_format(format);
108 const DataType type = data_type_from_format(format);
109
110 init(tensor_shape, num_channels, type);
111
112 _format = format;
113}
114
115void TensorInfo::init(const TensorShape &tensor_shape, Format format,
116 const Strides &strides_in_bytes, size_t offset_first_element_in_bytes,
117 size_t total_size_in_bytes)
118{
119 size_t num_channels = num_channels_from_format(format);
120 const DataType type = data_type_from_format(format);
121
122 init(tensor_shape, num_channels, type, strides_in_bytes, offset_first_element_in_bytes, total_size_in_bytes);
123
124 _format = format;
125}
126
127void TensorInfo::init(size_t num_channels, DataType data_type, size_t fixed_point_position)
128{
129 init(TensorShape(), num_channels, data_type, fixed_point_position);
130}
131
132void TensorInfo::init(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, int fixed_point_position)
133{
134 ARM_COMPUTE_ERROR_ON(num_channels == 0);
135 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
136 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
137
138 _fixed_point_position = fixed_point_position;
139 _data_type = data_type;
140 _num_channels = num_channels;
141 _format = Format::UNKNOWN;
142
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,
148 size_t total_size_in_bytes, int fixed_point_position)
149{
150 ARM_COMPUTE_ERROR_ON(num_channels == 0);
151 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
152 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
153
154 _fixed_point_position = fixed_point_position;
155 _data_type = data_type;
156 _num_channels = num_channels;
157 _format = Format::UNKNOWN;
158 _tensor_shape = tensor_shape;
159 _offset_first_element_in_bytes = offset_first_element_in_bytes;
160 _strides_in_bytes = strides_in_bytes;
161 _total_size = total_size_in_bytes;
162
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000163 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100164}
165
166void TensorInfo::init(const HOGInfo &hog_info, unsigned int width, unsigned int height)
167{
168 // Number of cells for each block
169 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
170
John Richardson684cb0f2018-01-09 11:17:00 +0000171 // Tensor Size = (Number of horizontal block positions) * (Number of vertical block positions)
172 const Size2D num_block_positions_per_img = hog_info.num_block_positions_per_image(Size2D(width, height));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100173
174 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
175 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
176
John Richardson684cb0f2018-01-09 11:17:00 +0000177 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 +0100178}
179
180size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, Format format)
181{
182 const size_t num_channels = num_channels_from_format(format);
183 const DataType type = data_type_from_format(format);
184 size_t total_size = init_auto_padding(tensor_shape, num_channels, type);
185
186 _format = format;
187
188 return total_size;
189}
190
191size_t TensorInfo::init_auto_padding(const TensorShape &tensor_shape, size_t num_channels, DataType data_type, int fixed_point_position)
192{
193 ARM_COMPUTE_ERROR_ON(num_channels == 0);
194 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
195 ARM_COMPUTE_ERROR_ON(data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
196
197 _fixed_point_position = fixed_point_position;
198 _data_type = data_type;
199 _num_channels = num_channels;
200 _format = Format::UNKNOWN;
201 _tensor_shape = tensor_shape;
202
Diego Lopez Recasbcbc9702017-12-18 11:28:27 +0000203 _valid_region = ValidRegion{ Coordinates(), _tensor_shape };
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100204
205 auto_padding();
206
207 return _total_size;
208}
209
210size_t TensorInfo::init_auto_padding(const HOGInfo &hog_info, unsigned int width, unsigned int height)
211{
212 // Number of cells for each block
213 const Size2D num_cells_per_block = hog_info.num_cells_per_block();
214
John Richardson684cb0f2018-01-09 11:17:00 +0000215 // Tensor Size = (Number of horizontal block positions) * (Number of vertical block positions)
216 const Size2D num_block_positions_per_img = hog_info.num_block_positions_per_image(Size2D(width, height));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100217
218 // Number of tensor channels = (Number of cells per block) * (Number of bins per cell)
219 const size_t num_channels = num_cells_per_block.area() * hog_info.num_bins();
220
John Richardson684cb0f2018-01-09 11:17:00 +0000221 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 +0100222}
223
224bool TensorInfo::auto_padding()
225{
226 ARM_COMPUTE_ERROR_ON(!_is_resizable);
227
228 // Some kernels compute 32 elements at the time, worst case scenario they
229 // will read 32 values after the last element
230 const size_t extra_pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 32;
231 const size_t pad_x = _tensor_shape.num_dimensions() < 1 ? 0 : 4;
232 const size_t pad_y = _tensor_shape.num_dimensions() < 2 ? 0 : 4;
233
234 return extend_padding(PaddingSize(pad_y, pad_x + extra_pad_x, pad_y, pad_x));
235}
236
237std::tuple<Strides, size_t, size_t> TensorInfo::calculate_padding_requirements(const PaddingSize &padding)
238{
239 // Calculate resulting stride for the X, Y and Z dimension
240 const size_t stride_x = element_size();
241 const size_t stride_y = (padding.left + _tensor_shape[0] + padding.right) * stride_x;
242 const size_t stride_z = (padding.top + _tensor_shape[1] + padding.bottom) * stride_y;
243
244 Strides required_strides;
245 size_t required_total_size = 0;
246 const size_t required_offset_first_element = padding.left * stride_x + padding.top * stride_y;
247
248 switch(_tensor_shape.num_dimensions())
249 {
250 case 0:
251 {
252 if(_tensor_shape.total_size() > 0)
253 {
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100254 required_strides = Strides(stride_x, stride_x);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100255 required_total_size = stride_z;
256 }
257 break;
258 }
259 case 1:
Gian Marco Iodiceee94f6a2017-09-11 17:38:02 +0100260 required_strides = compute_strides(*this, stride_x, stride_y);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100261 required_total_size = stride_z;
262 break;
263 case 2:
264 required_strides = compute_strides(*this, stride_x, stride_y);
265 required_total_size = stride_z;
266 break;
267 default:
268 {
269 required_strides = compute_strides(*this, stride_x, stride_y, stride_z);
270
271 const unsigned int idx_last_dimension = _tensor_shape.num_dimensions() - 1;
272
273 required_total_size = _tensor_shape[idx_last_dimension] * required_strides[idx_last_dimension];
274 break;
275 }
276 }
277
278 return std::make_tuple(required_strides, required_offset_first_element, required_total_size);
279}
280
281bool TensorInfo::extend_padding(const PaddingSize &padding)
282{
283 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{
318 return support::cpp14::make_unique<TensorInfo>(*this);
319}
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;
365 _total_size = _tensor_shape[idx_last_dimension] * _strides_in_bytes[idx_last_dimension];
366 }
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 Pinitas283c1792017-11-10 18:14:06 +0000374ITensorInfo &TensorInfo::set_fixed_point_position(int fixed_point_position)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100375{
376 ARM_COMPUTE_ERROR_ON(_data_type == DataType::QS8 && (fixed_point_position < 1 || fixed_point_position > 6));
377 ARM_COMPUTE_ERROR_ON(_data_type == DataType::QS16 && (fixed_point_position < 1 || fixed_point_position > 14));
378 _fixed_point_position = fixed_point_position;
Georgios Pinitas283c1792017-11-10 18:14:06 +0000379 return *this;
380}
381
Diego Lopez Recas35ceeb22017-12-04 18:56:10 +0000382ITensorInfo &TensorInfo::set_quantization_info(const QuantizationInfo &quantization_info)
Georgios Pinitas283c1792017-11-10 18:14:06 +0000383{
384 _quantization_info = quantization_info;
385 return *this;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100386}
387
Isabella Gottardid17a6772018-02-27 17:41:55 +0000388ITensorInfo &TensorInfo::set_data_layout(const DataLayout &data_layout)
389{
390 _data_layout = data_layout;
391 return *this;
392}
393
Georgios Pinitas30902ed2017-11-14 15:32:57 +0000394ITensorInfo &TensorInfo::reset_padding()
395{
396 _padding = PaddingSize();
397 if(((_format != Format::UNKNOWN) || (_data_type != DataType::UNKNOWN)) && _total_size != 0)
398 {
399 std::tie(_strides_in_bytes, _offset_first_element_in_bytes, _total_size) = calculate_padding_requirements(_padding);
400 }
401 return *this;
402}
403
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100404size_t TensorInfo::offset_element_in_bytes(const Coordinates &pos) const
405{
406 ARM_COMPUTE_ERROR_ON_COORDINATES_DIMENSIONS_GTE(pos, _tensor_shape.num_dimensions());
407
408 size_t offset = _offset_first_element_in_bytes;
409
410 for(size_t i = 0; i < _tensor_shape.num_dimensions(); ++i)
411 {
412 offset += pos[i] * _strides_in_bytes[i];
413 }
414
415 return offset;
416}