blob: e63eb3cc044e7e7b457c6a1186cb923b3d070d4b [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_TYPES_H
#define ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_TYPES_H
#include <android-base/chrono_utils.h>
#include <android-base/expected.h>
#include <android-base/unique_fd.h>
#include <array>
#include <chrono>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>
#include "nnapi/OperandTypes.h"
#include "nnapi/OperationTypes.h"
#include "nnapi/Result.h"
// Forward declare AHardwareBuffer
extern "C" typedef struct AHardwareBuffer AHardwareBuffer;
namespace android::nn {
// Forward declarations
class IBuffer;
class IBurst;
class IDevice;
class IExecution;
class IPreparedModel;
struct Memory;
// Constants
constexpr float kDefaultExecTime = std::numeric_limits<float>::max();
constexpr float kDefaultPowerUsage = std::numeric_limits<float>::max();
constexpr uint32_t kByteSizeOfCacheToken = 32;
constexpr uint32_t kMaxNumberOfCacheFiles = 32;
/**
* Numeric values of extension operand and operation types have the
* following structure:
* - 16 high bits represent the "prefix", which corresponds uniquely to the
* extension name.
* - 16 low bits represent the type ID within the extension.
*/
constexpr uint8_t kExtensionTypeBits = 16;
constexpr uint8_t kExtensionPrefixBits = 16;
constexpr uint32_t kDefaultRequestMemoryAlignment = 64;
constexpr uint32_t kDefaultRequestMemoryPadding = 64;
constexpr uint32_t kMinMemoryAlignment = alignof(std::max_align_t);
constexpr uint32_t kMinMemoryPadding = 1;
constexpr auto kLoopTimeoutDefault = std::chrono::seconds{2};
constexpr auto kLoopTimeoutMaximum = std::chrono::seconds{15};
// Aliases
using SharedBuffer = std::shared_ptr<const IBuffer>;
using SharedBurst = std::shared_ptr<const IBurst>;
using SharedDevice = std::shared_ptr<const IDevice>;
using SharedExecution = std::shared_ptr<const IExecution>;
using SharedMemory = std::shared_ptr<const Memory>;
using SharedPreparedModel = std::shared_ptr<const IPreparedModel>;
// Canonical types
/**
* Status of a device.
*/
enum class DeviceStatus {
AVAILABLE = 0,
BUSY = 1,
OFFLINE = 2,
UNKNOWN = 3,
};
/**
* Execution preferences.
*/
enum class ExecutionPreference {
/**
* Prefer executing in a way that minimizes battery drain.
* This is desirable for compilations that will be executed often.
*/
LOW_POWER = 0,
/**
* Prefer returning a single answer as fast as possible, even if this causes
* more power consumption.
*/
FAST_SINGLE_ANSWER = 1,
/**
* Prefer maximizing the throughput of successive frames, for example when
* processing successive frames coming from the camera.
*/
SUSTAINED_SPEED = 2,
DEFAULT = FAST_SINGLE_ANSWER,
};
/**
* Device types.
*
* The type of NNAPI device.
*/
enum class DeviceType {
/** The device type cannot be provided. */
UNKNOWN = 0,
/** The device does not fall into any category below. */
OTHER = 1,
/** The device runs NNAPI models on single or multi-core CPU. */
CPU = 2,
/** The device can run NNAPI models and also accelerate graphics APIs such
* as OpenGL ES and Vulkan. */
GPU = 3,
/** Dedicated accelerator for Machine Learning workloads. */
ACCELERATOR = 4,
};
/**
* Specifies whether or not to measure timing information during execution.
*/
enum class MeasureTiming {
NO = 0,
YES = 1,
};
/**
* Priority given to a prepared model for execution.
*/
enum class Priority {
LOW = 0,
MEDIUM = 1,
HIGH = 2,
DEFAULT = MEDIUM,
};
// TODO: Should more errors from NeuralNetworks.h be incorporated? The left name shows errors that
// appear in NeuralNetworks.h but not in the HAL, and the right column shows what these values could
// map to:
// * OUT_OF_MEMORY ==> GENERAL_FAILURE / RESOURCE_EXHAUSTED_*
// * INCOMPLETE ==> GENERAL_FAILURE
// * UNEXPECTED_NULL ==> INVALID_ARGUMENT
// * UNMAPPABLE ==> GENERAL_FAILURE
// * BAD_STATE ==> INVALID_ARGUMENT
enum class ErrorStatus {
NONE = 0,
DEVICE_UNAVAILABLE = 1,
GENERAL_FAILURE = 2,
OUTPUT_INSUFFICIENT_SIZE = 3,
INVALID_ARGUMENT = 4,
MISSED_DEADLINE_TRANSIENT = 5,
MISSED_DEADLINE_PERSISTENT = 6,
RESOURCE_EXHAUSTED_TRANSIENT = 7,
RESOURCE_EXHAUSTED_PERSISTENT = 8,
DEAD_OBJECT = 10000,
};
struct GeneralError {
std::string message;
ErrorStatus code = ErrorStatus::GENERAL_FAILURE;
};
template <typename Type>
using GeneralResult = base::expected<Type, GeneralError>;
/**
* Fused activation function types.
*/
enum class FusedActivationFunc : int32_t {
/** NO fused activation function. */
NONE = 0,
/** Fused ReLU activation function. */
RELU = 1,
/** Fused ReLU1 activation function. */
RELU1 = 2,
/** Fused ReLU6 activation function. */
RELU6 = 3,
};
using Dimension = uint32_t;
using Dimensions = std::vector<Dimension>;
using CacheToken = std::array<uint8_t, kByteSizeOfCacheToken>;
/**
* Describes the shape information of an output operand after execution.
*/
struct OutputShape {
/**
* Dimensions of the operand.
*/
std::vector<uint32_t> dimensions;
/**
* Whether the provided buffer size is sufficient for the output.
*/
bool isSufficient = false;
};
struct ExecutionError {
std::string message;
ErrorStatus code = ErrorStatus::GENERAL_FAILURE;
// OutputShapes for code == OUTPUT_INSUFFICIENT_SIZE
std::vector<OutputShape> outputShapes = {};
};
template <typename Type>
using ExecutionResult = base::expected<Type, ExecutionError>;
/**
* The capabilities of a driver.
*
* This represents performance of non-extension operations.
*
* Performance of an operation other than {@link OperationType::IF} and
* {@link OperationType::WHILE} comes from the type of its first operand.
*/
struct Capabilities {
/**
* Performance information for the reference workload.
*
* Used by a driver to report its performance characteristics.
*/
struct PerformanceInfo {
/**
* Ratio of the time taken by the driver to execute the
* workload compared to the time the CPU would take for the
* same workload. A lower number is better.
*/
float execTime = kDefaultExecTime;
/**
* Ratio of the energy used by the driver compared to what
* the CPU would use for doing the same workload. A lower number
* is better.
*/
float powerUsage = kDefaultPowerUsage;
};
/**
* Driver performance when operating on a particular data type.
* In the case of float32 data, this is used when the calculations
* are not relaxed.
*/
struct OperandPerformance {
OperandType type{};
PerformanceInfo info;
};
class OperandPerformanceTable {
public:
static Result<OperandPerformanceTable> create(
std::vector<OperandPerformance> operandPerformances);
PerformanceInfo lookup(OperandType type) const;
const std::vector<OperandPerformance>& asVector() const;
private:
explicit OperandPerformanceTable(std::vector<OperandPerformance> operandPerformances);
std::vector<OperandPerformance> mSorted;
};
/**
* Driver performance when operating on float32 data but performing
* calculations with range and/or precision as low as that of the IEEE
* 754 16-bit floating-point format.
*/
PerformanceInfo relaxedFloat32toFloat16PerformanceScalar;
PerformanceInfo relaxedFloat32toFloat16PerformanceTensor;
/**
* Performance by operand type. Must be sorted by OperandType.
*
* If a particular {@link OperandType} is not present in operandPerformance,
* its performance is treated as
* { .execTime = FLT_MAX, .powerUsage = FLT_MAX }.
*
* Performance does not apply to {@link OperandType::SUBGRAPH}, and a driver
* must not report operand performance for {@link OperandType::SUBGRAPH}.
*/
OperandPerformanceTable operandPerformance;
/**
* Performance of an {@link OperationType::IF} operation is the sum of
* {@link Capabilities::ifPerformance} and the mean of performance for the
* two branch subgraphs, where performance for a subgraph is the sum of the
* performance of all operations within the subgraph.
*/
PerformanceInfo ifPerformance;
/**
* Performance of a {@link OperationType::WHILE} operation is the sum of
* {@link Capabilities::whilePerformance}, performance for the condition
* subgraph and performance for the body subgraph, where performance for a
* subgraph is the sum of the performance of all operations within the
* subgraph.
*/
PerformanceInfo whilePerformance;
};
/**
* Information about an extension.
*/
struct Extension {
/**
* Information about an extension operand type.
*/
struct OperandTypeInformation {
/**
* The extension operand type.
*/
uint16_t type = 0;
/**
* Indicates whether the extension operand type represents a tensor or
* a scalar.
*/
bool isTensor = false;
/**
* The byte size of the operand (if scalar) or of a single element (if
* tensor).
*/
uint32_t byteSize = 0;
};
/**
* The extension name.
*
* The name must consist of lowercase latin letters, numbers, periods, and
* underscore signs. The name must contain at least one period.
*
* The name must start with the reverse domain name of the vendor.
*
* Example: com.google.test_extension
*/
std::string name;
/**
* Information about operand types defined by the extension.
*/
std::vector<OperandTypeInformation> operandTypes;
};
/**
* Describes one operation of the model's graph.
*/
struct Operation {
/**
* The operation type.
*/
OperationType type{};
/**
* Describes the table that contains the indexes of the inputs of the
* operation. The offset is the index in the operandIndexes table.
*/
std::vector<uint32_t> inputs;
/**
* Describes the table that contains the indexes of the outputs of the
* operation. The offset is the index in the operandIndexes table.
*/
std::vector<uint32_t> outputs;
};
/**
* Describes the location of a data object.
*/
struct DataLocation {
/**
* The address of the memory where the data is found.
*
* This field is only active when lifetime is POINTER.
*/
std::variant<const void*, void*> pointer;
/**
* The index of the memory pool where this location is found.
*/
uint32_t poolIndex = 0;
/**
* Offset in bytes from the start of the pool.
*/
uint32_t offset = 0;
/**
* The length of the data in bytes.
*/
uint32_t length = 0;
/**
* The end padding of the specified memory region in bytes.
*/
uint32_t padding = 0;
};
/**
* Describes one operand of the model's graph.
*/
struct Operand {
/**
* How an operand is used.
*/
enum class LifeTime {
/**
* The operand is internal to the model. It's created by an operation and
* consumed by other operations. It must be an output operand of
* exactly one operation.
*/
TEMPORARY_VARIABLE = 0,
/**
* The operand is an input of a subgraph. It must not be an output
* operand of any operation.
*
* An operand can't be both input and output of a subgraph.
*/
SUBGRAPH_INPUT = 1,
/**
* The operand is an output of a subgraph. It must be an output
* operand of exactly one operation.
*
* An operand can't be both input and output of a subgraph.
*/
SUBGRAPH_OUTPUT = 2,
/**
* The operand is a constant found in Model::operandValues. It must
* not be an output operand of any operation.
*/
CONSTANT_COPY = 3,
/**
* The operand is a constant that was specified via a Memory
* object. It must not be an output operand of any operation.
*/
CONSTANT_REFERENCE = 4,
/**
* The operand does not have a value. This is valid only for optional
* arguments of operations.
*/
NO_VALUE = 5,
/**
* The operand is a reference to a subgraph. It must be an input to one
* or more {@link OperationType::IF} or {@link OperationType::WHILE}
* operations.
*/
SUBGRAPH = 6,
/**
* This operand is a constant found in a user buffer. It must not be an
* output operand of any operation.
*/
POINTER = 7,
};
/**
* No additional parameters.
*/
using NoParams = std::monostate;
/**
* Parameters for TENSOR_QUANT8_SYMM_PER_CHANNEL operand.
*/
struct SymmPerChannelQuantParams {
/** Array of scaling values for each channel. Each value must be greater than zero. */
std::vector<float> scales;
/** Index of the channel dimension */
uint32_t channelDim = 0;
};
/**
* Extension operand parameters.
*
* The framework treats this as an opaque data blob.
* The format is up to individual extensions.
*/
using ExtensionParams = std::vector<uint8_t>;
/**
* Additional parameters specific to a particular operand type.
*/
using ExtraParams = std::variant<NoParams, SymmPerChannelQuantParams, ExtensionParams>;
/**
* The data type.
*
* Besides the values listed in {@link OperationType}, any value equal or over
* (1 << kExtensionTypeBits) is possible and should be interpreted
* as an extension type according to {@link Model::extensionNameToPrefix}.
*/
OperandType type{};
/**
* Dimensions of the operand.
*
* For a scalar operand, dimensions.size() must be 0.
*
* A tensor operand with all dimensions specified has "fully
* specified" dimensions. Whenever possible (i.e., whenever the
* dimensions are known at model construction time), a tensor
* operand should have (but is not required to have) fully
* specified dimensions, in order to enable the best possible
* performance.
*
* If a tensor operand's dimensions are not fully specified, the
* dimensions of the operand are deduced from the operand
* dimensions and values of the operation for which that operand
* is an output or from the corresponding {@link OperationType::IF} or
* {@link OperationType::WHILE} operation input operand dimensions in the
* case of referenced subgraph input operands.
*
* In the following situations, a tensor operand's dimensions must
* be fully specified:
*
* - The operand has lifetime CONSTANT_COPY, CONSTANT_REFERENCE, or
* POINTER.
*
* - The operand has lifetime SUBGRAPH_INPUT and belongs to the main
* subgraph. Fully specified dimensions must either be present in the
* Operand or they must be provided in the corresponding
* RequestArgument.
* EXCEPTION: If the input is optional and omitted
* (by setting the hasNoValue field of the corresponding
* RequestArgument to true) then it need not have fully
* specified dimensions.
*
* A tensor operand with some number of unspecified dimensions is
* represented by setting each unspecified dimension to 0.
*
* A tensor operand with unspecified rank is represented by providing
* an empty dimensions vector.
*/
Dimensions dimensions;
/**
* Quantized scale of the operand.
*
* Must be 0 when not applicable to an operand type.
*
* See {@link OperandType}.
*/
float scale = 0.0f;
/**
* Quantized zero-point offset of the operand.
*
* Must be 0 when not applicable to an operand type.
*
* See {@link OperandType}.
*/
int32_t zeroPoint = 0;
/**
* How the operand is used.
*/
LifeTime lifetime{};
/**
* Where to find the data for this operand.
* If the lifetime is TEMPORARY_VARIABLE, SUBGRAPH_INPUT, SUBGRAPH_OUTPUT,
* or NO_VALUE:
* - All the fields must be 0.
* If the lifetime is CONSTANT_COPY:
* - location.pointer is null.
* - location.poolIndex is 0.
* - location.offset is the offset in bytes into Model::operandValues.
* - location.length is set.
* - location.padding is 0.
* If the lifetime is CONSTANT_REFERENCE:
* - location.pointer is null.
* - location.poolIndex is set.
* - location.offset is the offset in bytes into the specified pool.
* - location.length is set.
* - location.padding is set.
* If the lifetime is SUBGRAPH:
* - location.pointer is null.
* - location.poolIndex is 0.
* - location.offset is the index of the referenced subgraph in
* {@link Model::referenced}.
* - location.length is 0.
* - location.padding is 0.
* If the lifetime is POINTER:
* - location.pointer is non-null.
* - location.poolIndex is 0.
* - location.offset is 0.
* - location.length is set.
* - location.padding is 0.
*/
DataLocation location;
/**
* Additional parameters specific to a particular operand type.
*/
ExtraParams extraParams;
};
struct Handle {
std::vector<base::unique_fd> fds;
std::vector<int> ints;
};
using SharedHandle = std::shared_ptr<const Handle>;
struct Memory {
struct Ashmem {
base::unique_fd fd;
size_t size;
};
struct Fd {
size_t size;
int prot;
base::unique_fd fd;
size_t offset;
};
// RAII wrapper for AHardwareBuffer
struct HardwareBuffer {
using Deleter = std::add_pointer_t<void(AHardwareBuffer*)>;
using Handle = std::unique_ptr<AHardwareBuffer, Deleter>;
Handle handle;
};
struct Unknown {
Handle handle;
size_t size;
std::string name;
};
std::variant<Ashmem, Fd, HardwareBuffer, Unknown> handle;
};
/**
* A Neural Network Model.
*
* This includes not only the execution graph, but also constant data such as
* weights or scalars added at construction time. The only information that
* may not be known is the shape of the input tensors.
*/
struct Model {
/**
* An excerpt of the execution graph.
*/
struct Subgraph {
/**
* All operands included in the subgraph.
*/
std::vector<Operand> operands;
/**
* All operations included in the subgraph.
*
* The operations are sorted into execution order. Every operand
* with lifetime SUBGRAPH_OUTPUT or TEMPORARY_VARIABLE must be
* written before it is read.
*/
std::vector<Operation> operations;
/**
* Input indexes of the subgraph. There must be at least one.
*
* Each value corresponds to the index of the operand in "operands".
*/
std::vector<uint32_t> inputIndexes;
/**
* Output indexes of the subgraph. There must be at least one.
*
* Each value corresponds to the index of the operand in "operands".
*/
std::vector<uint32_t> outputIndexes;
};
class OperandValues {
public:
OperandValues();
OperandValues(const uint8_t* data, size_t length);
// Append a segment of memory (starting at `data` with `length` number of bytes) to the back
// of `OperandValues`, adding padding as necessary so that the appended data is aligned.
// Refer to `getAlignmentForLength` for more information on alignment (such as what the
// current alignments are for different data lengths).
DataLocation append(const uint8_t* data, size_t length);
const uint8_t* data() const;
size_t size() const;
private:
std::vector<uint8_t> mData;
};
/**
* A correspondence between an extension name and a prefix of operand and
* operation type values.
*/
struct ExtensionNameAndPrefix {
/**
* The extension name.
*
* See {@link Extension::name} for the format specification.
*/
std::string name;
/**
* The unique extension identifier within the model.
*
* See {@link Model::extensionNameToPrefix}.
*/
uint16_t prefix = 0;
};
/**
* The top-level subgraph.
*/
Subgraph main;
/**
* Referenced subgraphs.
*
* Each subgraph is referenced by the main subgraph or at least one other
* referenced subgraph.
*
* There must be no reference cycles.
*/
std::vector<Subgraph> referenced;
/**
* A byte buffer containing operand data that were copied into the model.
*
* An operand's value must be located here if and only if Operand::lifetime
* equals Operand::LifeTime::CONSTANT_COPY.
*/
OperandValues operandValues;
/**
* A collection of shared memory pools containing operand values.
*
* An operand's value must be located here if and only if Operand::lifetime
* equals Operand::LifeTime::CONSTANT_REFERENCE.
*/
std::vector<SharedMemory> pools;
/**
* 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
* precision as low as that of the IEEE 754 16-bit floating-point format.
* 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
* range and precision of the IEEE 754 32-bit floating-point format.
*/
bool relaxComputationFloat32toFloat16 = false;
/**
* The mapping between extension names and prefixes of operand and
* operation type values.
*
* An operand or operation whose numeric type value is equal to or greater
* than (1 << kExtensionTypeBits) should be interpreted
* as an extension operand. The low
* {@link kExtensionTypeBits} bits of the value correspond to the type ID
* within the extension and the high {@link kExtensionPrefixBits} bits encode
* the "prefix", which maps uniquely to the extension name.
*
* For example, if a model contains an operation whose value is
* 0xAAAABBBB and extensionNameToPrefix contains an entry with
* prefix=0xAAAA and name="vendor.test.test_extension", then
* the operation should be interpreted as the operation 0xBBBB
* of the extension named vendor.test.test_extension.
*
* This is a one-to-one correspondence. That is, there must be at most one
* prefix corresponding to each extension name and at most one extension
* name corresponding to each prefix.
*/
std::vector<ExtensionNameAndPrefix> extensionNameToPrefix;
};
/**
* A buffer descriptor. Describes the properties of a buffer.
*/
struct BufferDesc {
/**
* Dimensions of the buffer. May have unknown dimensions or rank. A buffer with some number
* of unspecified dimensions is represented by setting each unspecified dimension to 0. A
* buffer with unspecified rank is represented by providing an empty dimensions vector.
*/
Dimensions dimensions;
};
/**
* Describes a role of an input or output to a prepared model.
*/
struct BufferRole {
/**
* The index of the IPreparedModel within the "preparedModel" argument passed in
* IDevice::allocate.
*/
uint32_t modelIndex = 0;
/**
* The index of the input or output operand.
*/
uint32_t ioIndex = 0;
/**
* A floating-point value within the range (0.0, 1.0]. Describes how likely the
* buffer is to be used in the specified role. This is provided as a hint to
* optimize the case when multiple roles prefer different buffer locations or data
* layouts.
*/
float probability = 0.0f;
};
/**
* Inputs to be sent to and outputs to be retrieved from a prepared model.
*
* A Request serves two primary tasks:
* 1) Provides the input and output data to be used when executing the model.
* 2) Specifies any updates to the input operand metadata that were left
* unspecified at model preparation time.
*
* An output must not overlap with any other output, with an input, or
* with an operand of lifetime CONSTANT_REFERENCE.
*/
struct Request {
/**
* Metadata information specifying the location of the input or output data and
* any updates to the input or output operand.
*/
struct Argument {
enum class LifeTime {
POOL = 0,
NO_VALUE = 1,
POINTER = 2,
};
LifeTime lifetime{};
/**
* The location within one of the memory pools passed in the Request.
*/
DataLocation location;
/**
* Updated dimension information.
*
* If dimensions.size() > 0, dimension information was provided
* along with the argument. This can be the case for models that
* accept inputs of varying size. This can't change the rank, just
* the value of the dimensions that were unspecified in the
* model. If dimensions.size() > 0, then all dimensions must be
* specified here; and any dimension that was specified in the
* model must have the same value here.
*
* If the dimensions in the model are not fully specified, then
* they must be fully specified here, unless hasNoValue is set to
* true. If the dimensions in the model are fully specified, then
* either dimensions.size() may be 0, or the dimensions in the
* model must be identical to the dimensions here.
*/
Dimensions dimensions;
};
/**
* Specifies a driver-managed buffer. It is the token corresponding to an
* IBuffer returned from IDevice::allocate, and is specific to the IDevice
* object.
*/
enum class MemoryDomainToken : uint32_t {};
/**
* A memory pool.
*/
using MemoryPool = std::variant<SharedMemory, MemoryDomainToken, SharedBuffer>;
/**
* Input data and information to be used in the execution of a prepared
* model.
*
* The index of the input corresponds to the index in Model::main::inputIndexes.
* E.g., inputs[i] corresponds to Model::main::inputIndexes[i].
*/
std::vector<Argument> inputs;
/**
* Output data and information to be used in the execution of a prepared
* model.
*
* The index of the output corresponds to the index in Model::main::outputIndexes.
* E.g., outputs[i] corresponds to Model::main::outputIndexes[i].
*/
std::vector<Argument> outputs;
/**
* A collection of memory pools containing operand data for both the
* inputs and the outputs to a model.
*/
std::vector<MemoryPool> pools;
};
// Representation of sync_fence.
class SyncFence {
public:
static SyncFence createAsSignaled();
static SyncFence create(base::unique_fd fd);
static Result<SyncFence> create(SharedHandle syncFence);
// The function syncWait() has the same semantics as the system function
// ::sync_wait(), except that the syncWait() return value is semantically
// richer.
enum class FenceState {
ACTIVE, // fence has not been signaled
SIGNALED, // fence has been signaled
ERROR, // fence has been placed in the error state
UNKNOWN, // either bad argument passed to syncWait(), or internal error
};
using Timeout = std::chrono::duration<int, std::milli>;
using OptionalTimeout = std::optional<Timeout>;
FenceState syncWait(OptionalTimeout optionalTimeout) const;
SharedHandle getSharedHandle() const;
bool hasFd() const;
int getFd() const;
private:
explicit SyncFence(SharedHandle syncFence);
SharedHandle mSyncFence;
};
using Clock = base::boot_clock;
using Duration = std::chrono::nanoseconds;
using OptionalDuration = std::optional<Duration>;
using TimePoint = std::chrono::time_point<Clock, Duration>;
using OptionalTimePoint = std::optional<TimePoint>;
/**
* Timing information measured during execution. Each time is a duration from
* the beginning of some task to the end of that task, including time when that
* task is not active (for example, preempted by some other task, or
* waiting for some resource to become available).
*
* Times are measured in nanoseconds.
*/
struct Timing {
/** Execution time on device (not driver, which runs on host processor). */
OptionalDuration timeOnDevice;
/** Execution time in driver (including time on device). */
OptionalDuration timeInDriver;
};
// Returns status, timingLaunched, timingFenced
using ExecuteFencedInfoCallback = std::function<GeneralResult<std::pair<Timing, Timing>>()>;
enum class Version { ANDROID_OC_MR1, ANDROID_P, ANDROID_Q, ANDROID_R, ANDROID_S, CURRENT_RUNTIME };
// Describes the memory preference of an operand.
struct MemoryPreference {
// Must be a power of 2.
// For pointer buffers, the alignment is satisfied if the address of the pointer is a multiple
// of the "alignment" value. For memory pools, the alignment is satisfied if the offset of the
// sub-region specified by DataLocation is a multiple of the "alignment" value.
uint32_t alignment;
// Must be a power of 2.
// For both pointer buffers and memory pools, the padding is satisfied if the padded length is
// greater than or equal to the raw size of the operand (i.e. the size of an element multiplied
// by the number of elements) rounding up to a multiple of the "padding" value. In DataLocation,
// the padded length equals to the sum of the length and padding fields.
uint32_t padding;
};
} // namespace android::nn
#endif // ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_TYPES_H