blob: 3b09c6b0b7ea09f9f32ef9dc4a8f4a5bb85c5db2 [file] [log] [blame]
Kaizen8938bd32017-09-28 14:38:23 +01001/*
Anthony Barbierf45d5a92018-01-24 16:23:15 +00002 * Copyright (c) 2017-2018 ARM Limited.
Kaizen8938bd32017-09-28 14:38: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_GRAPH_UTILS_H__
25#define __ARM_COMPUTE_GRAPH_UTILS_H__
26
Kaizenbf8b01d2017-10-12 14:26:51 +010027#include "arm_compute/core/PixelValue.h"
Jenkins52ba29e2018-08-29 15:32:11 +000028#include "arm_compute/core/Utils.h"
Jenkinsb3a371b2018-05-23 11:36:53 +010029#include "arm_compute/core/utils/misc/Utility.h"
Anthony Barbier8140e1e2017-12-14 23:48:46 +000030#include "arm_compute/graph/Graph.h"
Kaizen8938bd32017-09-28 14:38:23 +010031#include "arm_compute/graph/ITensorAccessor.h"
32#include "arm_compute/graph/Types.h"
Jenkinsb3a371b2018-05-23 11:36:53 +010033#include "arm_compute/runtime/Tensor.h"
Kaizen8938bd32017-09-28 14:38:23 +010034
Jenkins52ba29e2018-08-29 15:32:11 +000035#include "utils/CommonGraphOptions.h"
36
Anthony Barbier06ea0482018-02-22 15:45:35 +000037#include <array>
Kaizenbf8b01d2017-10-12 14:26:51 +010038#include <random>
Anthony Barbier8a3da6f2017-10-23 18:55:17 +010039#include <string>
40#include <vector>
Kaizenbf8b01d2017-10-12 14:26:51 +010041
Kaizen8938bd32017-09-28 14:38:23 +010042namespace arm_compute
43{
44namespace graph_utils
45{
Anthony Barbier06ea0482018-02-22 15:45:35 +000046/** Preprocessor interface **/
47class IPreprocessor
48{
49public:
Jenkinsb3a371b2018-05-23 11:36:53 +010050 /** Default destructor. */
51 virtual ~IPreprocessor() = default;
52 /** Preprocess the given tensor.
53 *
54 * @param[in] tensor Tensor to preprocess.
55 */
Anthony Barbier06ea0482018-02-22 15:45:35 +000056 virtual void preprocess(ITensor &tensor) = 0;
57};
58
59/** Caffe preproccessor */
60class CaffePreproccessor : public IPreprocessor
61{
62public:
63 /** Default Constructor
64 *
65 * @param mean Mean array in RGB ordering
66 * @param bgr Boolean specifying if the preprocessing should assume BGR format
67 */
68 CaffePreproccessor(std::array<float, 3> mean = std::array<float, 3> { { 0, 0, 0 } }, bool bgr = true);
69 void preprocess(ITensor &tensor) override;
70
71private:
72 std::array<float, 3> _mean;
73 bool _bgr;
74};
75
76/** TF preproccessor */
77class TFPreproccessor : public IPreprocessor
78{
79public:
80 void preprocess(ITensor &tensor) override;
81};
82
Kaizen8938bd32017-09-28 14:38:23 +010083/** PPM writer class */
84class PPMWriter : public graph::ITensorAccessor
85{
86public:
87 /** Constructor
88 *
89 * @param[in] name PPM file name
90 * @param[in] maximum Maximum elements to access
91 */
92 PPMWriter(std::string name, unsigned int maximum = 1);
93 /** Allows instances to move constructed */
94 PPMWriter(PPMWriter &&) = default;
95
96 // Inherited methods overriden:
97 bool access_tensor(ITensor &tensor) override;
98
99private:
100 const std::string _name;
101 unsigned int _iterator;
102 unsigned int _maximum;
103};
104
105/** Dummy accessor class */
Kaizenbf8b01d2017-10-12 14:26:51 +0100106class DummyAccessor final : public graph::ITensorAccessor
Kaizen8938bd32017-09-28 14:38:23 +0100107{
108public:
109 /** Constructor
110 *
111 * @param[in] maximum Maximum elements to write
112 */
113 DummyAccessor(unsigned int maximum = 1);
114 /** Allows instances to move constructed */
115 DummyAccessor(DummyAccessor &&) = default;
116
117 // Inherited methods overriden:
118 bool access_tensor(ITensor &tensor) override;
119
120private:
121 unsigned int _iterator;
122 unsigned int _maximum;
123};
124
Jenkinsb3a371b2018-05-23 11:36:53 +0100125/** NumPy accessor class */
126class NumPyAccessor final : public graph::ITensorAccessor
127{
128public:
129 /** Constructor
130 *
131 * @param[in] npy_path Path to npy file.
132 * @param[in] shape Shape of the numpy tensor data.
133 * @param[in] data_type DataType of the numpy tensor data.
134 * @param[out] output_stream (Optional) Output stream
135 */
136 NumPyAccessor(std::string npy_path, TensorShape shape, DataType data_type, std::ostream &output_stream = std::cout);
137 /** Allow instances of this class to be move constructed */
138 NumPyAccessor(NumPyAccessor &&) = default;
139 /** Prevent instances of this class from being copied (As this class contains pointers) */
140 NumPyAccessor(const NumPyAccessor &) = delete;
141 /** Prevent instances of this class from being copied (As this class contains pointers) */
142 NumPyAccessor &operator=(const NumPyAccessor &) = delete;
143
144 // Inherited methods overriden:
145 bool access_tensor(ITensor &tensor) override;
146
147private:
148 template <typename T>
149 void access_numpy_tensor(ITensor &tensor);
150
151 Tensor _npy_tensor;
152 const std::string _filename;
153 std::ostream &_output_stream;
154};
155
Jenkins52ba29e2018-08-29 15:32:11 +0000156/** Image accessor class */
157class ImageAccessor final : public graph::ITensorAccessor
Anthony Barbier8a3da6f2017-10-23 18:55:17 +0100158{
159public:
160 /** Constructor
161 *
Jenkins52ba29e2018-08-29 15:32:11 +0000162 * @param[in] filename Image file
163 * @param[in] bgr (Optional) Fill the first plane with blue channel (default = false - RGB format)
164 * @param[in] preprocessor (Optional) Image pre-processing object
Anthony Barbier8a3da6f2017-10-23 18:55:17 +0100165 */
Jenkins52ba29e2018-08-29 15:32:11 +0000166 ImageAccessor(std::string filename, bool bgr = true, std::unique_ptr<IPreprocessor> preprocessor = nullptr);
Anthony Barbier8a3da6f2017-10-23 18:55:17 +0100167 /** Allow instances of this class to be move constructed */
Jenkins52ba29e2018-08-29 15:32:11 +0000168 ImageAccessor(ImageAccessor &&) = default;
Anthony Barbier8a3da6f2017-10-23 18:55:17 +0100169
170 // Inherited methods overriden:
171 bool access_tensor(ITensor &tensor) override;
172
173private:
Jenkins52ba29e2018-08-29 15:32:11 +0000174 bool _already_loaded;
175 const std::string _filename;
Anthony Barbier06ea0482018-02-22 15:45:35 +0000176 const bool _bgr;
177 std::unique_ptr<IPreprocessor> _preprocessor;
Anthony Barbier8a3da6f2017-10-23 18:55:17 +0100178};
179
Jenkins52ba29e2018-08-29 15:32:11 +0000180/** Input Accessor used for network validation */
181class ValidationInputAccessor final : public graph::ITensorAccessor
182{
183public:
184 /** Constructor
185 *
186 * @param[in] image_list File containing all the images to validate
187 * @param[in] images_path Path to images.
188 * @param[in] bgr (Optional) Fill the first plane with blue channel (default = false - RGB format)
189 * @param[in] preprocessor (Optional) Image pre-processing object (default = nullptr)
190 * @param[in] start (Optional) Start range
191 * @param[in] end (Optional) End range
192 * @param[out] output_stream (Optional) Output stream
193 *
194 * @note Range is defined as [start, end]
195 */
196 ValidationInputAccessor(const std::string &image_list,
197 std::string images_path,
198 std::unique_ptr<IPreprocessor> preprocessor = nullptr,
199 bool bgr = true,
200 unsigned int start = 0,
201 unsigned int end = 0,
202 std::ostream &output_stream = std::cout);
203
204 // Inherited methods overriden:
205 bool access_tensor(ITensor &tensor) override;
206
207private:
208 std::string _path;
209 std::vector<std::string> _images;
210 std::unique_ptr<IPreprocessor> _preprocessor;
211 bool _bgr;
212 size_t _offset;
213 std::ostream &_output_stream;
214};
215
216/** Output Accessor used for network validation */
217class ValidationOutputAccessor final : public graph::ITensorAccessor
218{
219public:
220 /** Default Constructor
221 *
222 * @param[in] image_list File containing all the images and labels results
223 * @param[out] output_stream (Optional) Output stream (Defaults to the standard output stream)
224 * @param[in] start (Optional) Start range
225 * @param[in] end (Optional) End range
226 *
227 * @note Range is defined as [start, end]
228 */
229 ValidationOutputAccessor(const std::string &image_list,
230 std::ostream &output_stream = std::cout,
231 unsigned int start = 0,
232 unsigned int end = 0);
233 /** Reset accessor state */
234 void reset();
235
236 // Inherited methods overriden:
237 bool access_tensor(ITensor &tensor) override;
238
239private:
240 /** Access predictions of the tensor
241 *
242 * @tparam T Tensor elements type
243 *
244 * @param[in] tensor Tensor to read the predictions from
245 */
246 template <typename T>
247 std::vector<size_t> access_predictions_tensor(ITensor &tensor);
248 /** Aggregates the results of a sample
249 *
250 * @param[in] res Vector containing the results of a graph
251 * @param[in,out] positive_samples Positive samples to be updated
252 * @param[in] top_n Top n accuracy to measure
253 * @param[in] correct_label Correct label of the current sample
254 */
255 void aggregate_sample(const std::vector<size_t> &res, size_t &positive_samples, size_t top_n, size_t correct_label);
256 /** Reports top N accuracy
257 *
258 * @param[in] top_n Top N accuracy that is being reported
259 * @param[in] total_samples Total number of samples
260 * @param[in] positive_samples Positive samples
261 */
262 void report_top_n(size_t top_n, size_t total_samples, size_t positive_samples);
263
264private:
265 std::vector<int> _results;
266 std::ostream &_output_stream;
267 size_t _offset;
268 size_t _positive_samples_top1;
269 size_t _positive_samples_top5;
270};
271
Anthony Barbier8a3da6f2017-10-23 18:55:17 +0100272/** Result accessor class */
273class TopNPredictionsAccessor final : public graph::ITensorAccessor
274{
275public:
276 /** Constructor
277 *
278 * @param[in] labels_path Path to labels text file.
279 * @param[in] top_n (Optional) Number of output classes to print
280 * @param[out] output_stream (Optional) Output stream
281 */
282 TopNPredictionsAccessor(const std::string &labels_path, size_t top_n = 5, std::ostream &output_stream = std::cout);
283 /** Allow instances of this class to be move constructed */
284 TopNPredictionsAccessor(TopNPredictionsAccessor &&) = default;
285 /** Prevent instances of this class from being copied (As this class contains pointers) */
286 TopNPredictionsAccessor(const TopNPredictionsAccessor &) = delete;
287 /** Prevent instances of this class from being copied (As this class contains pointers) */
288 TopNPredictionsAccessor &operator=(const TopNPredictionsAccessor &) = delete;
289
290 // Inherited methods overriden:
291 bool access_tensor(ITensor &tensor) override;
292
293private:
Anthony Barbierf45d5a92018-01-24 16:23:15 +0000294 template <typename T>
295 void access_predictions_tensor(ITensor &tensor);
296
Anthony Barbier8a3da6f2017-10-23 18:55:17 +0100297 std::vector<std::string> _labels;
298 std::ostream &_output_stream;
299 size_t _top_n;
300};
301
Kaizenbf8b01d2017-10-12 14:26:51 +0100302/** Random accessor class */
303class RandomAccessor final : public graph::ITensorAccessor
304{
305public:
306 /** Constructor
307 *
308 * @param[in] lower Lower bound value.
309 * @param[in] upper Upper bound value.
310 * @param[in] seed (Optional) Seed used to initialise the random number generator.
311 */
312 RandomAccessor(PixelValue lower, PixelValue upper, const std::random_device::result_type seed = 0);
313 /** Allows instances to move constructed */
314 RandomAccessor(RandomAccessor &&) = default;
315
316 // Inherited methods overriden:
317 bool access_tensor(ITensor &tensor) override;
318
319private:
320 template <typename T, typename D>
321 void fill(ITensor &tensor, D &&distribution);
322 PixelValue _lower;
323 PixelValue _upper;
324 std::random_device::result_type _seed;
325};
326
Kaizen8938bd32017-09-28 14:38:23 +0100327/** Numpy Binary loader class*/
Kaizenbf8b01d2017-10-12 14:26:51 +0100328class NumPyBinLoader final : public graph::ITensorAccessor
Kaizen8938bd32017-09-28 14:38:23 +0100329{
330public:
331 /** Default Constructor
332 *
Jenkinsb3a371b2018-05-23 11:36:53 +0100333 * @param[in] filename Binary file name
334 * @param[in] file_layout (Optional) Layout of the numpy tensor data. Defaults to NCHW
Kaizen8938bd32017-09-28 14:38:23 +0100335 */
Jenkinsb3a371b2018-05-23 11:36:53 +0100336 NumPyBinLoader(std::string filename, DataLayout file_layout = DataLayout::NCHW);
Kaizen8938bd32017-09-28 14:38:23 +0100337 /** Allows instances to move constructed */
338 NumPyBinLoader(NumPyBinLoader &&) = default;
339
340 // Inherited methods overriden:
341 bool access_tensor(ITensor &tensor) override;
342
343private:
Jenkins52ba29e2018-08-29 15:32:11 +0000344 bool _already_loaded;
Kaizen8938bd32017-09-28 14:38:23 +0100345 const std::string _filename;
Jenkinsb3a371b2018-05-23 11:36:53 +0100346 const DataLayout _file_layout;
Kaizen8938bd32017-09-28 14:38:23 +0100347};
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000348
Anthony Barbierf45d5a92018-01-24 16:23:15 +0000349/** Generates appropriate random accessor
350 *
351 * @param[in] lower Lower random values bound
352 * @param[in] upper Upper random values bound
353 * @param[in] seed Random generator seed
354 *
355 * @return A ramdom accessor
356 */
357inline std::unique_ptr<graph::ITensorAccessor> get_random_accessor(PixelValue lower, PixelValue upper, const std::random_device::result_type seed = 0)
358{
359 return arm_compute::support::cpp14::make_unique<RandomAccessor>(lower, upper, seed);
360}
361
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000362/** Generates appropriate weights accessor according to the specified path
363 *
364 * @note If path is empty will generate a DummyAccessor else will generate a NumPyBinLoader
365 *
Jenkinsb3a371b2018-05-23 11:36:53 +0100366 * @param[in] path Path to the data files
367 * @param[in] data_file Relative path to the data files from path
368 * @param[in] file_layout (Optional) Layout of file. Defaults to NCHW
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000369 *
370 * @return An appropriate tensor accessor
371 */
Jenkinsb3a371b2018-05-23 11:36:53 +0100372inline std::unique_ptr<graph::ITensorAccessor> get_weights_accessor(const std::string &path,
373 const std::string &data_file,
374 DataLayout file_layout = DataLayout::NCHW)
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000375{
376 if(path.empty())
377 {
378 return arm_compute::support::cpp14::make_unique<DummyAccessor>();
379 }
380 else
381 {
Jenkinsb3a371b2018-05-23 11:36:53 +0100382 return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(path + data_file, file_layout);
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000383 }
384}
385
Jenkins52ba29e2018-08-29 15:32:11 +0000386/** Generates appropriate input accessor according to the specified graph parameters
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000387 *
Jenkins52ba29e2018-08-29 15:32:11 +0000388 * @param[in] graph_parameters Graph parameters
389 * @param[in] preprocessor (Optional) Preproccessor object
390 * @param[in] bgr (Optional) Fill the first plane with blue channel (default = true)
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000391 *
392 * @return An appropriate tensor accessor
393 */
Jenkins52ba29e2018-08-29 15:32:11 +0000394inline std::unique_ptr<graph::ITensorAccessor> get_input_accessor(const arm_compute::utils::CommonGraphParams &graph_parameters,
395 std::unique_ptr<IPreprocessor> preprocessor = nullptr,
396 bool bgr = true)
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000397{
Jenkins52ba29e2018-08-29 15:32:11 +0000398 if(!graph_parameters.validation_file.empty())
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000399 {
Jenkins52ba29e2018-08-29 15:32:11 +0000400 return arm_compute::support::cpp14::make_unique<ValidationInputAccessor>(graph_parameters.validation_file,
401 graph_parameters.validation_path,
402 std::move(preprocessor),
403 bgr,
404 graph_parameters.validation_range_start,
405 graph_parameters.validation_range_end);
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000406 }
407 else
408 {
Jenkins52ba29e2018-08-29 15:32:11 +0000409 const std::string &image_file = graph_parameters.image;
410 const std::string &image_file_lower = lower_string(image_file);
411 if(arm_compute::utility::endswith(image_file_lower, ".npy"))
Jenkinsb3a371b2018-05-23 11:36:53 +0100412 {
Jenkins52ba29e2018-08-29 15:32:11 +0000413 return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(image_file);
414 }
415 else if(arm_compute::utility::endswith(image_file_lower, ".jpeg")
416 || arm_compute::utility::endswith(image_file_lower, ".jpg")
417 || arm_compute::utility::endswith(image_file_lower, ".ppm"))
418 {
419 return arm_compute::support::cpp14::make_unique<ImageAccessor>(image_file, bgr, std::move(preprocessor));
Jenkinsb3a371b2018-05-23 11:36:53 +0100420 }
421 else
422 {
Jenkins52ba29e2018-08-29 15:32:11 +0000423 return arm_compute::support::cpp14::make_unique<DummyAccessor>();
Jenkinsb3a371b2018-05-23 11:36:53 +0100424 }
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000425 }
426}
427
Jenkins52ba29e2018-08-29 15:32:11 +0000428/** Generates appropriate output accessor according to the specified graph parameters
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000429 *
Jenkins52ba29e2018-08-29 15:32:11 +0000430 * @note If the output accessor is requested to validate the graph then ValidationOutputAccessor is generated
431 * else if output_accessor_file is empty will generate a DummyAccessor else will generate a TopNPredictionsAccessor
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000432 *
Jenkins52ba29e2018-08-29 15:32:11 +0000433 * @param[in] graph_parameters Graph parameters
434 * @param[in] top_n (Optional) Number of output classes to print (default = 5)
435 * @param[in] is_validation (Optional) Validation flag (default = false)
436 * @param[out] output_stream (Optional) Output stream (default = std::cout)
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000437 *
438 * @return An appropriate tensor accessor
439 */
Jenkins52ba29e2018-08-29 15:32:11 +0000440inline std::unique_ptr<graph::ITensorAccessor> get_output_accessor(const arm_compute::utils::CommonGraphParams &graph_parameters,
441 size_t top_n = 5,
442 bool is_validation = false,
443 std::ostream &output_stream = std::cout)
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000444{
Jenkins52ba29e2018-08-29 15:32:11 +0000445 if(!graph_parameters.validation_file.empty())
446 {
447 return arm_compute::support::cpp14::make_unique<ValidationOutputAccessor>(graph_parameters.validation_file,
448 output_stream,
449 graph_parameters.validation_range_start,
450 graph_parameters.validation_range_end);
451 }
452 else if(graph_parameters.labels.empty())
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000453 {
Anthony Barbierf45d5a92018-01-24 16:23:15 +0000454 return arm_compute::support::cpp14::make_unique<DummyAccessor>(0);
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000455 }
456 else
457 {
Jenkins52ba29e2018-08-29 15:32:11 +0000458 return arm_compute::support::cpp14::make_unique<TopNPredictionsAccessor>(graph_parameters.labels, top_n, output_stream);
Anthony Barbier8140e1e2017-12-14 23:48:46 +0000459 }
460}
Jenkinsb3a371b2018-05-23 11:36:53 +0100461/** Generates appropriate npy output accessor according to the specified npy_path
462 *
463 * @note If npy_path is empty will generate a DummyAccessor else will generate a NpyAccessor
464 *
465 * @param[in] npy_path Path to npy file.
466 * @param[in] shape Shape of the numpy tensor data.
467 * @param[in] data_type DataType of the numpy tensor data.
468 * @param[out] output_stream (Optional) Output stream
469 *
470 * @return An appropriate tensor accessor
471 */
472inline std::unique_ptr<graph::ITensorAccessor> get_npy_output_accessor(const std::string &npy_path, TensorShape shape, DataType data_type, std::ostream &output_stream = std::cout)
473{
474 if(npy_path.empty())
475 {
476 return arm_compute::support::cpp14::make_unique<DummyAccessor>(0);
477 }
478 else
479 {
480 return arm_compute::support::cpp14::make_unique<NumPyAccessor>(npy_path, shape, data_type, output_stream);
481 }
482}
483
Jenkins52ba29e2018-08-29 15:32:11 +0000484/** Permutes a given tensor shape given the input and output data layout
485 *
486 * @param[in] tensor_shape Tensor shape to permute
487 * @param[in] in_data_layout Input tensor shape data layout
488 * @param[in] out_data_layout Output tensor shape data layout
489 *
490 * @return Permuted tensor shape
491 */
492inline TensorShape permute_shape(TensorShape tensor_shape, DataLayout in_data_layout, DataLayout out_data_layout)
493{
494 if(in_data_layout != out_data_layout)
495 {
496 arm_compute::PermutationVector perm_vec = (in_data_layout == DataLayout::NCHW) ? arm_compute::PermutationVector(2U, 0U, 1U) : arm_compute::PermutationVector(1U, 2U, 0U);
497 arm_compute::permute(tensor_shape, perm_vec);
498 }
499 return tensor_shape;
500}
501
Jenkinsb3a371b2018-05-23 11:36:53 +0100502/** Utility function to return the TargetHint
503 *
504 * @param[in] target Integer value which expresses the selected target. Must be 0 for NEON or 1 for OpenCL or 2 (OpenCL with Tuner)
505 *
506 * @return the TargetHint
507 */
508inline graph::Target set_target_hint(int target)
509{
510 ARM_COMPUTE_ERROR_ON_MSG(target > 3, "Invalid target. Target must be 0 (NEON), 1 (OpenCL), 2 (OpenCL + Tuner), 3 (GLES)");
511 if((target == 1 || target == 2))
512 {
513 return graph::Target::CL;
514 }
515 else if(target == 3)
516 {
517 return graph::Target::GC;
518 }
519 else
520 {
521 return graph::Target::NEON;
522 }
523}
Kaizenbf8b01d2017-10-12 14:26:51 +0100524} // namespace graph_utils
Kaizen8938bd32017-09-28 14:38:23 +0100525} // namespace arm_compute
526
527#endif /* __ARM_COMPUTE_GRAPH_UTILS_H__ */