blob: 6a9d585c142d1bb03e29964f2064b0e798b46849 [file] [log] [blame]
Georgios Pinitas8a5146f2021-01-12 15:51:07 +00001/*
2 * Copyright (c) 2021 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_ACL_HPP_
25#define ARM_COMPUTE_ACL_HPP_
26
27#include "arm_compute/Acl.h"
28
29#include <cstdlib>
30#include <memory>
31#include <string>
Georgios Pinitas3f26ef42021-02-23 10:01:33 +000032#include <vector>
Georgios Pinitas8a5146f2021-01-12 15:51:07 +000033
34#if defined(ARM_COMPUTE_EXCEPTIONS_ENABLED)
35#include <exception>
36#endif /* defined(ARM_COMPUTE_EXCEPTIONS_ENABLED) */
37
38// Helper Macros
39#define ARM_COMPUTE_IGNORE_UNUSED(x) (void)(x)
40
41namespace acl
42{
43// Forward declarations
44class Context;
Georgios Pinitasc3c352e2021-03-18 10:59:40 +000045class Queue;
Georgios Pinitas3f26ef42021-02-23 10:01:33 +000046class Tensor;
47class TensorPack;
Georgios Pinitas8a5146f2021-01-12 15:51:07 +000048
49/**< Status code enum */
50enum class StatusCode
51{
52 Success = AclSuccess,
53 RuntimeError = AclRuntimeError,
54 OutOfMemory = AclOutOfMemory,
55 Unimplemented = AclUnimplemented,
56 UnsupportedTarget = AclUnsupportedTarget,
57 InvalidArgument = AclInvalidArgument,
58 InvalidTarget = AclInvalidTarget,
59 UnsupportedConfig = AclUnsupportedConfig,
60 InvalidObjectState = AclInvalidObjectState,
61};
62
63/**< Utility namespace containing helpers functions */
64namespace detail
65{
66/** Construct to handle destruction of objects
67 *
68 * @tparam T Object base type
69 */
70template <typename T>
71struct ObjectDeleter
72{
73};
74
75#define OBJECT_DELETER(obj, func) \
76 template <> \
77 struct ObjectDeleter<obj> \
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010078 \
Georgios Pinitas8a5146f2021-01-12 15:51:07 +000079 { \
80 static inline AclStatus Destroy(obj v) \
81 { \
82 return func(v); \
83 } \
84 };
85
86OBJECT_DELETER(AclContext, AclDestroyContext)
Georgios Pinitasc3c352e2021-03-18 10:59:40 +000087OBJECT_DELETER(AclQueue, AclDestroyQueue)
Georgios Pinitas3f26ef42021-02-23 10:01:33 +000088OBJECT_DELETER(AclTensor, AclDestroyTensor)
89OBJECT_DELETER(AclTensorPack, AclDestroyTensorPack)
Georgios Pinitas41648142021-08-03 08:24:00 +010090OBJECT_DELETER(AclOperator, AclDestroyOperator)
Georgios Pinitas8a5146f2021-01-12 15:51:07 +000091
92#undef OBJECT_DELETER
93
94/** Convert a strongly typed enum to an old plain c enum
95 *
96 * @tparam E Plain old C enum
97 * @tparam SE Strongly typed resulting enum
98 *
99 * @param[in] v Value to convert
100 *
101 * @return A corresponding plain old C enumeration
102 */
103template <typename E, typename SE>
104constexpr E as_cenum(SE v) noexcept
105{
106 return static_cast<E>(static_cast<typename std::underlying_type<SE>::type>(v));
107}
108
109/** Convert plain old enumeration to a strongly typed enum
110 *
111 * @tparam SE Strongly typed resulting enum
112 * @tparam E Plain old C enum
113 *
114 * @param[in] val Value to convert
115 *
116 * @return A corresponding strongly typed enumeration
117 */
118template <typename SE, typename E>
119constexpr SE as_enum(E val) noexcept
120{
121 return static_cast<SE>(val);
122}
123
124/** Object base class for library objects
125 *
126 * Class is defining basic common interface for all the library objects
127 *
128 * @tparam T Object type to be templated on
129 */
130template <typename T>
131class ObjectBase
132{
133public:
134 /** Destructor */
135 ~ObjectBase() = default;
136 /** Copy constructor */
137 ObjectBase(const ObjectBase<T> &) = default;
138 /** Move Constructor */
139 ObjectBase(ObjectBase<T> &&) = default;
140 /** Copy assignment operator */
141 ObjectBase<T> &operator=(const ObjectBase<T> &) = default;
142 /** Move assignment operator */
143 ObjectBase<T> &operator=(ObjectBase<T> &&) = default;
144 /** Reset object value
145 *
146 * @param [in] val Value to set
147 */
148 void reset(T *val)
149 {
150 _object.reset(val, detail::ObjectDeleter<T *>::Destroy);
151 }
152 /** Access uderlying object
153 *
154 * @return Underlying object
155 */
156 const T *get() const
157 {
158 return _object.get();
159 }
160 /** Access uderlying object
161 *
162 * @return Underlying object
163 */
164 T *get()
165 {
166 return _object.get();
167 }
168
169protected:
170 /** Constructor */
171 ObjectBase() = default;
172
173protected:
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100174 std::shared_ptr<T> _object{nullptr}; /**< Library object */
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000175};
176
177/** Equality operator for library object
178 *
179 * @tparam T Parameter to template on
180 *
181 * @param[in] lhs Left hand-side argument
182 * @param[in] rhs Right hand-side argument
183 *
184 * @return True if objects are equal, else false
185 */
186template <typename T>
187bool operator==(const ObjectBase<T> &lhs, const ObjectBase<T> &rhs)
188{
189 return lhs.get() == rhs.get();
190}
191
192/** Inequality operator for library object
193 *
194 * @tparam T Parameter to template on
195 *
196 * @param[in] lhs Left hand-side argument
197 * @param[in] rhs Right hand-side argument
198 *
199 * @return True if objects are equal, else false
200 */
201template <typename T>
202bool operator!=(const ObjectBase<T> &lhs, const ObjectBase<T> &rhs)
203{
204 return !(lhs == rhs);
205}
206} // namespace detail
207
208#if defined(ARM_COMPUTE_EXCEPTIONS_ENABLED)
209/** Status class
210 *
211 * Class is an extension of std::exception and contains the underlying
212 * status construct and an error explanatory message to be reported.
213 *
214 * @note Class is visible only when exceptions are enabled during compilation
215 */
216class Status : public std::exception
217{
218public:
219 /** Constructor
220 *
221 * @param[in] status Status returned
222 * @param[in] msg Error message to be bound with the exception
223 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100224 Status(StatusCode status, const std::string &msg) : _status(status), _msg(msg)
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000225 {
226 }
227 /** Returns an explanatory exception message
228 *
229 * @return Status message
230 */
231 const char *what() const noexcept override
232 {
233 return _msg.c_str();
234 }
235 /** Underlying status accessor
236 *
237 * @return Status code
238 */
239 StatusCode status() const
240 {
241 return _status;
242 }
243 /** Explicit status converter
244 *
245 * @return Status code
246 */
247 explicit operator StatusCode() const
248 {
249 return _status;
250 }
251
252private:
253 StatusCode _status; /**< Status code */
254 std::string _msg; /**< Status message */
255};
256
257/** Reports an error status and throws an exception object in case of failure
258 *
259 * @note This implementation is used when exceptions are enabled during compilation
260 *
261 * @param[in] status Status to report
262 * @param[in] msg Explanatory error messaged
263 *
264 * @return Status code
265 */
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000266static inline void report_status(StatusCode status, const std::string &msg)
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000267{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100268 if (status != StatusCode::Success)
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000269 {
270 throw Status(status, msg);
271 }
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000272}
273#else /* defined(ARM_COMPUTE_EXCEPTIONS_ENABLED) */
274/** Reports a status code
275 *
276 * @note This implementation is used when exceptions are disabled during compilation
277 * @note Message is surpressed and not reported in this case
278 *
279 * @param[in] status Status to report
280 * @param[in] msg Explanatory error messaged
281 *
282 * @return Status code
283 */
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000284static inline void report_status(StatusCode status, const std::string &msg)
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000285{
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000286 ARM_COMPUTE_IGNORE_UNUSED(status);
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000287 ARM_COMPUTE_IGNORE_UNUSED(msg);
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000288}
289#endif /* defined(ARM_COMPUTE_EXCEPTIONS_ENABLED) */
290
291/**< Target enum */
292enum class Target
293{
294 Cpu = AclCpu, /**< Cpu target that leverages SIMD */
295 GpuOcl = AclGpuOcl /**< Gpu target that leverages OpenCL */
296};
297
298/**< Available execution modes */
299enum class ExecutionMode
300{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100301 FastRerun =
302 AclPreferFastRerun, /**< Prefer minimum latency in consecutive runs, might introduce higher startup times */
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000303 FastStart = AclPreferFastStart, /**< Prefer minimizing startup time */
304};
305
306/** Context class
307 *
308 * Context acts as a central aggregate service for further objects created from it.
309 * It provides, internally, common facilities in order to avoid the use of global
310 * statically initialized objects that can lead to important side-effect under
311 * specific execution contexts.
312 *
313 * For example context contains allocators for object creation, for further backing memory allocation,
314 * any serialization interfaces and other modules that affect the construction of objects,
315 * like program caches for OpenCL.
316 */
317class Context : public detail::ObjectBase<AclContext_>
318{
319public:
320 /**< Context options */
321 struct Options
322 {
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000323 static constexpr int32_t num_threads_auto = -1; /**< Allow runtime to specify number of threads */
324
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000325 /** Default Constructor
326 *
327 * @note By default no precision loss is enabled for operators
328 * @note By default the preferred execution mode is to favor multiple consecutive reruns of an operator
329 */
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000330 Options()
331 : Options(ExecutionMode::FastRerun /* mode */,
332 AclCpuCapabilitiesAuto /* caps */,
333 false /* enable_fast_math */,
334 nullptr /* kernel_config */,
335 num_threads_auto /* max_compute_units */,
336 nullptr /* allocator */)
337 {
338 }
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000339 /** Constructor
340 *
341 * @param[in] mode Execution mode to be used
342 * @param[in] caps Capabilities to be used
343 * @param[in] enable_fast_math Allow precision loss in favor of performance
344 * @param[in] kernel_config Kernel configuration file containing construction tuning meta-data
345 * @param[in] max_compute_units Max compute units that are expected to used
346 * @param[in] allocator Allocator to be used for internal memory allocation
347 */
348 Options(ExecutionMode mode,
349 AclTargetCapabilities caps,
350 bool enable_fast_math,
351 const char *kernel_config,
352 int32_t max_compute_units,
353 AclAllocator *allocator)
354 {
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000355 copts.mode = detail::as_cenum<AclExecutionMode>(mode);
356 copts.capabilities = caps;
357 copts.enable_fast_math = enable_fast_math;
358 copts.kernel_config_file = kernel_config;
359 copts.max_compute_units = max_compute_units;
360 copts.allocator = allocator;
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000361 }
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000362
363 AclContextOptions copts{};
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000364 };
365
366public:
367 /** Constructor
368 *
369 * @note Serves as a simpler delegate constructor
370 * @note As context options, default conservative options will be used
371 *
372 * @param[in] target Target to create context for
373 * @param[out] status Status information if requested
374 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100375 explicit Context(Target target, StatusCode *status = nullptr) : Context(target, Options(), status)
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000376 {
377 }
378 /** Constructor
379 *
380 * @param[in] target Target to create context for
381 * @param[in] options Context construction options
382 * @param[out] status Status information if requested
383 */
384 Context(Target target, const Options &options, StatusCode *status = nullptr)
385 {
386 AclContext ctx;
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100387 const auto st =
388 detail::as_enum<StatusCode>(AclCreateContext(&ctx, detail::as_cenum<AclTarget>(target), &options.copts));
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000389 reset(ctx);
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000390 report_status(st, "[Compute Library] Failed to create context");
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100391 if (status)
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000392 {
393 *status = st;
394 }
395 }
396};
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000397
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000398/**< Available tuning modes */
399enum class TuningMode
400{
401 Rapid = AclRapid,
402 Normal = AclNormal,
403 Exhaustive = AclExhaustive
404};
405
406/** Queue class
407 *
408 * Queue is responsible for the execution related aspects, with main responsibilities those of
409 * scheduling and tuning operators.
410 *
411 * Multiple queues can be created from the same context, and the same operator can be scheduled on each concurrently.
412 *
413 * @note An operator might depend on the maximum possible compute units that are provided in the context,
414 * thus in cases where the number of the scheduling units of the queue are greater might lead to errors.
415 */
416class Queue : public detail::ObjectBase<AclQueue_>
417{
418public:
419 /**< Queue options */
420 struct Options
421 {
422 /** Default Constructor
423 *
424 * As default options, no tuning will be performed, and the number of scheduling units will
425 * depends on internal device discovery functionality
426 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100427 Options() : opts{AclTuningModeNone, 0} {};
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000428 /** Constructor
429 *
430 * @param[in] mode Tuning mode to be used
431 * @param[in] compute_units Number of scheduling units to be used
432 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100433 Options(TuningMode mode, int32_t compute_units) : opts{detail::as_cenum<AclTuningMode>(mode), compute_units}
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000434 {
435 }
436
437 AclQueueOptions opts;
438 };
439
440public:
441 /** Constructor
442 *
443 * @note Serves as a simpler delegate constructor
444 * @note As queue options, default conservative options will be used
445 *
446 * @param[in] ctx Context to create queue for
447 * @param[out] status Status information if requested
448 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100449 explicit Queue(Context &ctx, StatusCode *status = nullptr) : Queue(ctx, Options(), status)
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000450 {
451 }
452 /** Constructor
453 *
454 * @note As queue options, default conservative options will be used
455 *
456 * @param[in] ctx Context from where the queue will be created from
457 * @param[in] options Queue options to be used
458 * @param[out] status Status information if requested
459 */
460 explicit Queue(Context &ctx, const Options &options = Options(), StatusCode *status = nullptr)
461 {
462 AclQueue queue;
463 const auto st = detail::as_enum<StatusCode>(AclCreateQueue(&queue, ctx.get(), &options.opts));
464 reset(queue);
465 report_status(st, "[Compute Library] Failed to create queue!");
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100466 if (status)
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000467 {
468 *status = st;
469 }
470 }
471 /** Block until all the tasks of the queue have been marked as finished
472 *
473 * @return Status code
474 */
475 StatusCode finish()
476 {
477 return detail::as_enum<StatusCode>(AclQueueFinish(_object.get()));
478 }
479};
480
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000481/**< Data type enumeration */
482enum class DataType
483{
484 Unknown = AclDataTypeUnknown,
485 UInt8 = AclUInt8,
486 Int8 = AclInt8,
487 UInt16 = AclUInt16,
488 Int16 = AclInt16,
489 UInt32 = AclUint32,
490 Int32 = AclInt32,
491 Float16 = AclFloat16,
492 BFloat16 = AclBFloat16,
493 Float32 = AclFloat32,
494};
495
496/** Tensor Descriptor class
497 *
498 * Structure that contains all the required meta-data to represent a tensor
499 */
500class TensorDescriptor
501{
502public:
503 /** Constructor
504 *
505 * @param[in] shape Shape of the tensor
506 * @param[in] data_type Data type of the tensor
507 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100508 TensorDescriptor(const std::vector<int32_t> &shape, DataType data_type) : _shape(shape), _data_type(data_type)
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000509 {
510 _cdesc.ndims = _shape.size();
511 _cdesc.shape = _shape.data();
512 _cdesc.data_type = detail::as_cenum<AclDataType>(_data_type);
513 _cdesc.strides = nullptr;
514 _cdesc.boffset = 0;
515 }
Sang-Hoon Parkc6fcfb42021-03-31 15:18:16 +0100516 /** Constructor
517 *
518 * @param[in] desc C-type descriptor
519 */
520 explicit TensorDescriptor(const AclTensorDescriptor &desc)
521 {
522 _cdesc = desc;
523 _data_type = detail::as_enum<DataType>(desc.data_type);
524 _shape.reserve(desc.ndims);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100525 for (int32_t d = 0; d < desc.ndims; ++d)
Sang-Hoon Parkc6fcfb42021-03-31 15:18:16 +0100526 {
527 _shape.emplace_back(desc.shape[d]);
528 }
529 }
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000530 /** Get underlying C tensor descriptor
531 *
532 * @return Underlying structure
533 */
534 const AclTensorDescriptor *get() const
535 {
536 return &_cdesc;
537 }
Sang-Hoon Parkc6fcfb42021-03-31 15:18:16 +0100538 /** Operator to compare two TensorDescriptor
539 *
540 * @param[in] other The instance to compare against
541 *
542 * @return True if two instances have the same shape and data type
543 */
544 bool operator==(const TensorDescriptor &other)
545 {
546 bool is_same = true;
547
548 is_same &= _data_type == other._data_type;
549 is_same &= _shape.size() == other._shape.size();
550
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100551 if (is_same)
Sang-Hoon Parkc6fcfb42021-03-31 15:18:16 +0100552 {
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100553 for (uint32_t d = 0; d < _shape.size(); ++d)
Sang-Hoon Parkc6fcfb42021-03-31 15:18:16 +0100554 {
555 is_same &= _shape[d] == other._shape[d];
556 }
557 }
558
559 return is_same;
560 }
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000561
562private:
563 std::vector<int32_t> _shape{};
564 DataType _data_type{};
565 AclTensorDescriptor _cdesc{};
566};
567
568/** Import memory types */
569enum class ImportType
570{
571 Host = AclImportMemoryType::AclHostPtr
572};
573
574/** Tensor class
575 *
576 * Tensor is an mathematical construct that can represent an N-Dimensional space.
577 *
578 * @note Maximum dimensionality support is 6 internally at the moment
579 */
580class Tensor : public detail::ObjectBase<AclTensor_>
581{
582public:
583 /** Constructor
584 *
585 * @note Tensor memory is allocated
586 *
587 * @param[in] ctx Context from where the tensor will be created from
588 * @param[in] desc Tensor descriptor to be used
589 * @param[out] status Status information if requested
590 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100591 Tensor(Context &ctx, const TensorDescriptor &desc, StatusCode *status = nullptr) : Tensor(ctx, desc, true, status)
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000592 {
593 }
594 /** Constructor
595 *
596 * @param[in] ctx Context from where the tensor will be created from
597 * @param[in] desc Tensor descriptor to be used
598 * @param[in] allocate Flag to indicate if the tensor needs to be allocated
599 * @param[out] status Status information if requested
600 */
601 Tensor(Context &ctx, const TensorDescriptor &desc, bool allocate, StatusCode *status)
602 {
603 AclTensor tensor;
604 const auto st = detail::as_enum<StatusCode>(AclCreateTensor(&tensor, ctx.get(), desc.get(), allocate));
605 reset(tensor);
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000606 report_status(st, "[Compute Library] Failed to create tensor!");
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100607 if (status)
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000608 {
609 *status = st;
610 }
611 }
612 /** Maps the backing memory of a given tensor that can be used by the host to access any contents
613 *
614 * @return A valid non-zero pointer in case of success else nullptr
615 */
616 void *map()
617 {
618 void *handle = nullptr;
619 const auto st = detail::as_enum<StatusCode>(AclMapTensor(_object.get(), &handle));
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000620 report_status(st, "[Compute Library] Failed to map the tensor and extract the tensor's backing memory!");
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000621 return handle;
622 }
623 /** Unmaps tensor's memory
624 *
625 * @param[in] handle Handle to unmap
626 *
627 * @return Status code
628 */
629 StatusCode unmap(void *handle)
630 {
631 const auto st = detail::as_enum<StatusCode>(AclUnmapTensor(_object.get(), handle));
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000632 report_status(st, "[Compute Library] Failed to unmap the tensor!");
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000633 return st;
634 }
635 /** Import external memory to a given tensor object
636 *
637 * @param[in] handle External memory handle
638 * @param[in] type Type of memory to be imported
639 *
640 * @return Status code
641 */
642 StatusCode import(void *handle, ImportType type)
643 {
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100644 const auto st = detail::as_enum<StatusCode>(
645 AclTensorImport(_object.get(), handle, detail::as_cenum<AclImportMemoryType>(type)));
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000646 report_status(st, "[Compute Library] Failed to import external memory to tensor!");
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000647 return st;
648 }
Sang-Hoon Parkc6fcfb42021-03-31 15:18:16 +0100649 /** Get the size of the tensor in byte
650 *
651 * @note The size isn't based on allocated memory, but based on information in its descriptor (dimensions, data type, etc.).
652 *
653 * @return The size of the tensor in byte
654 */
655 uint64_t get_size()
656 {
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100657 uint64_t size{0};
Sang-Hoon Parkc6fcfb42021-03-31 15:18:16 +0100658 const auto st = detail::as_enum<StatusCode>(AclGetTensorSize(_object.get(), &size));
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000659 report_status(st, "[Compute Library] Failed to get the size of the tensor");
Sang-Hoon Parkc6fcfb42021-03-31 15:18:16 +0100660 return size;
661 }
662 /** Get the descriptor of this tensor
663 *
664 * @return The descriptor describing the characteristics of this tensor
665 */
666 TensorDescriptor get_descriptor()
667 {
668 AclTensorDescriptor desc;
669 const auto st = detail::as_enum<StatusCode>(AclGetTensorDescriptor(_object.get(), &desc));
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000670 report_status(st, "[Compute Library] Failed to get the descriptor of the tensor");
Sang-Hoon Parkc6fcfb42021-03-31 15:18:16 +0100671 return TensorDescriptor(desc);
672 }
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000673};
674
675/** Tensor pack class
676 *
677 * Pack is a utility construct that is used to create a collection of tensors that can then
678 * be passed into operator as inputs.
679 */
680class TensorPack : public detail::ObjectBase<AclTensorPack_>
681{
682public:
683 /** Pack pair construct */
684 struct PackPair
685 {
686 /** Constructor
687 *
688 * @param[in] tensor_ Tensor to pack
689 * @param[in] slot_id_ Slot identification of the tensor in respect with the operator
690 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100691 PackPair(Tensor *tensor_, int32_t slot_id_) : tensor(tensor_), slot_id(slot_id_)
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000692 {
693 }
694
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100695 Tensor *tensor{nullptr}; /**< Tensor object */
696 int32_t slot_id{AclSlotUnknown}; /**< Slot id in respect with the operator */
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000697 };
698
699public:
700 /** Constructor
701 *
702 * @param[in] ctx Context from where the tensor pack will be created from
703 * @param[out] status Status information if requested
704 */
705 explicit TensorPack(Context &ctx, StatusCode *status = nullptr)
706 {
707 AclTensorPack pack;
708 const auto st = detail::as_enum<StatusCode>(AclCreateTensorPack(&pack, ctx.get()));
709 reset(pack);
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000710 report_status(st, "[Compute Library] Failure during tensor pack creation");
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100711 if (status)
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000712 {
713 *status = st;
714 }
715 }
716 /** Add tensor to tensor pack
717 *
718 * @param[in] slot_id Slot id of the tensor in respect with the operator
719 * @param[in] tensor Tensor to be added in the pack
720 *
721 * @return Status code
722 */
723 StatusCode add(Tensor &tensor, int32_t slot_id)
724 {
725 return detail::as_enum<StatusCode>(AclPackTensor(_object.get(), tensor.get(), slot_id));
726 }
727 /** Add a list of tensors to a tensor pack
728 *
729 * @param[in] packed Pair packs to be added
730 *
731 * @return Status code
732 */
733 StatusCode add(std::initializer_list<PackPair> packed)
734 {
735 const size_t size = packed.size();
736 std::vector<int32_t> slots(size);
737 std::vector<AclTensor> tensors(size);
738 int i = 0;
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100739 for (auto &p : packed)
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000740 {
741 slots[i] = p.slot_id;
742 tensors[i] = AclTensor(p.tensor);
743 ++i;
744 }
745 return detail::as_enum<StatusCode>(AclPackTensors(_object.get(), tensors.data(), slots.data(), size));
746 }
747};
Georgios Pinitas06ac6e42021-07-05 08:08:52 +0100748
749/** Operator class
750 *
751 * Operators are the basic algorithmic blocks responsible for performing distinct operations
752 */
753class Operator : public detail::ObjectBase<AclOperator_>
754{
755public:
756 /** Run an operator on a given input list
757 *
758 * @param[in,out] queue Queue to scheduler the operator on
759 * @param pack Tensor list to be used as input
760 *
761 * @return Status Code
762 */
763 StatusCode run(Queue &queue, TensorPack &pack)
764 {
765 return detail::as_cenum<StatusCode>(AclRunOperator(_object.get(), queue.get(), pack.get()));
766 }
767
768protected:
769 /** Constructor */
770 Operator() = default;
771};
Georgios Pinitas41648142021-08-03 08:24:00 +0100772
773/// Operators
774using ActivationDesc = AclActivationDescriptor;
775class Activation : public Operator
776{
777public:
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100778 Activation(Context &ctx,
779 const TensorDescriptor &src,
780 const TensorDescriptor &dst,
781 const ActivationDesc &desc,
782 StatusCode *status = nullptr)
Georgios Pinitas41648142021-08-03 08:24:00 +0100783 {
784 AclOperator op;
785 const auto st = detail::as_enum<StatusCode>(AclActivation(&op, ctx.get(), src.get(), dst.get(), desc));
786 reset(op);
787 report_status(st, "[Compute Library] Failure during Activation operator creation");
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100788 if (status)
Georgios Pinitas41648142021-08-03 08:24:00 +0100789 {
790 *status = st;
791 }
792 }
793};
Georgios Pinitas8a5146f2021-01-12 15:51:07 +0000794} // namespace acl
795#undef ARM_COMPUTE_IGNORE_UNUSED
796#endif /* ARM_COMPUTE_ACL_HPP_ */