1*c217d954SCole Faust /*
2*c217d954SCole Faust * Copyright (c) 2021 Arm Limited.
3*c217d954SCole Faust *
4*c217d954SCole Faust * SPDX-License-Identifier: MIT
5*c217d954SCole Faust *
6*c217d954SCole Faust * Permission is hereby granted, free of charge, to any person obtaining a copy
7*c217d954SCole Faust * of this software and associated documentation files (the "Software"), to
8*c217d954SCole Faust * deal in the Software without restriction, including without limitation the
9*c217d954SCole Faust * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*c217d954SCole Faust * sell copies of the Software, and to permit persons to whom the Software is
11*c217d954SCole Faust * furnished to do so, subject to the following conditions:
12*c217d954SCole Faust *
13*c217d954SCole Faust * The above copyright notice and this permission notice shall be included in all
14*c217d954SCole Faust * copies or substantial portions of the Software.
15*c217d954SCole Faust *
16*c217d954SCole Faust * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*c217d954SCole Faust * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*c217d954SCole Faust * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*c217d954SCole Faust * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*c217d954SCole Faust * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*c217d954SCole Faust * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*c217d954SCole Faust * SOFTWARE.
23*c217d954SCole Faust */
24*c217d954SCole Faust #ifndef ARM_COMPUTE_ACL_HPP_
25*c217d954SCole Faust #define ARM_COMPUTE_ACL_HPP_
26*c217d954SCole Faust
27*c217d954SCole Faust #include "arm_compute/Acl.h"
28*c217d954SCole Faust
29*c217d954SCole Faust #include <cstdlib>
30*c217d954SCole Faust #include <memory>
31*c217d954SCole Faust #include <string>
32*c217d954SCole Faust #include <vector>
33*c217d954SCole Faust
34*c217d954SCole Faust #if defined(ARM_COMPUTE_EXCEPTIONS_ENABLED)
35*c217d954SCole Faust #include <exception>
36*c217d954SCole Faust #endif /* defined(ARM_COMPUTE_EXCEPTIONS_ENABLED) */
37*c217d954SCole Faust
38*c217d954SCole Faust // Helper Macros
39*c217d954SCole Faust #define ARM_COMPUTE_IGNORE_UNUSED(x) (void)(x)
40*c217d954SCole Faust
41*c217d954SCole Faust namespace acl
42*c217d954SCole Faust {
43*c217d954SCole Faust // Forward declarations
44*c217d954SCole Faust class Context;
45*c217d954SCole Faust class Queue;
46*c217d954SCole Faust class Tensor;
47*c217d954SCole Faust class TensorPack;
48*c217d954SCole Faust
49*c217d954SCole Faust /**< Status code enum */
50*c217d954SCole Faust enum class StatusCode
51*c217d954SCole Faust {
52*c217d954SCole Faust Success = AclSuccess,
53*c217d954SCole Faust RuntimeError = AclRuntimeError,
54*c217d954SCole Faust OutOfMemory = AclOutOfMemory,
55*c217d954SCole Faust Unimplemented = AclUnimplemented,
56*c217d954SCole Faust UnsupportedTarget = AclUnsupportedTarget,
57*c217d954SCole Faust InvalidArgument = AclInvalidArgument,
58*c217d954SCole Faust InvalidTarget = AclInvalidTarget,
59*c217d954SCole Faust UnsupportedConfig = AclUnsupportedConfig,
60*c217d954SCole Faust InvalidObjectState = AclInvalidObjectState,
61*c217d954SCole Faust };
62*c217d954SCole Faust
63*c217d954SCole Faust /**< Utility namespace containing helpers functions */
64*c217d954SCole Faust namespace detail
65*c217d954SCole Faust {
66*c217d954SCole Faust /** Construct to handle destruction of objects
67*c217d954SCole Faust *
68*c217d954SCole Faust * @tparam T Object base type
69*c217d954SCole Faust */
70*c217d954SCole Faust template <typename T>
71*c217d954SCole Faust struct ObjectDeleter
72*c217d954SCole Faust {
73*c217d954SCole Faust };
74*c217d954SCole Faust
75*c217d954SCole Faust #define OBJECT_DELETER(obj, func) \
76*c217d954SCole Faust template <> \
77*c217d954SCole Faust struct ObjectDeleter<obj> \
78*c217d954SCole Faust \
79*c217d954SCole Faust { \
80*c217d954SCole Faust static inline AclStatus Destroy(obj v) \
81*c217d954SCole Faust { \
82*c217d954SCole Faust return func(v); \
83*c217d954SCole Faust } \
84*c217d954SCole Faust };
85*c217d954SCole Faust
OBJECT_DELETER(AclContext,AclDestroyContext)86*c217d954SCole Faust OBJECT_DELETER(AclContext, AclDestroyContext)
87*c217d954SCole Faust OBJECT_DELETER(AclQueue, AclDestroyQueue)
88*c217d954SCole Faust OBJECT_DELETER(AclTensor, AclDestroyTensor)
89*c217d954SCole Faust OBJECT_DELETER(AclTensorPack, AclDestroyTensorPack)
90*c217d954SCole Faust OBJECT_DELETER(AclOperator, AclDestroyOperator)
91*c217d954SCole Faust
92*c217d954SCole Faust #undef OBJECT_DELETER
93*c217d954SCole Faust
94*c217d954SCole Faust /** Convert a strongly typed enum to an old plain c enum
95*c217d954SCole Faust *
96*c217d954SCole Faust * @tparam E Plain old C enum
97*c217d954SCole Faust * @tparam SE Strongly typed resulting enum
98*c217d954SCole Faust *
99*c217d954SCole Faust * @param[in] v Value to convert
100*c217d954SCole Faust *
101*c217d954SCole Faust * @return A corresponding plain old C enumeration
102*c217d954SCole Faust */
103*c217d954SCole Faust template <typename E, typename SE>
104*c217d954SCole Faust constexpr E as_cenum(SE v) noexcept
105*c217d954SCole Faust {
106*c217d954SCole Faust return static_cast<E>(static_cast<typename std::underlying_type<SE>::type>(v));
107*c217d954SCole Faust }
108*c217d954SCole Faust
109*c217d954SCole Faust /** Convert plain old enumeration to a strongly typed enum
110*c217d954SCole Faust *
111*c217d954SCole Faust * @tparam SE Strongly typed resulting enum
112*c217d954SCole Faust * @tparam E Plain old C enum
113*c217d954SCole Faust *
114*c217d954SCole Faust * @param[in] val Value to convert
115*c217d954SCole Faust *
116*c217d954SCole Faust * @return A corresponding strongly typed enumeration
117*c217d954SCole Faust */
118*c217d954SCole Faust template <typename SE, typename E>
as_enum(E val)119*c217d954SCole Faust constexpr SE as_enum(E val) noexcept
120*c217d954SCole Faust {
121*c217d954SCole Faust return static_cast<SE>(val);
122*c217d954SCole Faust }
123*c217d954SCole Faust
124*c217d954SCole Faust /** Object base class for library objects
125*c217d954SCole Faust *
126*c217d954SCole Faust * Class is defining basic common interface for all the library objects
127*c217d954SCole Faust *
128*c217d954SCole Faust * @tparam T Object type to be templated on
129*c217d954SCole Faust */
130*c217d954SCole Faust template <typename T>
131*c217d954SCole Faust class ObjectBase
132*c217d954SCole Faust {
133*c217d954SCole Faust public:
134*c217d954SCole Faust /** Destructor */
135*c217d954SCole Faust ~ObjectBase() = default;
136*c217d954SCole Faust /** Copy constructor */
137*c217d954SCole Faust ObjectBase(const ObjectBase<T> &) = default;
138*c217d954SCole Faust /** Move Constructor */
139*c217d954SCole Faust ObjectBase(ObjectBase<T> &&) = default;
140*c217d954SCole Faust /** Copy assignment operator */
141*c217d954SCole Faust ObjectBase<T> &operator=(const ObjectBase<T> &) = default;
142*c217d954SCole Faust /** Move assignment operator */
143*c217d954SCole Faust ObjectBase<T> &operator=(ObjectBase<T> &&) = default;
144*c217d954SCole Faust /** Reset object value
145*c217d954SCole Faust *
146*c217d954SCole Faust * @param [in] val Value to set
147*c217d954SCole Faust */
reset(T * val)148*c217d954SCole Faust void reset(T *val)
149*c217d954SCole Faust {
150*c217d954SCole Faust _object.reset(val, detail::ObjectDeleter<T *>::Destroy);
151*c217d954SCole Faust }
152*c217d954SCole Faust /** Access uderlying object
153*c217d954SCole Faust *
154*c217d954SCole Faust * @return Underlying object
155*c217d954SCole Faust */
get() const156*c217d954SCole Faust const T *get() const
157*c217d954SCole Faust {
158*c217d954SCole Faust return _object.get();
159*c217d954SCole Faust }
160*c217d954SCole Faust /** Access uderlying object
161*c217d954SCole Faust *
162*c217d954SCole Faust * @return Underlying object
163*c217d954SCole Faust */
get()164*c217d954SCole Faust T *get()
165*c217d954SCole Faust {
166*c217d954SCole Faust return _object.get();
167*c217d954SCole Faust }
168*c217d954SCole Faust
169*c217d954SCole Faust protected:
170*c217d954SCole Faust /** Constructor */
171*c217d954SCole Faust ObjectBase() = default;
172*c217d954SCole Faust
173*c217d954SCole Faust protected:
174*c217d954SCole Faust std::shared_ptr<T> _object{ nullptr }; /**< Library object */
175*c217d954SCole Faust };
176*c217d954SCole Faust
177*c217d954SCole Faust /** Equality operator for library object
178*c217d954SCole Faust *
179*c217d954SCole Faust * @tparam T Parameter to template on
180*c217d954SCole Faust *
181*c217d954SCole Faust * @param[in] lhs Left hand-side argument
182*c217d954SCole Faust * @param[in] rhs Right hand-side argument
183*c217d954SCole Faust *
184*c217d954SCole Faust * @return True if objects are equal, else false
185*c217d954SCole Faust */
186*c217d954SCole Faust template <typename T>
operator ==(const ObjectBase<T> & lhs,const ObjectBase<T> & rhs)187*c217d954SCole Faust bool operator==(const ObjectBase<T> &lhs, const ObjectBase<T> &rhs)
188*c217d954SCole Faust {
189*c217d954SCole Faust return lhs.get() == rhs.get();
190*c217d954SCole Faust }
191*c217d954SCole Faust
192*c217d954SCole Faust /** Inequality operator for library object
193*c217d954SCole Faust *
194*c217d954SCole Faust * @tparam T Parameter to template on
195*c217d954SCole Faust *
196*c217d954SCole Faust * @param[in] lhs Left hand-side argument
197*c217d954SCole Faust * @param[in] rhs Right hand-side argument
198*c217d954SCole Faust *
199*c217d954SCole Faust * @return True if objects are equal, else false
200*c217d954SCole Faust */
201*c217d954SCole Faust template <typename T>
operator !=(const ObjectBase<T> & lhs,const ObjectBase<T> & rhs)202*c217d954SCole Faust bool operator!=(const ObjectBase<T> &lhs, const ObjectBase<T> &rhs)
203*c217d954SCole Faust {
204*c217d954SCole Faust return !(lhs == rhs);
205*c217d954SCole Faust }
206*c217d954SCole Faust } // namespace detail
207*c217d954SCole Faust
208*c217d954SCole Faust #if defined(ARM_COMPUTE_EXCEPTIONS_ENABLED)
209*c217d954SCole Faust /** Status class
210*c217d954SCole Faust *
211*c217d954SCole Faust * Class is an extension of std::exception and contains the underlying
212*c217d954SCole Faust * status construct and an error explanatory message to be reported.
213*c217d954SCole Faust *
214*c217d954SCole Faust * @note Class is visible only when exceptions are enabled during compilation
215*c217d954SCole Faust */
216*c217d954SCole Faust class Status : public std::exception
217*c217d954SCole Faust {
218*c217d954SCole Faust public:
219*c217d954SCole Faust /** Constructor
220*c217d954SCole Faust *
221*c217d954SCole Faust * @param[in] status Status returned
222*c217d954SCole Faust * @param[in] msg Error message to be bound with the exception
223*c217d954SCole Faust */
Status(StatusCode status,const std::string & msg)224*c217d954SCole Faust Status(StatusCode status, const std::string &msg)
225*c217d954SCole Faust : _status(status), _msg(msg)
226*c217d954SCole Faust {
227*c217d954SCole Faust }
228*c217d954SCole Faust /** Returns an explanatory exception message
229*c217d954SCole Faust *
230*c217d954SCole Faust * @return Status message
231*c217d954SCole Faust */
what() const232*c217d954SCole Faust const char *what() const noexcept override
233*c217d954SCole Faust {
234*c217d954SCole Faust return _msg.c_str();
235*c217d954SCole Faust }
236*c217d954SCole Faust /** Underlying status accessor
237*c217d954SCole Faust *
238*c217d954SCole Faust * @return Status code
239*c217d954SCole Faust */
status() const240*c217d954SCole Faust StatusCode status() const
241*c217d954SCole Faust {
242*c217d954SCole Faust return _status;
243*c217d954SCole Faust }
244*c217d954SCole Faust /** Explicit status converter
245*c217d954SCole Faust *
246*c217d954SCole Faust * @return Status code
247*c217d954SCole Faust */
operator StatusCode() const248*c217d954SCole Faust explicit operator StatusCode() const
249*c217d954SCole Faust {
250*c217d954SCole Faust return _status;
251*c217d954SCole Faust }
252*c217d954SCole Faust
253*c217d954SCole Faust private:
254*c217d954SCole Faust StatusCode _status; /**< Status code */
255*c217d954SCole Faust std::string _msg; /**< Status message */
256*c217d954SCole Faust };
257*c217d954SCole Faust
258*c217d954SCole Faust /** Reports an error status and throws an exception object in case of failure
259*c217d954SCole Faust *
260*c217d954SCole Faust * @note This implementation is used when exceptions are enabled during compilation
261*c217d954SCole Faust *
262*c217d954SCole Faust * @param[in] status Status to report
263*c217d954SCole Faust * @param[in] msg Explanatory error messaged
264*c217d954SCole Faust *
265*c217d954SCole Faust * @return Status code
266*c217d954SCole Faust */
report_status(StatusCode status,const std::string & msg)267*c217d954SCole Faust static inline void report_status(StatusCode status, const std::string &msg)
268*c217d954SCole Faust {
269*c217d954SCole Faust if(status != StatusCode::Success)
270*c217d954SCole Faust {
271*c217d954SCole Faust throw Status(status, msg);
272*c217d954SCole Faust }
273*c217d954SCole Faust }
274*c217d954SCole Faust #else /* defined(ARM_COMPUTE_EXCEPTIONS_ENABLED) */
275*c217d954SCole Faust /** Reports a status code
276*c217d954SCole Faust *
277*c217d954SCole Faust * @note This implementation is used when exceptions are disabled during compilation
278*c217d954SCole Faust * @note Message is surpressed and not reported in this case
279*c217d954SCole Faust *
280*c217d954SCole Faust * @param[in] status Status to report
281*c217d954SCole Faust * @param[in] msg Explanatory error messaged
282*c217d954SCole Faust *
283*c217d954SCole Faust * @return Status code
284*c217d954SCole Faust */
report_status(StatusCode status,const std::string & msg)285*c217d954SCole Faust static inline void report_status(StatusCode status, const std::string &msg)
286*c217d954SCole Faust {
287*c217d954SCole Faust ARM_COMPUTE_IGNORE_UNUSED(status);
288*c217d954SCole Faust ARM_COMPUTE_IGNORE_UNUSED(msg);
289*c217d954SCole Faust }
290*c217d954SCole Faust #endif /* defined(ARM_COMPUTE_EXCEPTIONS_ENABLED) */
291*c217d954SCole Faust
292*c217d954SCole Faust /**< Target enum */
293*c217d954SCole Faust enum class Target
294*c217d954SCole Faust {
295*c217d954SCole Faust Cpu = AclCpu, /**< Cpu target that leverages SIMD */
296*c217d954SCole Faust GpuOcl = AclGpuOcl /**< Gpu target that leverages OpenCL */
297*c217d954SCole Faust };
298*c217d954SCole Faust
299*c217d954SCole Faust /**< Available execution modes */
300*c217d954SCole Faust enum class ExecutionMode
301*c217d954SCole Faust {
302*c217d954SCole Faust FastRerun = AclPreferFastRerun, /**< Prefer minimum latency in consecutive runs, might introduce higher startup times */
303*c217d954SCole Faust FastStart = AclPreferFastStart, /**< Prefer minimizing startup time */
304*c217d954SCole Faust };
305*c217d954SCole Faust
306*c217d954SCole Faust /** Context class
307*c217d954SCole Faust *
308*c217d954SCole Faust * Context acts as a central aggregate service for further objects created from it.
309*c217d954SCole Faust * It provides, internally, common facilities in order to avoid the use of global
310*c217d954SCole Faust * statically initialized objects that can lead to important side-effect under
311*c217d954SCole Faust * specific execution contexts.
312*c217d954SCole Faust *
313*c217d954SCole Faust * For example context contains allocators for object creation, for further backing memory allocation,
314*c217d954SCole Faust * any serialization interfaces and other modules that affect the construction of objects,
315*c217d954SCole Faust * like program caches for OpenCL.
316*c217d954SCole Faust */
317*c217d954SCole Faust class Context : public detail::ObjectBase<AclContext_>
318*c217d954SCole Faust {
319*c217d954SCole Faust public:
320*c217d954SCole Faust /**< Context options */
321*c217d954SCole Faust struct Options
322*c217d954SCole Faust {
323*c217d954SCole Faust static constexpr int32_t num_threads_auto = -1; /**< Allow runtime to specify number of threads */
324*c217d954SCole Faust
325*c217d954SCole Faust /** Default Constructor
326*c217d954SCole Faust *
327*c217d954SCole Faust * @note By default no precision loss is enabled for operators
328*c217d954SCole Faust * @note By default the preferred execution mode is to favor multiple consecutive reruns of an operator
329*c217d954SCole Faust */
Optionsacl::Context::Options330*c217d954SCole Faust Options()
331*c217d954SCole Faust : Options(ExecutionMode::FastRerun /* mode */,
332*c217d954SCole Faust AclCpuCapabilitiesAuto /* caps */,
333*c217d954SCole Faust false /* enable_fast_math */,
334*c217d954SCole Faust nullptr /* kernel_config */,
335*c217d954SCole Faust num_threads_auto /* max_compute_units */,
336*c217d954SCole Faust nullptr /* allocator */)
337*c217d954SCole Faust {
338*c217d954SCole Faust }
339*c217d954SCole Faust /** Constructor
340*c217d954SCole Faust *
341*c217d954SCole Faust * @param[in] mode Execution mode to be used
342*c217d954SCole Faust * @param[in] caps Capabilities to be used
343*c217d954SCole Faust * @param[in] enable_fast_math Allow precision loss in favor of performance
344*c217d954SCole Faust * @param[in] kernel_config Kernel configuration file containing construction tuning meta-data
345*c217d954SCole Faust * @param[in] max_compute_units Max compute units that are expected to used
346*c217d954SCole Faust * @param[in] allocator Allocator to be used for internal memory allocation
347*c217d954SCole Faust */
Optionsacl::Context::Options348*c217d954SCole Faust Options(ExecutionMode mode,
349*c217d954SCole Faust AclTargetCapabilities caps,
350*c217d954SCole Faust bool enable_fast_math,
351*c217d954SCole Faust const char *kernel_config,
352*c217d954SCole Faust int32_t max_compute_units,
353*c217d954SCole Faust AclAllocator *allocator)
354*c217d954SCole Faust {
355*c217d954SCole Faust copts.mode = detail::as_cenum<AclExecutionMode>(mode);
356*c217d954SCole Faust copts.capabilities = caps;
357*c217d954SCole Faust copts.enable_fast_math = enable_fast_math;
358*c217d954SCole Faust copts.kernel_config_file = kernel_config;
359*c217d954SCole Faust copts.max_compute_units = max_compute_units;
360*c217d954SCole Faust copts.allocator = allocator;
361*c217d954SCole Faust }
362*c217d954SCole Faust
363*c217d954SCole Faust AclContextOptions copts{};
364*c217d954SCole Faust };
365*c217d954SCole Faust
366*c217d954SCole Faust public:
367*c217d954SCole Faust /** Constructor
368*c217d954SCole Faust *
369*c217d954SCole Faust * @note Serves as a simpler delegate constructor
370*c217d954SCole Faust * @note As context options, default conservative options will be used
371*c217d954SCole Faust *
372*c217d954SCole Faust * @param[in] target Target to create context for
373*c217d954SCole Faust * @param[out] status Status information if requested
374*c217d954SCole Faust */
Context(Target target,StatusCode * status=nullptr)375*c217d954SCole Faust explicit Context(Target target, StatusCode *status = nullptr)
376*c217d954SCole Faust : Context(target, Options(), status)
377*c217d954SCole Faust {
378*c217d954SCole Faust }
379*c217d954SCole Faust /** Constructor
380*c217d954SCole Faust *
381*c217d954SCole Faust * @param[in] target Target to create context for
382*c217d954SCole Faust * @param[in] options Context construction options
383*c217d954SCole Faust * @param[out] status Status information if requested
384*c217d954SCole Faust */
Context(Target target,const Options & options,StatusCode * status=nullptr)385*c217d954SCole Faust Context(Target target, const Options &options, StatusCode *status = nullptr)
386*c217d954SCole Faust {
387*c217d954SCole Faust AclContext ctx;
388*c217d954SCole Faust const auto st = detail::as_enum<StatusCode>(AclCreateContext(&ctx, detail::as_cenum<AclTarget>(target), &options.copts));
389*c217d954SCole Faust reset(ctx);
390*c217d954SCole Faust report_status(st, "[Compute Library] Failed to create context");
391*c217d954SCole Faust if(status)
392*c217d954SCole Faust {
393*c217d954SCole Faust *status = st;
394*c217d954SCole Faust }
395*c217d954SCole Faust }
396*c217d954SCole Faust };
397*c217d954SCole Faust
398*c217d954SCole Faust /**< Available tuning modes */
399*c217d954SCole Faust enum class TuningMode
400*c217d954SCole Faust {
401*c217d954SCole Faust Rapid = AclRapid,
402*c217d954SCole Faust Normal = AclNormal,
403*c217d954SCole Faust Exhaustive = AclExhaustive
404*c217d954SCole Faust };
405*c217d954SCole Faust
406*c217d954SCole Faust /** Queue class
407*c217d954SCole Faust *
408*c217d954SCole Faust * Queue is responsible for the execution related aspects, with main responsibilities those of
409*c217d954SCole Faust * scheduling and tuning operators.
410*c217d954SCole Faust *
411*c217d954SCole Faust * Multiple queues can be created from the same context, and the same operator can be scheduled on each concurrently.
412*c217d954SCole Faust *
413*c217d954SCole Faust * @note An operator might depend on the maximum possible compute units that are provided in the context,
414*c217d954SCole Faust * thus in cases where the number of the scheduling units of the queue are greater might lead to errors.
415*c217d954SCole Faust */
416*c217d954SCole Faust class Queue : public detail::ObjectBase<AclQueue_>
417*c217d954SCole Faust {
418*c217d954SCole Faust public:
419*c217d954SCole Faust /**< Queue options */
420*c217d954SCole Faust struct Options
421*c217d954SCole Faust {
422*c217d954SCole Faust /** Default Constructor
423*c217d954SCole Faust *
424*c217d954SCole Faust * As default options, no tuning will be performed, and the number of scheduling units will
425*c217d954SCole Faust * depends on internal device discovery functionality
426*c217d954SCole Faust */
Optionsacl::Queue::Options427*c217d954SCole Faust Options()
428*c217d954SCole Faust : opts{ AclTuningModeNone, 0 } {};
429*c217d954SCole Faust /** Constructor
430*c217d954SCole Faust *
431*c217d954SCole Faust * @param[in] mode Tuning mode to be used
432*c217d954SCole Faust * @param[in] compute_units Number of scheduling units to be used
433*c217d954SCole Faust */
Optionsacl::Queue::Options434*c217d954SCole Faust Options(TuningMode mode, int32_t compute_units)
435*c217d954SCole Faust : opts{ detail::as_cenum<AclTuningMode>(mode), compute_units }
436*c217d954SCole Faust {
437*c217d954SCole Faust }
438*c217d954SCole Faust
439*c217d954SCole Faust AclQueueOptions opts;
440*c217d954SCole Faust };
441*c217d954SCole Faust
442*c217d954SCole Faust public:
443*c217d954SCole Faust /** Constructor
444*c217d954SCole Faust *
445*c217d954SCole Faust * @note Serves as a simpler delegate constructor
446*c217d954SCole Faust * @note As queue options, default conservative options will be used
447*c217d954SCole Faust *
448*c217d954SCole Faust * @param[in] ctx Context to create queue for
449*c217d954SCole Faust * @param[out] status Status information if requested
450*c217d954SCole Faust */
Queue(Context & ctx,StatusCode * status=nullptr)451*c217d954SCole Faust explicit Queue(Context &ctx, StatusCode *status = nullptr)
452*c217d954SCole Faust : Queue(ctx, Options(), status)
453*c217d954SCole Faust {
454*c217d954SCole Faust }
455*c217d954SCole Faust /** Constructor
456*c217d954SCole Faust *
457*c217d954SCole Faust * @note As queue options, default conservative options will be used
458*c217d954SCole Faust *
459*c217d954SCole Faust * @param[in] ctx Context from where the queue will be created from
460*c217d954SCole Faust * @param[in] options Queue options to be used
461*c217d954SCole Faust * @param[out] status Status information if requested
462*c217d954SCole Faust */
Queue(Context & ctx,const Options & options=Options (),StatusCode * status=nullptr)463*c217d954SCole Faust explicit Queue(Context &ctx, const Options &options = Options(), StatusCode *status = nullptr)
464*c217d954SCole Faust {
465*c217d954SCole Faust AclQueue queue;
466*c217d954SCole Faust const auto st = detail::as_enum<StatusCode>(AclCreateQueue(&queue, ctx.get(), &options.opts));
467*c217d954SCole Faust reset(queue);
468*c217d954SCole Faust report_status(st, "[Compute Library] Failed to create queue!");
469*c217d954SCole Faust if(status)
470*c217d954SCole Faust {
471*c217d954SCole Faust *status = st;
472*c217d954SCole Faust }
473*c217d954SCole Faust }
474*c217d954SCole Faust /** Block until all the tasks of the queue have been marked as finished
475*c217d954SCole Faust *
476*c217d954SCole Faust * @return Status code
477*c217d954SCole Faust */
finish()478*c217d954SCole Faust StatusCode finish()
479*c217d954SCole Faust {
480*c217d954SCole Faust return detail::as_enum<StatusCode>(AclQueueFinish(_object.get()));
481*c217d954SCole Faust }
482*c217d954SCole Faust };
483*c217d954SCole Faust
484*c217d954SCole Faust /**< Data type enumeration */
485*c217d954SCole Faust enum class DataType
486*c217d954SCole Faust {
487*c217d954SCole Faust Unknown = AclDataTypeUnknown,
488*c217d954SCole Faust UInt8 = AclUInt8,
489*c217d954SCole Faust Int8 = AclInt8,
490*c217d954SCole Faust UInt16 = AclUInt16,
491*c217d954SCole Faust Int16 = AclInt16,
492*c217d954SCole Faust UInt32 = AclUint32,
493*c217d954SCole Faust Int32 = AclInt32,
494*c217d954SCole Faust Float16 = AclFloat16,
495*c217d954SCole Faust BFloat16 = AclBFloat16,
496*c217d954SCole Faust Float32 = AclFloat32,
497*c217d954SCole Faust };
498*c217d954SCole Faust
499*c217d954SCole Faust /** Tensor Descriptor class
500*c217d954SCole Faust *
501*c217d954SCole Faust * Structure that contains all the required meta-data to represent a tensor
502*c217d954SCole Faust */
503*c217d954SCole Faust class TensorDescriptor
504*c217d954SCole Faust {
505*c217d954SCole Faust public:
506*c217d954SCole Faust /** Constructor
507*c217d954SCole Faust *
508*c217d954SCole Faust * @param[in] shape Shape of the tensor
509*c217d954SCole Faust * @param[in] data_type Data type of the tensor
510*c217d954SCole Faust */
TensorDescriptor(const std::vector<int32_t> & shape,DataType data_type)511*c217d954SCole Faust TensorDescriptor(const std::vector<int32_t> &shape, DataType data_type)
512*c217d954SCole Faust : _shape(shape), _data_type(data_type)
513*c217d954SCole Faust {
514*c217d954SCole Faust _cdesc.ndims = _shape.size();
515*c217d954SCole Faust _cdesc.shape = _shape.data();
516*c217d954SCole Faust _cdesc.data_type = detail::as_cenum<AclDataType>(_data_type);
517*c217d954SCole Faust _cdesc.strides = nullptr;
518*c217d954SCole Faust _cdesc.boffset = 0;
519*c217d954SCole Faust }
520*c217d954SCole Faust /** Constructor
521*c217d954SCole Faust *
522*c217d954SCole Faust * @param[in] desc C-type descriptor
523*c217d954SCole Faust */
TensorDescriptor(const AclTensorDescriptor & desc)524*c217d954SCole Faust explicit TensorDescriptor(const AclTensorDescriptor &desc)
525*c217d954SCole Faust {
526*c217d954SCole Faust _cdesc = desc;
527*c217d954SCole Faust _data_type = detail::as_enum<DataType>(desc.data_type);
528*c217d954SCole Faust _shape.reserve(desc.ndims);
529*c217d954SCole Faust for(int32_t d = 0; d < desc.ndims; ++d)
530*c217d954SCole Faust {
531*c217d954SCole Faust _shape.emplace_back(desc.shape[d]);
532*c217d954SCole Faust }
533*c217d954SCole Faust }
534*c217d954SCole Faust /** Get underlying C tensor descriptor
535*c217d954SCole Faust *
536*c217d954SCole Faust * @return Underlying structure
537*c217d954SCole Faust */
get() const538*c217d954SCole Faust const AclTensorDescriptor *get() const
539*c217d954SCole Faust {
540*c217d954SCole Faust return &_cdesc;
541*c217d954SCole Faust }
542*c217d954SCole Faust /** Operator to compare two TensorDescriptor
543*c217d954SCole Faust *
544*c217d954SCole Faust * @param[in] other The instance to compare against
545*c217d954SCole Faust *
546*c217d954SCole Faust * @return True if two instances have the same shape and data type
547*c217d954SCole Faust */
operator ==(const TensorDescriptor & other)548*c217d954SCole Faust bool operator==(const TensorDescriptor &other)
549*c217d954SCole Faust {
550*c217d954SCole Faust bool is_same = true;
551*c217d954SCole Faust
552*c217d954SCole Faust is_same &= _data_type == other._data_type;
553*c217d954SCole Faust is_same &= _shape.size() == other._shape.size();
554*c217d954SCole Faust
555*c217d954SCole Faust if(is_same)
556*c217d954SCole Faust {
557*c217d954SCole Faust for(uint32_t d = 0; d < _shape.size(); ++d)
558*c217d954SCole Faust {
559*c217d954SCole Faust is_same &= _shape[d] == other._shape[d];
560*c217d954SCole Faust }
561*c217d954SCole Faust }
562*c217d954SCole Faust
563*c217d954SCole Faust return is_same;
564*c217d954SCole Faust }
565*c217d954SCole Faust
566*c217d954SCole Faust private:
567*c217d954SCole Faust std::vector<int32_t> _shape{};
568*c217d954SCole Faust DataType _data_type{};
569*c217d954SCole Faust AclTensorDescriptor _cdesc{};
570*c217d954SCole Faust };
571*c217d954SCole Faust
572*c217d954SCole Faust /** Import memory types */
573*c217d954SCole Faust enum class ImportType
574*c217d954SCole Faust {
575*c217d954SCole Faust Host = AclImportMemoryType::AclHostPtr
576*c217d954SCole Faust };
577*c217d954SCole Faust
578*c217d954SCole Faust /** Tensor class
579*c217d954SCole Faust *
580*c217d954SCole Faust * Tensor is an mathematical construct that can represent an N-Dimensional space.
581*c217d954SCole Faust *
582*c217d954SCole Faust * @note Maximum dimensionality support is 6 internally at the moment
583*c217d954SCole Faust */
584*c217d954SCole Faust class Tensor : public detail::ObjectBase<AclTensor_>
585*c217d954SCole Faust {
586*c217d954SCole Faust public:
587*c217d954SCole Faust /** Constructor
588*c217d954SCole Faust *
589*c217d954SCole Faust * @note Tensor memory is allocated
590*c217d954SCole Faust *
591*c217d954SCole Faust * @param[in] ctx Context from where the tensor will be created from
592*c217d954SCole Faust * @param[in] desc Tensor descriptor to be used
593*c217d954SCole Faust * @param[out] status Status information if requested
594*c217d954SCole Faust */
Tensor(Context & ctx,const TensorDescriptor & desc,StatusCode * status=nullptr)595*c217d954SCole Faust Tensor(Context &ctx, const TensorDescriptor &desc, StatusCode *status = nullptr)
596*c217d954SCole Faust : Tensor(ctx, desc, true, status)
597*c217d954SCole Faust {
598*c217d954SCole Faust }
599*c217d954SCole Faust /** Constructor
600*c217d954SCole Faust *
601*c217d954SCole Faust * @param[in] ctx Context from where the tensor will be created from
602*c217d954SCole Faust * @param[in] desc Tensor descriptor to be used
603*c217d954SCole Faust * @param[in] allocate Flag to indicate if the tensor needs to be allocated
604*c217d954SCole Faust * @param[out] status Status information if requested
605*c217d954SCole Faust */
Tensor(Context & ctx,const TensorDescriptor & desc,bool allocate,StatusCode * status)606*c217d954SCole Faust Tensor(Context &ctx, const TensorDescriptor &desc, bool allocate, StatusCode *status)
607*c217d954SCole Faust {
608*c217d954SCole Faust AclTensor tensor;
609*c217d954SCole Faust const auto st = detail::as_enum<StatusCode>(AclCreateTensor(&tensor, ctx.get(), desc.get(), allocate));
610*c217d954SCole Faust reset(tensor);
611*c217d954SCole Faust report_status(st, "[Compute Library] Failed to create tensor!");
612*c217d954SCole Faust if(status)
613*c217d954SCole Faust {
614*c217d954SCole Faust *status = st;
615*c217d954SCole Faust }
616*c217d954SCole Faust }
617*c217d954SCole Faust /** Maps the backing memory of a given tensor that can be used by the host to access any contents
618*c217d954SCole Faust *
619*c217d954SCole Faust * @return A valid non-zero pointer in case of success else nullptr
620*c217d954SCole Faust */
map()621*c217d954SCole Faust void *map()
622*c217d954SCole Faust {
623*c217d954SCole Faust void *handle = nullptr;
624*c217d954SCole Faust const auto st = detail::as_enum<StatusCode>(AclMapTensor(_object.get(), &handle));
625*c217d954SCole Faust report_status(st, "[Compute Library] Failed to map the tensor and extract the tensor's backing memory!");
626*c217d954SCole Faust return handle;
627*c217d954SCole Faust }
628*c217d954SCole Faust /** Unmaps tensor's memory
629*c217d954SCole Faust *
630*c217d954SCole Faust * @param[in] handle Handle to unmap
631*c217d954SCole Faust *
632*c217d954SCole Faust * @return Status code
633*c217d954SCole Faust */
unmap(void * handle)634*c217d954SCole Faust StatusCode unmap(void *handle)
635*c217d954SCole Faust {
636*c217d954SCole Faust const auto st = detail::as_enum<StatusCode>(AclUnmapTensor(_object.get(), handle));
637*c217d954SCole Faust report_status(st, "[Compute Library] Failed to unmap the tensor!");
638*c217d954SCole Faust return st;
639*c217d954SCole Faust }
640*c217d954SCole Faust /** Import external memory to a given tensor object
641*c217d954SCole Faust *
642*c217d954SCole Faust * @param[in] handle External memory handle
643*c217d954SCole Faust * @param[in] type Type of memory to be imported
644*c217d954SCole Faust *
645*c217d954SCole Faust * @return Status code
646*c217d954SCole Faust */
import(void * handle,ImportType type)647*c217d954SCole Faust StatusCode import(void *handle, ImportType type)
648*c217d954SCole Faust {
649*c217d954SCole Faust const auto st = detail::as_enum<StatusCode>(AclTensorImport(_object.get(), handle, detail::as_cenum<AclImportMemoryType>(type)));
650*c217d954SCole Faust report_status(st, "[Compute Library] Failed to import external memory to tensor!");
651*c217d954SCole Faust return st;
652*c217d954SCole Faust }
653*c217d954SCole Faust /** Get the size of the tensor in byte
654*c217d954SCole Faust *
655*c217d954SCole Faust * @note The size isn't based on allocated memory, but based on information in its descriptor (dimensions, data type, etc.).
656*c217d954SCole Faust *
657*c217d954SCole Faust * @return The size of the tensor in byte
658*c217d954SCole Faust */
get_size()659*c217d954SCole Faust uint64_t get_size()
660*c217d954SCole Faust {
661*c217d954SCole Faust uint64_t size{ 0 };
662*c217d954SCole Faust const auto st = detail::as_enum<StatusCode>(AclGetTensorSize(_object.get(), &size));
663*c217d954SCole Faust report_status(st, "[Compute Library] Failed to get the size of the tensor");
664*c217d954SCole Faust return size;
665*c217d954SCole Faust }
666*c217d954SCole Faust /** Get the descriptor of this tensor
667*c217d954SCole Faust *
668*c217d954SCole Faust * @return The descriptor describing the characteristics of this tensor
669*c217d954SCole Faust */
get_descriptor()670*c217d954SCole Faust TensorDescriptor get_descriptor()
671*c217d954SCole Faust {
672*c217d954SCole Faust AclTensorDescriptor desc;
673*c217d954SCole Faust const auto st = detail::as_enum<StatusCode>(AclGetTensorDescriptor(_object.get(), &desc));
674*c217d954SCole Faust report_status(st, "[Compute Library] Failed to get the descriptor of the tensor");
675*c217d954SCole Faust return TensorDescriptor(desc);
676*c217d954SCole Faust }
677*c217d954SCole Faust };
678*c217d954SCole Faust
679*c217d954SCole Faust /** Tensor pack class
680*c217d954SCole Faust *
681*c217d954SCole Faust * Pack is a utility construct that is used to create a collection of tensors that can then
682*c217d954SCole Faust * be passed into operator as inputs.
683*c217d954SCole Faust */
684*c217d954SCole Faust class TensorPack : public detail::ObjectBase<AclTensorPack_>
685*c217d954SCole Faust {
686*c217d954SCole Faust public:
687*c217d954SCole Faust /** Pack pair construct */
688*c217d954SCole Faust struct PackPair
689*c217d954SCole Faust {
690*c217d954SCole Faust /** Constructor
691*c217d954SCole Faust *
692*c217d954SCole Faust * @param[in] tensor_ Tensor to pack
693*c217d954SCole Faust * @param[in] slot_id_ Slot identification of the tensor in respect with the operator
694*c217d954SCole Faust */
PackPairacl::TensorPack::PackPair695*c217d954SCole Faust PackPair(Tensor *tensor_, int32_t slot_id_)
696*c217d954SCole Faust : tensor(tensor_), slot_id(slot_id_)
697*c217d954SCole Faust {
698*c217d954SCole Faust }
699*c217d954SCole Faust
700*c217d954SCole Faust Tensor *tensor{ nullptr }; /**< Tensor object */
701*c217d954SCole Faust int32_t slot_id{ AclSlotUnknown }; /**< Slot id in respect with the operator */
702*c217d954SCole Faust };
703*c217d954SCole Faust
704*c217d954SCole Faust public:
705*c217d954SCole Faust /** Constructor
706*c217d954SCole Faust *
707*c217d954SCole Faust * @param[in] ctx Context from where the tensor pack will be created from
708*c217d954SCole Faust * @param[out] status Status information if requested
709*c217d954SCole Faust */
TensorPack(Context & ctx,StatusCode * status=nullptr)710*c217d954SCole Faust explicit TensorPack(Context &ctx, StatusCode *status = nullptr)
711*c217d954SCole Faust {
712*c217d954SCole Faust AclTensorPack pack;
713*c217d954SCole Faust const auto st = detail::as_enum<StatusCode>(AclCreateTensorPack(&pack, ctx.get()));
714*c217d954SCole Faust reset(pack);
715*c217d954SCole Faust report_status(st, "[Compute Library] Failure during tensor pack creation");
716*c217d954SCole Faust if(status)
717*c217d954SCole Faust {
718*c217d954SCole Faust *status = st;
719*c217d954SCole Faust }
720*c217d954SCole Faust }
721*c217d954SCole Faust /** Add tensor to tensor pack
722*c217d954SCole Faust *
723*c217d954SCole Faust * @param[in] slot_id Slot id of the tensor in respect with the operator
724*c217d954SCole Faust * @param[in] tensor Tensor to be added in the pack
725*c217d954SCole Faust *
726*c217d954SCole Faust * @return Status code
727*c217d954SCole Faust */
add(Tensor & tensor,int32_t slot_id)728*c217d954SCole Faust StatusCode add(Tensor &tensor, int32_t slot_id)
729*c217d954SCole Faust {
730*c217d954SCole Faust return detail::as_enum<StatusCode>(AclPackTensor(_object.get(), tensor.get(), slot_id));
731*c217d954SCole Faust }
732*c217d954SCole Faust /** Add a list of tensors to a tensor pack
733*c217d954SCole Faust *
734*c217d954SCole Faust * @param[in] packed Pair packs to be added
735*c217d954SCole Faust *
736*c217d954SCole Faust * @return Status code
737*c217d954SCole Faust */
add(std::initializer_list<PackPair> packed)738*c217d954SCole Faust StatusCode add(std::initializer_list<PackPair> packed)
739*c217d954SCole Faust {
740*c217d954SCole Faust const size_t size = packed.size();
741*c217d954SCole Faust std::vector<int32_t> slots(size);
742*c217d954SCole Faust std::vector<AclTensor> tensors(size);
743*c217d954SCole Faust int i = 0;
744*c217d954SCole Faust for(auto &p : packed)
745*c217d954SCole Faust {
746*c217d954SCole Faust slots[i] = p.slot_id;
747*c217d954SCole Faust tensors[i] = AclTensor(p.tensor);
748*c217d954SCole Faust ++i;
749*c217d954SCole Faust }
750*c217d954SCole Faust return detail::as_enum<StatusCode>(AclPackTensors(_object.get(), tensors.data(), slots.data(), size));
751*c217d954SCole Faust }
752*c217d954SCole Faust };
753*c217d954SCole Faust
754*c217d954SCole Faust /** Operator class
755*c217d954SCole Faust *
756*c217d954SCole Faust * Operators are the basic algorithmic blocks responsible for performing distinct operations
757*c217d954SCole Faust */
758*c217d954SCole Faust class Operator : public detail::ObjectBase<AclOperator_>
759*c217d954SCole Faust {
760*c217d954SCole Faust public:
761*c217d954SCole Faust /** Run an operator on a given input list
762*c217d954SCole Faust *
763*c217d954SCole Faust * @param[in,out] queue Queue to scheduler the operator on
764*c217d954SCole Faust * @param pack Tensor list to be used as input
765*c217d954SCole Faust *
766*c217d954SCole Faust * @return Status Code
767*c217d954SCole Faust */
run(Queue & queue,TensorPack & pack)768*c217d954SCole Faust StatusCode run(Queue &queue, TensorPack &pack)
769*c217d954SCole Faust {
770*c217d954SCole Faust return detail::as_cenum<StatusCode>(AclRunOperator(_object.get(), queue.get(), pack.get()));
771*c217d954SCole Faust }
772*c217d954SCole Faust
773*c217d954SCole Faust protected:
774*c217d954SCole Faust /** Constructor */
775*c217d954SCole Faust Operator() = default;
776*c217d954SCole Faust };
777*c217d954SCole Faust
778*c217d954SCole Faust /// Operators
779*c217d954SCole Faust using ActivationDesc = AclActivationDescriptor;
780*c217d954SCole Faust class Activation : public Operator
781*c217d954SCole Faust {
782*c217d954SCole Faust public:
Activation(Context & ctx,const TensorDescriptor & src,const TensorDescriptor & dst,const ActivationDesc & desc,StatusCode * status=nullptr)783*c217d954SCole Faust Activation(Context &ctx, const TensorDescriptor &src, const TensorDescriptor &dst, const ActivationDesc &desc, StatusCode *status = nullptr)
784*c217d954SCole Faust {
785*c217d954SCole Faust AclOperator op;
786*c217d954SCole Faust const auto st = detail::as_enum<StatusCode>(AclActivation(&op, ctx.get(), src.get(), dst.get(), desc));
787*c217d954SCole Faust reset(op);
788*c217d954SCole Faust report_status(st, "[Compute Library] Failure during Activation operator creation");
789*c217d954SCole Faust if(status)
790*c217d954SCole Faust {
791*c217d954SCole Faust *status = st;
792*c217d954SCole Faust }
793*c217d954SCole Faust }
794*c217d954SCole Faust };
795*c217d954SCole Faust } // namespace acl
796*c217d954SCole Faust #undef ARM_COMPUTE_IGNORE_UNUSED
797*c217d954SCole Faust #endif /* ARM_COMPUTE_ACL_HPP_ */
798