1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_IPREPARED_MODEL_H
18 #define ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_IPREPARED_MODEL_H
19 
20 #include <any>
21 #include <functional>
22 #include <memory>
23 #include <utility>
24 #include <vector>
25 
26 #include "nnapi/Types.h"
27 
28 namespace android::nn {
29 
30 /**
31  * IPreparedModel describes a model that has been prepared for execution and is used to launch
32  * executions.
33  *
34  * This interface is thread-safe, and any class that implements this interface must be thread-safe.
35  */
36 class IPreparedModel {
37    public:
38     /**
39      * Performs a synchronous execution on a prepared model.
40      *
41      * The execution is performed synchronously with respect to the caller. IPreparedModel::execute
42      * must verify the inputs to the function are correct. If there is an error,
43      * IPreparedModel::execute must immediately return {@link ErrorStatus::INVALID_ARGUMENT} as a
44      * ExecutionError. If the inputs to the function are valid and there is no error,
45      * IPreparedModel::execute must perform the execution, and must not return until the execution
46      * is complete.
47      *
48      * The caller must not change the content of any data object referenced by request (described by
49      * the {@link DataLocation} of a {@link RequestArgument}) until IPreparedModel::execute returns.
50      * IPreparedModel::execute must not change the content of any of the data objects corresponding
51      * to request inputs.
52      *
53      * If the prepared model was prepared from a model wherein all tensor operands have fully
54      * specified dimensions, and the inputs to the function are valid, and at execution time every
55      * operation's input operands have legal values, then the execution should complete
56      * successfully. There must be no failure unless the device itself is in a bad state.
57      *
58      * IPreparedModel::execute may be called with an optional deadline. If the execution is not
59      * able to be completed before the provided deadline, the execution may be aborted, and either
60      * {@link ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
61      * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned as a ExecutionError.
62      *
63      * @param request The input and output information on which the prepared model is to be
64      *     executed.
65      * @param measure Specifies whether or not to measure duration of the execution.
66      * @param deadline Optional time point. If provided, execute is expected to complete by this
67      *     time point. If it is not able to be completed by the deadline, the execution may be
68      *     aborted.
69      * @param loopTimeoutDuration The maximum amount of time that should be spent executing a {@link
70      *     OperationType::WHILE} operation. If a loop condition model does not output `false` within
71      *     this duration, the execution must be aborted. If no loop timeout duration is provided,
72      *     the maximum amount of time is {@link kControlFlowTimeoutDefault}. When provided, the
73      *     duration must not exceed {@link kControlFlowTimeoutMaximum}.
74      * @return A pair consisting of:
75      *     - A list of shape information of model output operands. The index into "outputShapes"
76      *       corresponds to the index of the output operand in the Request outputs vector.
77      *       outputShapes must be empty unless the execution is successful or the ExecutionResult is
78      *       {@link ErrorStatus::OUTPUT_INSUFFICIENT_SIZE}. outputShapes may be empty if the
79      *       execution is successful and all model output operands are fully-specified at execution
80      *       time. outputShapes must have the same number of elements as the number of model output
81      *       operands if the ExecutionResult is {@link ErrorStatus::OUTPUT_INSUFFICIENT_SIZE}, or if
82      *       the execution is successful and the model has at least one output operand that is not
83      *       fully-specified.
84      *     - Duration of execution. Unless measure is YES and the execution is successful, all times
85      *       must be reported as UINT64_MAX. A driver may choose to report any time as UINT64_MAX,
86      *       indicating that measurement is not available.
87      */
88     virtual ExecutionResult<std::pair<std::vector<OutputShape>, Timing>> execute(
89             const Request& request, MeasureTiming measure, const OptionalTimePoint& deadline,
90             const OptionalDuration& loopTimeoutDuration) const = 0;
91 
92     /**
93      * Launch a fenced asynchronous execution on a prepared model.
94      *
95      * The execution is performed asynchronously with respect to the caller.
96      * IPreparedModel::executeFenced must verify its inputs are correct, and the usages of memory
97      * pools allocated by IDevice::allocate are valid. If there is an error,
98      * IPreparedModel::executeFenced must immediately return {@link ErrorStatus::INVALID_ARGUMENT}
99      * as a GeneralError. If the inputs to the function are valid and there is no error,
100      * IPreparedModel::executeFenced must dispatch an asynchronous task to perform the execution in
101      * the background, and immediately return with a sync fence that will be signaled once the
102      * execution is completed and a callback that can be used by the client to query the duration
103      * and runtime error status. If the task has finished before the call returns, an empty handle
104      * may be returned for syncFence. The execution must wait for all the sync fences (if any) in
105      * waitFor to be signaled before starting the actual execution.
106      *
107      * When the asynchronous task has finished its execution, it must immediately signal the
108      * syncFence returned from the IPreparedModel::executeFenced call. After the syncFence is
109      * signaled, the task must not modify the content of any data object referenced by request
110      * (described by the {@link DataLocation} of a {@link Request::Argument}).
111      *
112      * IPreparedModel::executeFenced may be called with an optional deadline and an optional
113      * duration. If the execution is not able to be completed before the provided deadline or within
114      * the timeout duration (measured from when all sync fences in waitFor are signaled), whichever
115      * comes earlier, the execution may be aborted, and either {@link
116      * ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link ErrorStatus::MISSED_DEADLINE_PERSISTENT}
117      * may be returned as an GeneralError. The error due to an abort must be sent the same way as
118      * other errors, described above.
119      *
120      * If any of the sync fences in waitFor changes to error status after the
121      * IPreparedModel::executeFenced call succeeds, or the execution is aborted because it cannot
122      * finish before the deadline has been reached or the duration has elapsed, the driver must
123      * immediately set the returned syncFence to error status.
124      *
125      * @param request The input and output information on which the prepared model is to be
126      *     executed.
127      * @param waitFor A vector of sync fence file descriptors. The execution must wait for all sync
128      *     fence to be signaled before starting the task.
129      * @param measure Specifies whether or not to measure duration of the execution.
130      * @param deadline The time by which execution is expected to complete. If the execution cannot
131      *     be finished by the deadline, the execution may be aborted.
132      * @param loopTimeoutDuration The maximum amount of time that should be spent executing a {@link
133      *     OperationType::WHILE} operation. If a loop condition model does not output `false` within
134      *     this duration, the execution must be aborted. If no loop timeout duration is provided,
135      *     the maximum amount of time is {@link kControlFlowTimeoutDefault}. When provided, the
136      *     duration must not exceed {@link kControlFlowTimeoutMaximum}.
137      * @param timeoutDurationAfterFence The timeout duration within which the execution is expected
138      *     to complete after all sync fences in waitFor are signaled.
139      * @return A pair consisting of:
140      *     - A syncFence that will be triggered when the task is completed. The syncFence will be
141      *       set to error if critical error occurs when doing actual evaluation.
142      *     - A callback can be used to query information like duration and detailed runtime error
143      *       status when the task is completed.
144      */
145     virtual GeneralResult<std::pair<SyncFence, ExecuteFencedInfoCallback>> executeFenced(
146             const Request& request, const std::vector<SyncFence>& waitFor, MeasureTiming measure,
147             const OptionalTimePoint& deadline, const OptionalDuration& loopTimeoutDuration,
148             const OptionalDuration& timeoutDurationAfterFence) const = 0;
149 
150     /**
151      * Create a reusable execution from a request and execution configurations.
152      *
153      * IPreparedModel::createReusableExecution must verify the inputs to the function are correct.
154      * If there is an error, IPreparedModel::createReusableExecution must immediately return
155      * {@link ErrorStatus::INVALID_ARGUMENT} as a GeneralError. If the inputs to the function are
156      * valid and there is no error, IPreparedModel::createReusableExecution must construct a
157      * reusable execution.
158      *
159      * @param request The input and output information on which the prepared model is to be
160      *     executed.
161      * @param measure Specifies whether or not to measure duration of the computations performed
162      *     with the returned execution.
163      * @param loopTimeoutDuration The maximum amount of time that should be spent executing a {@link
164      *     OperationType::WHILE} operation. During a computation with the returned execution, if a
165      *     loop condition model does not output `false` within this duration, the computation must
166      *     be aborted. If no loop timeout duration is provided, the maximum amount of time is
167      *     {@link LoopTimeoutDurationNs::DEFAULT}. When provided, the duration must not exceed
168      *     {@link LoopTimeoutDurationNs::MAXIMUM}.
169      * @return execution An IExecution object representing a reusable execution that has been
170      *     specialized for a fixed request, otherwise GeneralError.
171      */
172     virtual GeneralResult<SharedExecution> createReusableExecution(
173             const Request& request, MeasureTiming measure,
174             const OptionalDuration& loopTimeoutDuration) const = 0;
175 
176     /**
177      * Creates a burst controller on a prepared model.
178      *
179      * @return ExecutionBurstController Execution burst controller object, otherwise GeneralError.
180      */
181     virtual GeneralResult<SharedBurst> configureExecutionBurst() const = 0;
182 
183     /**
184      * Return the resource that the IPreparedModel wraps, or any empty std::any.
185      *
186      * This method is used for IDevice::allocate.
187      *
188      * @return std::any containing the underlying resource.
189      */
190     virtual std::any getUnderlyingResource() const = 0;
191 
192     // Public virtual destructor to allow objects to be stored (and destroyed) as smart pointers.
193     // E.g., std::unique_ptr<IPreparedModel>.
194     virtual ~IPreparedModel() = default;
195 
196    protected:
197     // Protect the non-destructor special member functions to prevent object slicing.
198     IPreparedModel() = default;
199     IPreparedModel(const IPreparedModel&) = default;
200     IPreparedModel(IPreparedModel&&) noexcept = default;
201     IPreparedModel& operator=(const IPreparedModel&) = default;
202     IPreparedModel& operator=(IPreparedModel&&) noexcept = default;
203 };
204 
205 }  // namespace android::nn
206 
207 #endif  // ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_IPREPARED_MODEL_H
208