arm_compute v17.12
[platform/upstream/armcl.git] / utils / GraphUtils.h
1 /*
2  * Copyright (c) 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 #ifndef __ARM_COMPUTE_GRAPH_UTILS_H__
25 #define __ARM_COMPUTE_GRAPH_UTILS_H__
26
27 #include "arm_compute/core/PixelValue.h"
28 #include "arm_compute/graph/Graph.h"
29 #include "arm_compute/graph/ITensorAccessor.h"
30 #include "arm_compute/graph/Types.h"
31
32 #include <random>
33 #include <string>
34 #include <vector>
35
36 namespace arm_compute
37 {
38 namespace graph_utils
39 {
40 /** PPM writer class */
41 class PPMWriter : public graph::ITensorAccessor
42 {
43 public:
44     /** Constructor
45      *
46      * @param[in] name    PPM file name
47      * @param[in] maximum Maximum elements to access
48      */
49     PPMWriter(std::string name, unsigned int maximum = 1);
50     /** Allows instances to move constructed */
51     PPMWriter(PPMWriter &&) = default;
52
53     // Inherited methods overriden:
54     bool access_tensor(ITensor &tensor) override;
55
56 private:
57     const std::string _name;
58     unsigned int      _iterator;
59     unsigned int      _maximum;
60 };
61
62 /** Dummy accessor class */
63 class DummyAccessor final : public graph::ITensorAccessor
64 {
65 public:
66     /** Constructor
67      *
68      * @param[in] maximum Maximum elements to write
69      */
70     DummyAccessor(unsigned int maximum = 1);
71     /** Allows instances to move constructed */
72     DummyAccessor(DummyAccessor &&) = default;
73
74     // Inherited methods overriden:
75     bool access_tensor(ITensor &tensor) override;
76
77 private:
78     unsigned int _iterator;
79     unsigned int _maximum;
80 };
81
82 /** PPM accessor class */
83 class PPMAccessor final : public graph::ITensorAccessor
84 {
85 public:
86     /** Constructor
87      *
88      * @param[in] ppm_path Path to PPM file
89      * @param[in] bgr      (Optional) Fill the first plane with blue channel (default = false)
90      * @param[in] mean_r   (Optional) Red mean value to be subtracted from red channel
91      * @param[in] mean_g   (Optional) Green mean value to be subtracted from green channel
92      * @param[in] mean_b   (Optional) Blue mean value to be subtracted from blue channel
93      */
94     PPMAccessor(const std::string &ppm_path, bool bgr = true, float mean_r = 0.0f, float mean_g = 0.0f, float mean_b = 0.0f);
95     /** Allow instances of this class to be move constructed */
96     PPMAccessor(PPMAccessor &&) = default;
97
98     // Inherited methods overriden:
99     bool access_tensor(ITensor &tensor) override;
100
101 private:
102     const std::string &_ppm_path;
103     const bool         _bgr;
104     const float        _mean_r;
105     const float        _mean_g;
106     const float        _mean_b;
107 };
108
109 /** Result accessor class */
110 class TopNPredictionsAccessor final : public graph::ITensorAccessor
111 {
112 public:
113     /** Constructor
114      *
115      * @param[in]  labels_path   Path to labels text file.
116      * @param[in]  top_n         (Optional) Number of output classes to print
117      * @param[out] output_stream (Optional) Output stream
118      */
119     TopNPredictionsAccessor(const std::string &labels_path, size_t top_n = 5, std::ostream &output_stream = std::cout);
120     /** Allow instances of this class to be move constructed */
121     TopNPredictionsAccessor(TopNPredictionsAccessor &&) = default;
122     /** Prevent instances of this class from being copied (As this class contains pointers) */
123     TopNPredictionsAccessor(const TopNPredictionsAccessor &) = delete;
124     /** Prevent instances of this class from being copied (As this class contains pointers) */
125     TopNPredictionsAccessor &operator=(const TopNPredictionsAccessor &) = delete;
126
127     // Inherited methods overriden:
128     bool access_tensor(ITensor &tensor) override;
129
130 private:
131     std::vector<std::string> _labels;
132     std::ostream            &_output_stream;
133     size_t                   _top_n;
134 };
135
136 /** Random accessor class */
137 class RandomAccessor final : public graph::ITensorAccessor
138 {
139 public:
140     /** Constructor
141      *
142      * @param[in] lower Lower bound value.
143      * @param[in] upper Upper bound value.
144      * @param[in] seed  (Optional) Seed used to initialise the random number generator.
145      */
146     RandomAccessor(PixelValue lower, PixelValue upper, const std::random_device::result_type seed = 0);
147     /** Allows instances to move constructed */
148     RandomAccessor(RandomAccessor &&) = default;
149
150     // Inherited methods overriden:
151     bool access_tensor(ITensor &tensor) override;
152
153 private:
154     template <typename T, typename D>
155     void fill(ITensor &tensor, D &&distribution);
156     PixelValue                      _lower;
157     PixelValue                      _upper;
158     std::random_device::result_type _seed;
159 };
160
161 /** Numpy Binary loader class*/
162 class NumPyBinLoader final : public graph::ITensorAccessor
163 {
164 public:
165     /** Default Constructor
166      *
167      * @param filename Binary file name
168      */
169     NumPyBinLoader(std::string filename);
170     /** Allows instances to move constructed */
171     NumPyBinLoader(NumPyBinLoader &&) = default;
172
173     // Inherited methods overriden:
174     bool access_tensor(ITensor &tensor) override;
175
176 private:
177     const std::string _filename;
178 };
179
180 /** Generates appropriate weights accessor according to the specified path
181  *
182  * @note If path is empty will generate a DummyAccessor else will generate a NumPyBinLoader
183  *
184  * @param[in] path      Path to the data files
185  * @param[in] data_file Relative path to the data files from path
186  *
187  * @return An appropriate tensor accessor
188  */
189 inline std::unique_ptr<graph::ITensorAccessor> get_weights_accessor(const std::string &path, const std::string &data_file)
190 {
191     if(path.empty())
192     {
193         return arm_compute::support::cpp14::make_unique<DummyAccessor>();
194     }
195     else
196     {
197         return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(path + data_file);
198     }
199 }
200
201 /** Generates appropriate input accessor according to the specified ppm_path
202  *
203  * @note If ppm_path is empty will generate a DummyAccessor else will generate a PPMAccessor
204  *
205  * @param[in] ppm_path Path to PPM file
206  * @param[in] mean_r   Red mean value to be subtracted from red channel
207  * @param[in] mean_g   Green mean value to be subtracted from green channel
208  * @param[in] mean_b   Blue mean value to be subtracted from blue channel
209  *
210  * @return An appropriate tensor accessor
211  */
212 inline std::unique_ptr<graph::ITensorAccessor> get_input_accessor(const std::string &ppm_path, float mean_r, float mean_g, float mean_b)
213 {
214     if(ppm_path.empty())
215     {
216         return arm_compute::support::cpp14::make_unique<DummyAccessor>();
217     }
218     else
219     {
220         return arm_compute::support::cpp14::make_unique<PPMAccessor>(ppm_path, true, mean_r, mean_g, mean_b);
221     }
222 }
223
224 /** Utility function to return the TargetHint
225  *
226  * @param[in] target Integer value which expresses the selected target. Must be 0 for NEON or 1 for OpenCL
227  *
228  * @return the TargetHint
229  */
230 inline graph::TargetHint set_target_hint(int target)
231 {
232     ARM_COMPUTE_ERROR_ON_MSG(target > 1, "Invalid target. Target must be 0 (NEON) or 1 (OpenCL)");
233     if(target == 1 && graph::Graph::opencl_is_available())
234     {
235         // If type of target is OpenCL, check if OpenCL is available and initialize the scheduler
236         return graph::TargetHint::OPENCL;
237     }
238     else
239     {
240         return graph::TargetHint::NEON;
241     }
242 }
243
244 /** Generates appropriate output accessor according to the specified labels_path
245  *
246  * @note If labels_path is empty will generate a DummyAccessor else will generate a TopNPredictionsAccessor
247  *
248  * @param[in]  labels_path   Path to labels text file
249  * @param[in]  top_n         (Optional) Number of output classes to print
250  * @param[out] output_stream (Optional) Output stream
251  *
252  * @return An appropriate tensor accessor
253  */
254 inline std::unique_ptr<graph::ITensorAccessor> get_output_accessor(const std::string &labels_path, size_t top_n = 5, std::ostream &output_stream = std::cout)
255 {
256     if(labels_path.empty())
257     {
258         return arm_compute::support::cpp14::make_unique<DummyAccessor>();
259     }
260     else
261     {
262         return arm_compute::support::cpp14::make_unique<TopNPredictionsAccessor>(labels_path, top_n, output_stream);
263     }
264 }
265 } // namespace graph_utils
266 } // namespace arm_compute
267
268 #endif /* __ARM_COMPUTE_GRAPH_UTILS_H__ */