diff options
author | android-build-prod (mdb) <android-build-team-robot@google.com> | 2020-09-24 00:01:39 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-09-24 00:01:39 +0000 |
commit | 435500ac9c9dcc01a298e329d6a527d3d18a0790 (patch) | |
tree | e96ba1bdf1adeccc9f3513555d33f8787fa36067 | |
parent | 1dac19fba40aa3aa30f58f0282262219eee1b2fb (diff) | |
parent | ae88e9212933a2eb34b336f37307775fced0973e (diff) | |
download | ml-simpleperf-release.tar.gz |
Merge "Snap for 6859336 from f3a14c00046f3497f8a573794974dc2a5be6f35c to simpleperf-release" into simpleperf-releasesimpleperf-release
-rw-r--r-- | nn/apex/manifest.json | 2 | ||||
-rw-r--r-- | nn/common/Android.bp | 31 | ||||
-rw-r--r-- | nn/common/Types.cpp | 124 | ||||
-rw-r--r-- | nn/common/include/nnapi/OperandTypes.h | 45 | ||||
-rw-r--r-- | nn/common/include/nnapi/OperationTypes.h | 130 | ||||
-rw-r--r-- | nn/common/include/nnapi/Types.h | 297 |
6 files changed, 628 insertions, 1 deletions
diff --git a/nn/apex/manifest.json b/nn/apex/manifest.json index 963ef8717..570b57d9f 100644 --- a/nn/apex/manifest.json +++ b/nn/apex/manifest.json @@ -1,4 +1,4 @@ { "name": "com.android.neuralnetworks", - "version": 300000000 + "version": 300900700 } diff --git a/nn/common/Android.bp b/nn/common/Android.bp index c484fd15f..65d993247 100644 --- a/nn/common/Android.bp +++ b/nn/common/Android.bp @@ -229,6 +229,37 @@ cc_library_static { } cc_defaults { + name: "neuralnetworks_utils_defaults", + host_supported: true, + vendor_available: true, + cflags: [ + "-Wall", + "-Werror", + "-Wextra", + ], +} + +cc_library_static { + name: "neuralnetworks_types", + defaults: ["neuralnetworks_utils_defaults"], + srcs: [ + "Types.cpp", + ], + local_include_dirs: ["include/nnapi"], + export_include_dirs: ["include"], + shared_libs: [ + "libbase", + "libcutils", + "libutils", + ], + export_shared_lib_headers: [ + "libbase", + "libcutils", + "libutils", + ], +} + +cc_defaults { name: "NeuralNetworksTest_common", defaults: ["neuralnetworks_float16"], shared_libs: [ diff --git a/nn/common/Types.cpp b/nn/common/Types.cpp new file mode 100644 index 000000000..a49a8dc35 --- /dev/null +++ b/nn/common/Types.cpp @@ -0,0 +1,124 @@ +/* + * 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. + */ + +#include "Types.h" + +#include <android-base/logging.h> + +#include <algorithm> +#include <cstddef> +#include <iterator> +#include <limits> +#include <optional> +#include <utility> +#include <vector> + +#include "OperandTypes.h" +#include "OperationTypes.h" + +namespace android::nn { +namespace { + +constexpr size_t safeDivideRoundedUp(size_t numerator, size_t denominator) { + CHECK_NE(denominator, 0u); + CHECK_LE(numerator, std::numeric_limits<size_t>::max() - denominator); + return (numerator + denominator - 1) / denominator; +} + +constexpr size_t safeMultiply(size_t a, size_t b) { + if (b == 0) { + return 0; + } + CHECK_LE(a, std::numeric_limits<size_t>::max() / b); + return a * b; +} + +std::vector<AlignedData> allocateAligned(const uint8_t* data, size_t length) { + constexpr size_t kElementSize = sizeof(AlignedData); + const size_t numberElements = safeDivideRoundedUp(length, kElementSize); + std::vector<AlignedData> output(numberElements); + std::memcpy(output.data(), data, length); + return output; +} + +} // anonymous namespace + +Model::OperandValues::OperandValues() { + constexpr size_t kNumberBytes = 4 * 1024; + constexpr size_t kElementSize = sizeof(AlignedData); + constexpr size_t kNumberElements = safeDivideRoundedUp(kNumberBytes, kElementSize); + mData.reserve(kNumberElements); +} + +Model::OperandValues::OperandValues(const uint8_t* data, size_t length) + : mData(allocateAligned(data, length)) {} + +DataLocation Model::OperandValues::append(const uint8_t* data, size_t length) { + const size_t offset = size(); + auto contents = allocateAligned(data, length); + mData.insert(mData.end(), contents.begin(), contents.end()); + CHECK_LE(offset, std::numeric_limits<uint32_t>::max()); + CHECK_LE(length, std::numeric_limits<uint32_t>::max()); + return {.offset = static_cast<uint32_t>(offset), .length = static_cast<uint32_t>(length)}; +} + +const uint8_t* Model::OperandValues::data() const { + return reinterpret_cast<const uint8_t*>(mData.data()); +} + +size_t Model::OperandValues::size() const { + return safeMultiply(mData.size(), sizeof(AlignedData)); +} + +Capabilities::OperandPerformanceTable::OperandPerformanceTable( + std::vector<OperandPerformance> operandPerformances) + : mSorted(std::move(operandPerformances)) {} + +std::optional<Capabilities::OperandPerformanceTable> Capabilities::OperandPerformanceTable::create( + std::vector<OperandPerformance> operandPerformances) { + const auto notUnique = [](const auto& lhs, const auto& rhs) { return !(lhs.type < rhs.type); }; + const bool isUnique = std::adjacent_find(operandPerformances.begin(), operandPerformances.end(), + notUnique) == operandPerformances.end(); + if (!isUnique) { + LOG(ERROR) << "Failed to create OperandPerformanceTable: Input must be sorted by key (in " + "ascending order), and there must be no duplicate keys"; + return std::nullopt; + } + + return Capabilities::OperandPerformanceTable(std::move(operandPerformances)); +} + +Capabilities::PerformanceInfo Capabilities::OperandPerformanceTable::lookup( + OperandType operandType) const { + // Search for operand type in the sorted collection. + constexpr auto cmp = [](const auto& performance, auto type) { return performance.type < type; }; + const auto it = std::lower_bound(mSorted.begin(), mSorted.end(), operandType, cmp); + + // If the operand type is found, return its corresponding info. + if (it != mSorted.end() && it->type == operandType) { + return it->info; + } + + // If no performance info is defined, use the default value (float's max). + return Capabilities::PerformanceInfo{}; +} + +const std::vector<Capabilities::OperandPerformance>& +Capabilities::OperandPerformanceTable::asVector() const { + return mSorted; +} + +} // namespace android::nn diff --git a/nn/common/include/nnapi/OperandTypes.h b/nn/common/include/nnapi/OperandTypes.h new file mode 100644 index 000000000..641ffb658 --- /dev/null +++ b/nn/common/include/nnapi/OperandTypes.h @@ -0,0 +1,45 @@ +/* + * 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_OPERAND_TYPES_H +#define ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_OPERAND_TYPES_H + +namespace android::nn { + +enum class OperandType { + FLOAT32 = 0, + INT32 = 1, + UINT32 = 2, + TENSOR_FLOAT32 = 3, + TENSOR_INT32 = 4, + TENSOR_QUANT8_ASYMM = 5, + BOOL = 6, + TENSOR_QUANT16_SYMM = 7, + TENSOR_FLOAT16 = 8, + TENSOR_BOOL8 = 9, + FLOAT16 = 10, + TENSOR_QUANT8_SYMM_PER_CHANNEL = 11, + TENSOR_QUANT16_ASYMM = 12, + TENSOR_QUANT8_SYMM = 13, + TENSOR_QUANT8_ASYMM_SIGNED = 14, + SUBGRAPH = 15, + OEM = 10000, + TENSOR_OEM_BYTE = 10001, +}; + +} // namespace android::nn + +#endif // ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_OPERAND_TYPES_H diff --git a/nn/common/include/nnapi/OperationTypes.h b/nn/common/include/nnapi/OperationTypes.h new file mode 100644 index 000000000..5d8c59405 --- /dev/null +++ b/nn/common/include/nnapi/OperationTypes.h @@ -0,0 +1,130 @@ +/* + * 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_OPERATION_TYPES_H +#define ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_OPERATION_TYPES_H + +namespace android::nn { + +enum class OperationType { + ADD = 0, + AVERAGE_POOL_2D = 1, + CONCATENATION = 2, + CONV_2D = 3, + DEPTHWISE_CONV_2D = 4, + DEPTH_TO_SPACE = 5, + DEQUANTIZE = 6, + EMBEDDING_LOOKUP = 7, + FLOOR = 8, + FULLY_CONNECTED = 9, + HASHTABLE_LOOKUP = 10, + L2_NORMALIZATION = 11, + L2_POOL_2D = 12, + LOCAL_RESPONSE_NORMALIZATION = 13, + LOGISTIC = 14, + LSH_PROJECTION = 15, + LSTM = 16, + MAX_POOL_2D = 17, + MUL = 18, + RELU = 19, + RELU1 = 20, + RELU6 = 21, + RESHAPE = 22, + RESIZE_BILINEAR = 23, + RNN = 24, + SOFTMAX = 25, + SPACE_TO_DEPTH = 26, + SVDF = 27, + TANH = 28, + BATCH_TO_SPACE_ND = 29, + DIV = 30, + MEAN = 31, + PAD = 32, + SPACE_TO_BATCH_ND = 33, + SQUEEZE = 34, + STRIDED_SLICE = 35, + SUB = 36, + TRANSPOSE = 37, + ABS = 38, + ARGMAX = 39, + ARGMIN = 40, + AXIS_ALIGNED_BBOX_TRANSFORM = 41, + BIDIRECTIONAL_SEQUENCE_LSTM = 42, + BIDIRECTIONAL_SEQUENCE_RNN = 43, + BOX_WITH_NMS_LIMIT = 44, + CAST = 45, + CHANNEL_SHUFFLE = 46, + DETECTION_POSTPROCESSING = 47, + EQUAL = 48, + EXP = 49, + EXPAND_DIMS = 50, + GATHER = 51, + GENERATE_PROPOSALS = 52, + GREATER = 53, + GREATER_EQUAL = 54, + GROUPED_CONV_2D = 55, + HEATMAP_MAX_KEYPOINT = 56, + INSTANCE_NORMALIZATION = 57, + LESS = 58, + LESS_EQUAL = 59, + LOG = 60, + LOGICAL_AND = 61, + LOGICAL_NOT = 62, + LOGICAL_OR = 63, + LOG_SOFTMAX = 64, + MAXIMUM = 65, + MINIMUM = 66, + NEG = 67, + NOT_EQUAL = 68, + PAD_V2 = 69, + POW = 70, + PRELU = 71, + QUANTIZE = 72, + QUANTIZED_16BIT_LSTM = 73, + RANDOM_MULTINOMIAL = 74, + REDUCE_ALL = 75, + REDUCE_ANY = 76, + REDUCE_MAX = 77, + REDUCE_MIN = 78, + REDUCE_PROD = 79, + REDUCE_SUM = 80, + ROI_ALIGN = 81, + ROI_POOLING = 82, + RSQRT = 83, + SELECT = 84, + SIN = 85, + SLICE = 86, + SPLIT = 87, + SQRT = 88, + TILE = 89, + TOPK_V2 = 90, + TRANSPOSE_CONV_2D = 91, + UNIDIRECTIONAL_SEQUENCE_LSTM = 92, + UNIDIRECTIONAL_SEQUENCE_RNN = 93, + RESIZE_NEAREST_NEIGHBOR = 94, + QUANTIZED_LSTM = 95, + IF = 96, + WHILE = 97, + ELU = 98, + HARD_SWISH = 99, + FILL = 100, + RANK = 101, + OEM_OPERATION = 10000, +}; + +} // namespace android::nn + +#endif // ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_OPERATION_TYPES_H diff --git a/nn/common/include/nnapi/Types.h b/nn/common/include/nnapi/Types.h new file mode 100644 index 000000000..0536a2e2b --- /dev/null +++ b/nn/common/include/nnapi/Types.h @@ -0,0 +1,297 @@ +/* + * 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 <utils/NativeHandle.h> +#include <utils/StrongPointer.h> + +#include <array> +#include <chrono> +#include <limits> +#include <memory> +#include <optional> +#include <string> +#include <type_traits> +#include <variant> +#include <vector> + +#include "nnapi/OperandTypes.h" +#include "nnapi/OperationTypes.h" + +namespace android::nn { + +// Forward declarations + +class IBuffer; +class IDevice; +class IPreparedModel; + +// Default values + +constexpr uint64_t kNoTiming = std::numeric_limits<uint64_t>::max(); +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; +constexpr uint8_t kExtensionTypeBits = 16; +constexpr uint8_t kExtensionPrefixBits = 16; + +// Aliases + +using AlignedData = std::max_align_t; +using SharedBuffer = std::shared_ptr<const IBuffer>; +using SharedDevice = std::shared_ptr<const IDevice>; +using PreparedModel = std::shared_ptr<const IPreparedModel>; + +// Canonical types + +enum class DeviceStatus { + AVAILABLE = 0, + BUSY = 1, + OFFLINE = 2, + UNKNOWN = 3, +}; + +enum class ExecutionPreference { + LOW_POWER = 0, + FAST_SINGLE_ANSWER = 1, + SUSTAINED_SPEED = 2, + DEFAULT = FAST_SINGLE_ANSWER, +}; + +enum class DeviceType { + UNKNOWN = 0, + OTHER = 1, + CPU = 2, + GPU = 3, + ACCELERATOR = 4, +}; + +enum class MeasureTiming { + NO = 0, + YES = 1, +}; + +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, +}; + +using Dimension = uint32_t; +using Dimensions = std::vector<Dimension>; + +using CacheToken = std::array<uint8_t, kByteSizeOfCacheToken>; + +struct OutputShape { + std::vector<uint32_t> dimensions; + bool isSufficient = false; +}; + +struct Timing { + uint64_t timeOnDevice = kNoTiming; + uint64_t timeInDriver = kNoTiming; +}; + +struct Capabilities { + struct PerformanceInfo { + float execTime = kDefaultExecTime; + float powerUsage = kDefaultPowerUsage; + }; + struct OperandPerformance { + OperandType type{}; + PerformanceInfo info; + }; + class OperandPerformanceTable { + public: + static std::optional<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; + }; + + PerformanceInfo relaxedFloat32toFloat16PerformanceScalar; + PerformanceInfo relaxedFloat32toFloat16PerformanceTensor; + OperandPerformanceTable operandPerformance; + PerformanceInfo ifPerformance; + PerformanceInfo whilePerformance; +}; + +struct Extension { + struct OperandTypeInformation { + uint16_t type = 0; + bool isTensor = false; + uint32_t byteSize = 0; + }; + + std::string name; + std::vector<OperandTypeInformation> operandTypes; +}; + +struct Operation { + OperationType type{}; + std::vector<uint32_t> inputs; + std::vector<uint32_t> outputs; +}; + +struct DataLocation { + std::variant<const void*, void*> pointer; + uint32_t poolIndex = 0; + uint32_t offset = 0; + uint32_t length = 0; +}; + +struct Operand { + enum class LifeTime { + TEMPORARY_VARIABLE = 0, + SUBGRAPH_INPUT = 1, + SUBGRAPH_OUTPUT = 2, + CONSTANT_COPY = 3, + CONSTANT_REFERENCE = 4, + NO_VALUE = 5, + SUBGRAPH = 6, + POINTER = 7, + }; + using NoParams = std::monostate; + struct SymmPerChannelQuantParams { + std::vector<float> scales; + uint32_t channelDim = 0; + }; + using ExtensionParams = std::vector<uint8_t>; + using ExtraParams = std::variant<NoParams, SymmPerChannelQuantParams, ExtensionParams>; + + OperandType type{}; + Dimensions dimensions; + float scale = 0.0f; + int32_t zeroPoint = 0; + LifeTime lifetime{}; + DataLocation location; + ExtraParams extraParams; +}; + +using NativeHandle = ::android::sp<::android::NativeHandle>; + +struct Memory { + NativeHandle handle; + size_t size = 0; + std::string name; +}; + +struct Model { + struct Subgraph { + std::vector<Operand> operands; + std::vector<Operation> operations; + std::vector<uint32_t> inputIndexes; + std::vector<uint32_t> outputIndexes; + }; + class OperandValues { + public: + OperandValues(); + OperandValues(const uint8_t* data, size_t length); + + DataLocation append(const uint8_t* data, size_t length); + + const uint8_t* data() const; + size_t size() const; + + private: + std::vector<AlignedData> mData; + }; + struct ExtensionNameAndPrefix { + std::string name; + uint16_t prefix = 0; + }; + + Subgraph main; + std::vector<Subgraph> referenced; + OperandValues operandValues; + std::vector<Memory> pools; + bool relaxComputationFloat32toFloat16 = false; + std::vector<ExtensionNameAndPrefix> extensionNameToPrefix; +}; + +struct BufferDesc { + Dimensions dimensions; +}; + +struct BufferRole { + uint32_t modelIndex = 0; + uint32_t ioIndex = 0; + float frequency = 0.0f; +}; + +struct Request { + struct Argument { + enum class LifeTime { + POOL = 0, + NO_VALUE = 1, + POINTER = 2, + }; + + LifeTime lifetime{}; + DataLocation location; + Dimensions dimensions; + }; + enum class MemoryDomainToken : uint32_t {}; + using MemoryPool = std::variant<Memory, MemoryDomainToken, SharedBuffer>; + + std::vector<Argument> inputs; + std::vector<Argument> outputs; + std::vector<MemoryPool> pools; +}; + +using Clock = std::chrono::steady_clock; + +using TimePoint = std::chrono::time_point<Clock, std::chrono::nanoseconds>; +using OptionalTimePoint = std::optional<TimePoint>; + +using TimeoutDuration = std::chrono::nanoseconds; +using OptionalTimeoutDuration = std::optional<TimeoutDuration>; + +enum class Version { ANDROID_OC_MR1, ANDROID_P, ANDROID_Q, ANDROID_R, CURRENT_RUNTIME, INVALID }; + +} // namespace android::nn + +#endif // ANDROID_FRAMEWORKS_ML_NN_COMMON_NNAPI_TYPES_H |