xref: /aosp_15_r20/external/ComputeLibrary/arm_compute/Acl.hpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
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