blob: 9c93ee075793e7e2fdc306e1cb8d2a3ad4d3cd42 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Alex Gilday345ab182018-01-09 11:40:19 +00002 * Copyright (c) 2017, 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#ifndef __ARM_COMPUTE_TEST_TENSOR_LIBRARY_H__
25#define __ARM_COMPUTE_TEST_TENSOR_LIBRARY_H__
26
Anthony Barbier6ff3b192017-09-04 18:44:23 +010027#include "arm_compute/core/Coordinates.h"
28#include "arm_compute/core/Error.h"
29#include "arm_compute/core/Helpers.h"
30#include "arm_compute/core/TensorInfo.h"
31#include "arm_compute/core/TensorShape.h"
32#include "arm_compute/core/Types.h"
33#include "arm_compute/core/Window.h"
SiCong Li86b53332017-08-23 11:02:43 +010034#include "libnpy/npy.hpp"
Moritz Pflanzere49e2662017-07-21 15:55:28 +010035#include "tests/RawTensor.h"
36#include "tests/TensorCache.h"
37#include "tests/Utils.h"
Anthony Barbierf6705ec2017-09-28 12:01:10 +010038#include "tests/framework/Exceptions.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010039
40#include <algorithm>
41#include <cstddef>
42#include <fstream>
43#include <random>
44#include <string>
45#include <type_traits>
SiCong Li86b53332017-08-23 11:02:43 +010046#include <vector>
Anthony Barbier6ff3b192017-09-04 18:44:23 +010047
48namespace arm_compute
49{
50namespace test
51{
52/** Factory class to create and fill tensors.
53 *
54 * Allows to initialise tensors from loaded images or by specifying the shape
55 * explicitly. Furthermore, provides methods to fill tensors with the content of
56 * loaded images or with random values.
57 */
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +010058class AssetsLibrary final
Anthony Barbier6ff3b192017-09-04 18:44:23 +010059{
60public:
John Richardson70f946b2017-10-02 16:52:16 +010061 /** Initialises the library with a @p path to the assets directory.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010062 * Furthermore, sets the seed for the random generator to @p seed.
63 *
John Richardson70f946b2017-10-02 16:52:16 +010064 * @param[in] path Path to load assets from.
Anthony Barbier6ff3b192017-09-04 18:44:23 +010065 * @param[in] seed Seed used to initialise the random number generator.
66 */
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +010067 AssetsLibrary(std::string path, std::random_device::result_type seed);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010068
John Richardson70f946b2017-10-02 16:52:16 +010069 /** Path to assets directory used to initialise library. */
70 std::string path() const;
71
Anthony Barbier6ff3b192017-09-04 18:44:23 +010072 /** Seed that is used to fill tensors with random values. */
73 std::random_device::result_type seed() const;
74
Giorgio Arenafda46182017-06-16 13:57:33 +010075 /** Provides a tensor shape for the specified image.
76 *
77 * @param[in] name Image file used to look up the raw tensor.
78 */
79 TensorShape get_image_shape(const std::string &name);
80
Anthony Barbier6ff3b192017-09-04 18:44:23 +010081 /** Provides a contant raw tensor for the specified image.
82 *
83 * @param[in] name Image file used to look up the raw tensor.
84 */
85 const RawTensor &get(const std::string &name) const;
86
87 /** Provides a raw tensor for the specified image.
88 *
89 * @param[in] name Image file used to look up the raw tensor.
90 */
91 RawTensor get(const std::string &name);
92
93 /** Creates an uninitialised raw tensor with the given @p data_type and @p
94 * num_channels. The shape is derived from the specified image.
95 *
96 * @param[in] name Image file used to initialise the tensor.
97 * @param[in] data_type Data type used to initialise the tensor.
98 * @param[in] num_channels Number of channels used to initialise the tensor.
99 */
100 RawTensor get(const std::string &name, DataType data_type, int num_channels = 1) const;
101
102 /** Provides a contant raw tensor for the specified image after it has been
103 * converted to @p format.
104 *
105 * @param[in] name Image file used to look up the raw tensor.
106 * @param[in] format Format used to look up the raw tensor.
107 */
108 const RawTensor &get(const std::string &name, Format format) const;
109
110 /** Provides a raw tensor for the specified image after it has been
111 * converted to @p format.
112 *
113 * @param[in] name Image file used to look up the raw tensor.
114 * @param[in] format Format used to look up the raw tensor.
115 */
116 RawTensor get(const std::string &name, Format format);
117
118 /** Provides a contant raw tensor for the specified channel after it has
119 * been extracted form the given image.
120 *
121 * @param[in] name Image file used to look up the raw tensor.
122 * @param[in] channel Channel used to look up the raw tensor.
123 *
124 * @note The channel has to be unambiguous so that the format can be
125 * inferred automatically.
126 */
127 const RawTensor &get(const std::string &name, Channel channel) const;
128
129 /** Provides a raw tensor for the specified channel after it has been
130 * extracted form the given image.
131 *
132 * @param[in] name Image file used to look up the raw tensor.
133 * @param[in] channel Channel used to look up the raw tensor.
134 *
135 * @note The channel has to be unambiguous so that the format can be
136 * inferred automatically.
137 */
138 RawTensor get(const std::string &name, Channel channel);
139
140 /** Provides a constant raw tensor for the specified channel after it has
141 * been extracted form the given image formatted to @p format.
142 *
143 * @param[in] name Image file used to look up the raw tensor.
144 * @param[in] format Format used to look up the raw tensor.
145 * @param[in] channel Channel used to look up the raw tensor.
146 */
147 const RawTensor &get(const std::string &name, Format format, Channel channel) const;
148
149 /** Provides a raw tensor for the specified channel after it has been
150 * extracted form the given image formatted to @p format.
151 *
152 * @param[in] name Image file used to look up the raw tensor.
153 * @param[in] format Format used to look up the raw tensor.
154 * @param[in] channel Channel used to look up the raw tensor.
155 */
156 RawTensor get(const std::string &name, Format format, Channel channel);
157
Giorgio Arenaa2611812017-07-21 10:08:48 +0100158 /** Puts garbage values all around the tensor for testing purposes
159 *
160 * @param[in, out] tensor To be filled tensor.
161 * @param[in] distribution Distribution used to fill the tensor's surroundings.
162 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
163 */
164 template <typename T, typename D>
165 void fill_borders_with_garbage(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
166
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100167 /** Fills the specified @p tensor with random values drawn from @p
168 * distribution.
169 *
170 * @param[in, out] tensor To be filled tensor.
171 * @param[in] distribution Distribution used to fill the tensor.
172 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
173 *
174 * @note The @p distribution has to provide operator(Generator &) which
175 * will be used to draw samples.
176 */
177 template <typename T, typename D>
178 void fill(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const;
179
180 /** Fills the specified @p raw tensor with random values drawn from @p
181 * distribution.
182 *
183 * @param[in, out] raw To be filled raw.
184 * @param[in] distribution Distribution used to fill the tensor.
185 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
186 *
187 * @note The @p distribution has to provide operator(Generator &) which
188 * will be used to draw samples.
189 */
190 template <typename D>
191 void fill(RawTensor &raw, D &&distribution, std::random_device::result_type seed_offset) const;
192
193 /** Fills the specified @p tensor with the content of the specified image
194 * converted to the given format.
195 *
196 * @param[in, out] tensor To be filled tensor.
197 * @param[in] name Image file used to fill the tensor.
198 * @param[in] format Format of the image used to fill the tensor.
199 *
200 * @warning No check is performed that the specified format actually
201 * matches the format of the tensor.
202 */
203 template <typename T>
204 void fill(T &&tensor, const std::string &name, Format format) const;
205
206 /** Fills the raw tensor with the content of the specified image
207 * converted to the given format.
208 *
209 * @param[in, out] raw To be filled raw tensor.
210 * @param[in] name Image file used to fill the tensor.
211 * @param[in] format Format of the image used to fill the tensor.
212 *
213 * @warning No check is performed that the specified format actually
214 * matches the format of the tensor.
215 */
216 void fill(RawTensor &raw, const std::string &name, Format format) const;
217
218 /** Fills the specified @p tensor with the content of the specified channel
219 * extracted from the given image.
220 *
221 * @param[in, out] tensor To be filled tensor.
222 * @param[in] name Image file used to fill the tensor.
223 * @param[in] channel Channel of the image used to fill the tensor.
224 *
225 * @note The channel has to be unambiguous so that the format can be
226 * inferred automatically.
227 *
228 * @warning No check is performed that the specified format actually
229 * matches the format of the tensor.
230 */
231 template <typename T>
232 void fill(T &&tensor, const std::string &name, Channel channel) const;
233
234 /** Fills the raw tensor with the content of the specified channel
235 * extracted from the given image.
236 *
237 * @param[in, out] raw To be filled raw tensor.
238 * @param[in] name Image file used to fill the tensor.
239 * @param[in] channel Channel of the image used to fill the tensor.
240 *
241 * @note The channel has to be unambiguous so that the format can be
242 * inferred automatically.
243 *
244 * @warning No check is performed that the specified format actually
245 * matches the format of the tensor.
246 */
247 void fill(RawTensor &raw, const std::string &name, Channel channel) const;
248
249 /** Fills the specified @p tensor with the content of the specified channel
250 * extracted from the given image after it has been converted to the given
251 * format.
252 *
253 * @param[in, out] tensor To be filled tensor.
254 * @param[in] name Image file used to fill the tensor.
255 * @param[in] format Format of the image used to fill the tensor.
256 * @param[in] channel Channel of the image used to fill the tensor.
257 *
258 * @warning No check is performed that the specified format actually
259 * matches the format of the tensor.
260 */
261 template <typename T>
262 void fill(T &&tensor, const std::string &name, Format format, Channel channel) const;
263
264 /** Fills the raw tensor with the content of the specified channel
265 * extracted from the given image after it has been converted to the given
266 * format.
267 *
268 * @param[in, out] raw To be filled raw tensor.
269 * @param[in] name Image file used to fill the tensor.
270 * @param[in] format Format of the image used to fill the tensor.
271 * @param[in] channel Channel of the image used to fill the tensor.
272 *
273 * @warning No check is performed that the specified format actually
274 * matches the format of the tensor.
275 */
276 void fill(RawTensor &raw, const std::string &name, Format format, Channel channel) const;
277
Alex Gilday345ab182018-01-09 11:40:19 +0000278 /** Fills the specified @p tensor with the content of the raw tensor.
279 *
280 * @param[in, out] tensor To be filled tensor.
281 * @param[in] raw Raw tensor used to fill the tensor.
282 *
283 * @warning No check is performed that the specified format actually
284 * matches the format of the tensor.
285 */
286 template <typename T>
287 void fill(T &&tensor, RawTensor raw) const;
288
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100289 /** Fill a tensor with uniform distribution across the range of its type
290 *
291 * @param[in, out] tensor To be filled tensor.
292 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
293 */
294 template <typename T>
295 void fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset) const;
296
297 /** Fill a tensor with uniform distribution across the a specified range
298 *
299 * @param[in, out] tensor To be filled tensor.
300 * @param[in] seed_offset The offset will be added to the global seed before initialising the random generator.
301 * @param[in] low lowest value in the range (inclusive)
302 * @param[in] high highest value in the range (inclusive)
303 *
304 * @note @p low and @p high must be of the same type as the data type of @p tensor
305 */
306 template <typename T, typename D>
307 void fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset, D low, D high) const;
308
SiCong Li86b53332017-08-23 11:02:43 +0100309 /** Fills the specified @p tensor with data loaded from .npy (numpy binary) in specified path.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100310 *
311 * @param[in, out] tensor To be filled tensor.
312 * @param[in] name Data file.
SiCong Li86b53332017-08-23 11:02:43 +0100313 *
314 * @note The numpy array stored in the binary .npy file must be row-major in the sense that it
315 * must store elements within a row consecutively in the memory, then rows within a 2D slice,
316 * then 2D slices within a 3D slice and so on. Note that it imposes no restrictions on what
317 * indexing convention is used in the numpy array. That is, the numpy array can be either fortran
318 * style or C style as long as it adheres to the rule above.
319 *
320 * More concretely, the orders of dimensions for each style are as follows:
321 * C-style (numpy default):
322 * array[HigherDims..., Z, Y, X]
323 * Fortran style:
324 * array[X, Y, Z, HigherDims...]
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100325 */
326 template <typename T>
327 void fill_layer_data(T &&tensor, std::string name) const;
328
329private:
330 // Function prototype to convert between image formats.
331 using Converter = void (*)(const RawTensor &src, RawTensor &dst);
332 // Function prototype to extract a channel from an image.
333 using Extractor = void (*)(const RawTensor &src, RawTensor &dst);
334 // Function prototype to load an image file.
335 using Loader = RawTensor (*)(const std::string &path);
336
337 const Converter &get_converter(Format src, Format dst) const;
338 const Converter &get_converter(DataType src, Format dst) const;
339 const Converter &get_converter(Format src, DataType dst) const;
340 const Converter &get_converter(DataType src, DataType dst) const;
341 const Extractor &get_extractor(Format format, Channel) const;
342 const Loader &get_loader(const std::string &extension) const;
343
344 /** Creates a raw tensor from the specified image.
345 *
346 * @param[in] name To be loaded image file.
347 *
348 * @note If use_single_image is true @p name is ignored and the user image
349 * is loaded instead.
350 */
351 RawTensor load_image(const std::string &name) const;
352
353 /** Provides a raw tensor for the specified image and format.
354 *
355 * @param[in] name Image file used to look up the raw tensor.
356 * @param[in] format Format used to look up the raw tensor.
357 *
358 * If the tensor has already been requested before the cached version will
359 * be returned. Otherwise the tensor will be added to the cache.
360 *
361 * @note If use_single_image is true @p name is ignored and the user image
362 * is loaded instead.
363 */
364 const RawTensor &find_or_create_raw_tensor(const std::string &name, Format format) const;
365
366 /** Provides a raw tensor for the specified image, format and channel.
367 *
368 * @param[in] name Image file used to look up the raw tensor.
369 * @param[in] format Format used to look up the raw tensor.
370 * @param[in] channel Channel used to look up the raw tensor.
371 *
372 * If the tensor has already been requested before the cached version will
373 * be returned. Otherwise the tensor will be added to the cache.
374 *
375 * @note If use_single_image is true @p name is ignored and the user image
376 * is loaded instead.
377 */
378 const RawTensor &find_or_create_raw_tensor(const std::string &name, Format format, Channel channel) const;
379
380 mutable TensorCache _cache{};
381 mutable std::mutex _format_lock{};
382 mutable std::mutex _channel_lock{};
Anthony Barbierac69aa12017-07-03 17:39:37 +0100383 const std::string _library_path;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100384 std::random_device::result_type _seed;
385};
386
387template <typename T, typename D>
Giorgio Arenaa2611812017-07-21 10:08:48 +0100388void AssetsLibrary::fill_borders_with_garbage(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
389{
390 const PaddingSize padding_size = tensor.padding();
391
392 Window window;
393 window.set(0, Window::Dimension(-padding_size.left, tensor.shape()[0] + padding_size.right, 1));
Gian Marco5420b282017-11-29 10:41:38 +0000394 if(tensor.shape().num_dimensions() > 1)
395 {
396 window.set(1, Window::Dimension(-padding_size.top, tensor.shape()[1] + padding_size.bottom, 1));
397 }
Giorgio Arenaa2611812017-07-21 10:08:48 +0100398
399 std::mt19937 gen(_seed);
400
401 execute_window_loop(window, [&](const Coordinates & id)
402 {
403 TensorShape shape = tensor.shape();
404
405 // If outside of valid region
406 if(id.x() < 0 || id.x() >= static_cast<int>(shape.x()) || id.y() < 0 || id.y() >= static_cast<int>(shape.y()))
407 {
408 using ResultType = typename std::remove_reference<D>::type::result_type;
409 const ResultType value = distribution(gen);
410 void *const out_ptr = tensor(id);
411 store_value_with_data_type(out_ptr, value, tensor.data_type());
412 }
413 });
414}
415
416template <typename T, typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100417void AssetsLibrary::fill(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100418{
419 Window window;
420 for(unsigned int d = 0; d < tensor.shape().num_dimensions(); ++d)
421 {
422 window.set(d, Window::Dimension(0, tensor.shape()[d], 1));
423 }
424
425 std::mt19937 gen(_seed + seed_offset);
426
427 //FIXME: Replace with normal loop
428 execute_window_loop(window, [&](const Coordinates & id)
429 {
430 using ResultType = typename std::remove_reference<D>::type::result_type;
431 const ResultType value = distribution(gen);
432 void *const out_ptr = tensor(id);
433 store_value_with_data_type(out_ptr, value, tensor.data_type());
434 });
Giorgio Arenaa2611812017-07-21 10:08:48 +0100435
436 fill_borders_with_garbage(tensor, distribution, seed_offset);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100437}
438
439template <typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100440void AssetsLibrary::fill(RawTensor &raw, D &&distribution, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100441{
442 std::mt19937 gen(_seed + seed_offset);
443
444 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
445 {
446 using ResultType = typename std::remove_reference<D>::type::result_type;
447 const ResultType value = distribution(gen);
448 store_value_with_data_type(raw.data() + offset, value, raw.data_type());
449 }
450}
451
452template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100453void AssetsLibrary::fill(T &&tensor, const std::string &name, Format format) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100454{
455 const RawTensor &raw = get(name, format);
456
457 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
458 {
459 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
460
Moritz Pflanzer82e70a12017-08-08 16:20:45 +0100461 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
462 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100463 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
464 }
465}
466
467template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100468void AssetsLibrary::fill(T &&tensor, const std::string &name, Channel channel) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100469{
470 fill(std::forward<T>(tensor), name, get_format_for_channel(channel), channel);
471}
472
473template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100474void AssetsLibrary::fill(T &&tensor, const std::string &name, Format format, Channel channel) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100475{
476 const RawTensor &raw = get(name, format, channel);
477
478 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
479 {
480 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
481
Moritz Pflanzer82e70a12017-08-08 16:20:45 +0100482 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
483 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100484 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
485 }
486}
487
488template <typename T>
Alex Gilday345ab182018-01-09 11:40:19 +0000489void AssetsLibrary::fill(T &&tensor, RawTensor raw) const
490{
491 for(size_t offset = 0; offset < raw.size(); offset += raw.element_size())
492 {
493 const Coordinates id = index2coord(raw.shape(), offset / raw.element_size());
494
495 const RawTensor::value_type *const raw_ptr = raw.data() + offset;
496 const auto out_ptr = static_cast<RawTensor::value_type *>(tensor(id));
497 std::copy_n(raw_ptr, raw.element_size(), out_ptr);
498 }
499}
500
501template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100502void AssetsLibrary::fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100503{
504 switch(tensor.data_type())
505 {
506 case DataType::U8:
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000507 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100508 {
509 std::uniform_int_distribution<uint8_t> distribution_u8(std::numeric_limits<uint8_t>::lowest(), std::numeric_limits<uint8_t>::max());
510 fill(tensor, distribution_u8, seed_offset);
511 break;
512 }
513 case DataType::S8:
514 case DataType::QS8:
515 {
516 std::uniform_int_distribution<int8_t> distribution_s8(std::numeric_limits<int8_t>::lowest(), std::numeric_limits<int8_t>::max());
517 fill(tensor, distribution_s8, seed_offset);
518 break;
519 }
520 case DataType::U16:
521 {
522 std::uniform_int_distribution<uint16_t> distribution_u16(std::numeric_limits<uint16_t>::lowest(), std::numeric_limits<uint16_t>::max());
523 fill(tensor, distribution_u16, seed_offset);
524 break;
525 }
526 case DataType::S16:
Gian Marco Iodicebdb6b0b2017-06-30 12:21:00 +0100527 case DataType::QS16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100528 {
529 std::uniform_int_distribution<int16_t> distribution_s16(std::numeric_limits<int16_t>::lowest(), std::numeric_limits<int16_t>::max());
530 fill(tensor, distribution_s16, seed_offset);
531 break;
532 }
533 case DataType::U32:
534 {
535 std::uniform_int_distribution<uint32_t> distribution_u32(std::numeric_limits<uint32_t>::lowest(), std::numeric_limits<uint32_t>::max());
536 fill(tensor, distribution_u32, seed_offset);
537 break;
538 }
539 case DataType::S32:
540 {
541 std::uniform_int_distribution<int32_t> distribution_s32(std::numeric_limits<int32_t>::lowest(), std::numeric_limits<int32_t>::max());
542 fill(tensor, distribution_s32, seed_offset);
543 break;
544 }
545 case DataType::U64:
546 {
547 std::uniform_int_distribution<uint64_t> distribution_u64(std::numeric_limits<uint64_t>::lowest(), std::numeric_limits<uint64_t>::max());
548 fill(tensor, distribution_u64, seed_offset);
549 break;
550 }
551 case DataType::S64:
552 {
553 std::uniform_int_distribution<int64_t> distribution_s64(std::numeric_limits<int64_t>::lowest(), std::numeric_limits<int64_t>::max());
554 fill(tensor, distribution_s64, seed_offset);
555 break;
556 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100557 case DataType::F16:
SiCong Li02dfb2c2017-07-27 17:59:20 +0100558 {
559 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
560 std::uniform_real_distribution<float> distribution_f16(-100.f, 100.f);
561 fill(tensor, distribution_f16, seed_offset);
562 break;
563 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100564 case DataType::F32:
565 {
566 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
567 std::uniform_real_distribution<float> distribution_f32(-1000.f, 1000.f);
568 fill(tensor, distribution_f32, seed_offset);
569 break;
570 }
571 case DataType::F64:
572 {
573 // It doesn't make sense to check [-inf, inf], so hard code it to a big number
574 std::uniform_real_distribution<double> distribution_f64(-1000.f, 1000.f);
575 fill(tensor, distribution_f64, seed_offset);
576 break;
577 }
578 case DataType::SIZET:
579 {
580 std::uniform_int_distribution<size_t> distribution_sizet(std::numeric_limits<size_t>::lowest(), std::numeric_limits<size_t>::max());
581 fill(tensor, distribution_sizet, seed_offset);
582 break;
583 }
584 default:
585 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
586 }
587}
588
589template <typename T, typename D>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100590void AssetsLibrary::fill_tensor_uniform(T &&tensor, std::random_device::result_type seed_offset, D low, D high) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100591{
592 switch(tensor.data_type())
593 {
594 case DataType::U8:
Anton Lokhmotovaf6204c2017-11-08 09:34:19 +0000595 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100596 {
597 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint8_t, D>::value));
598 std::uniform_int_distribution<uint8_t> distribution_u8(low, high);
599 fill(tensor, distribution_u8, seed_offset);
600 break;
601 }
602 case DataType::S8:
603 case DataType::QS8:
604 {
605 ARM_COMPUTE_ERROR_ON(!(std::is_same<int8_t, D>::value));
606 std::uniform_int_distribution<int8_t> distribution_s8(low, high);
607 fill(tensor, distribution_s8, seed_offset);
608 break;
609 }
610 case DataType::U16:
611 {
612 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint16_t, D>::value));
613 std::uniform_int_distribution<uint16_t> distribution_u16(low, high);
614 fill(tensor, distribution_u16, seed_offset);
615 break;
616 }
617 case DataType::S16:
Georgios Pinitas21efeb42017-07-04 12:47:17 +0100618 case DataType::QS16:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100619 {
620 ARM_COMPUTE_ERROR_ON(!(std::is_same<int16_t, D>::value));
621 std::uniform_int_distribution<int16_t> distribution_s16(low, high);
622 fill(tensor, distribution_s16, seed_offset);
623 break;
624 }
625 case DataType::U32:
626 {
627 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint32_t, D>::value));
628 std::uniform_int_distribution<uint32_t> distribution_u32(low, high);
629 fill(tensor, distribution_u32, seed_offset);
630 break;
631 }
632 case DataType::S32:
633 {
634 ARM_COMPUTE_ERROR_ON(!(std::is_same<int32_t, D>::value));
635 std::uniform_int_distribution<int32_t> distribution_s32(low, high);
636 fill(tensor, distribution_s32, seed_offset);
637 break;
638 }
639 case DataType::U64:
640 {
641 ARM_COMPUTE_ERROR_ON(!(std::is_same<uint64_t, D>::value));
642 std::uniform_int_distribution<uint64_t> distribution_u64(low, high);
643 fill(tensor, distribution_u64, seed_offset);
644 break;
645 }
646 case DataType::S64:
647 {
648 ARM_COMPUTE_ERROR_ON(!(std::is_same<int64_t, D>::value));
649 std::uniform_int_distribution<int64_t> distribution_s64(low, high);
650 fill(tensor, distribution_s64, seed_offset);
651 break;
652 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100653 case DataType::F16:
654 {
Moritz Pflanzere49e2662017-07-21 15:55:28 +0100655 std::uniform_real_distribution<float> distribution_f16(low, high);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100656 fill(tensor, distribution_f16, seed_offset);
657 break;
658 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100659 case DataType::F32:
660 {
661 ARM_COMPUTE_ERROR_ON(!(std::is_same<float, D>::value));
662 std::uniform_real_distribution<float> distribution_f32(low, high);
663 fill(tensor, distribution_f32, seed_offset);
664 break;
665 }
666 case DataType::F64:
667 {
668 ARM_COMPUTE_ERROR_ON(!(std::is_same<double, D>::value));
669 std::uniform_real_distribution<double> distribution_f64(low, high);
670 fill(tensor, distribution_f64, seed_offset);
671 break;
672 }
673 case DataType::SIZET:
674 {
675 ARM_COMPUTE_ERROR_ON(!(std::is_same<size_t, D>::value));
676 std::uniform_int_distribution<size_t> distribution_sizet(low, high);
677 fill(tensor, distribution_sizet, seed_offset);
678 break;
679 }
680 default:
681 ARM_COMPUTE_ERROR("NOT SUPPORTED!");
682 }
683}
684
685template <typename T>
Moritz Pflanzerfb5aabb2017-07-18 14:39:55 +0100686void AssetsLibrary::fill_layer_data(T &&tensor, std::string name) const
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100687{
688#ifdef _WIN32
689 const std::string path_separator("\\");
Anthony Barbierac69aa12017-07-03 17:39:37 +0100690#else /* _WIN32 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100691 const std::string path_separator("/");
Anthony Barbierac69aa12017-07-03 17:39:37 +0100692#endif /* _WIN32 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100693 const std::string path = _library_path + path_separator + name;
694
SiCong Li86b53332017-08-23 11:02:43 +0100695 std::vector<unsigned long> shape;
696
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100697 // Open file
SiCong Li86b53332017-08-23 11:02:43 +0100698 std::ifstream stream(path, std::ios::in | std::ios::binary);
Anthony Barbierf6705ec2017-09-28 12:01:10 +0100699 if(!stream.good())
700 {
701 throw framework::FileNotFound("Could not load npy file: " + path);
702 }
Anthony Barbier87f21cd2017-11-10 16:27:32 +0000703 std::string header = npy::read_header(stream);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100704
SiCong Li86b53332017-08-23 11:02:43 +0100705 // Parse header
706 bool fortran_order = false;
707 std::string typestr;
Anthony Barbier87f21cd2017-11-10 16:27:32 +0000708 npy::parse_header(header, typestr, fortran_order, shape);
SiCong Li86b53332017-08-23 11:02:43 +0100709
710 // Check if the typestring matches the given one
711 std::string expect_typestr = get_typestring(tensor.data_type());
712 ARM_COMPUTE_ERROR_ON_MSG(typestr != expect_typestr, "Typestrings mismatch");
713
714 // Validate tensor shape
715 ARM_COMPUTE_ERROR_ON_MSG(shape.size() != tensor.shape().num_dimensions(), "Tensor ranks mismatch");
716 if(fortran_order)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100717 {
SiCong Li86b53332017-08-23 11:02:43 +0100718 for(size_t i = 0; i < shape.size(); ++i)
719 {
720 ARM_COMPUTE_ERROR_ON_MSG(tensor.shape()[i] != shape[i], "Tensor dimensions mismatch");
721 }
722 }
723 else
724 {
725 for(size_t i = 0; i < shape.size(); ++i)
726 {
727 ARM_COMPUTE_ERROR_ON_MSG(tensor.shape()[i] != shape[shape.size() - i - 1], "Tensor dimensions mismatch");
728 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100729 }
730
SiCong Li86b53332017-08-23 11:02:43 +0100731 // Read data
732 if(tensor.padding().empty())
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100733 {
SiCong Li86b53332017-08-23 11:02:43 +0100734 // If tensor has no padding read directly from stream.
735 stream.read(reinterpret_cast<char *>(tensor.data()), tensor.size());
736 }
737 else
738 {
739 // If tensor has padding accessing tensor elements through execution window.
740 Window window;
741 window.use_tensor_dimensions(tensor.shape());
742
743 //FIXME : Replace with normal loop
744 execute_window_loop(window, [&](const Coordinates & id)
745 {
746 stream.read(reinterpret_cast<char *>(tensor(id)), tensor.element_size());
747 });
748 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100749}
750} // namespace test
751} // namespace arm_compute
Anthony Barbierac69aa12017-07-03 17:39:37 +0100752#endif /* __ARM_COMPUTE_TEST_TENSOR_LIBRARY_H__ */