ExecutionBuilder.h revision 891b10f7048c62a37a74c4b570be220089dfd55e
1/* 2 * Copyright (C) 2017 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_ML_NN_RUNTIME_EXECUTION_BUILDER_H 18#define ANDROID_ML_NN_RUNTIME_EXECUTION_BUILDER_H 19 20#include "Event.h" 21#include "HalInterfaces.h" 22#include "Memory.h" 23#include "NeuralNetworks.h" 24 25#include <unordered_map> 26#include <vector> 27 28using ::android::hardware::neuralnetworks::V1_0::implementation::Event; 29 30namespace android { 31namespace nn { 32 33class CompilationBuilder; 34class ExecutionPlan; 35class Memory; 36class ModelBuilder; 37class StepExecutor; 38 39// TODO move length out of DataLocation 40struct ModelArgumentInfo { 41 // Whether the arguement was specified as being in a Memory, as a pointer, 42 // or has not been specified. 43 // If POINTER then: 44 // locationAndDimension.location.length is valid. 45 // locationAndDimension.dimension is valid. 46 // buffer is valid 47 // If MEMORY then: 48 // locationAndDimension.location.{poolIndex, offset, length} is valid. 49 // locationAndDimension.dimension is valid. 50 enum { POINTER, MEMORY, UNSPECIFIED } state = UNSPECIFIED; 51 RequestArgument locationAndDimension; 52 void* buffer; 53 54 int setFromPointer(const Operand& operand, const ANeuralNetworksOperandType* type, void* buffer, 55 uint32_t length); 56 int setFromMemory(const Operand& operand, const ANeuralNetworksOperandType* type, 57 uint32_t poolIndex, uint32_t offset, uint32_t length); 58 int updateDimensionInfo(const Operand& operand, const ANeuralNetworksOperandType* newType); 59}; 60 61class ExecutionBuilder { 62 friend class StepExecutor; 63public: 64 ExecutionBuilder(const CompilationBuilder* compilation); 65 66 int setInput(uint32_t index, const ANeuralNetworksOperandType* type, const void* buffer, 67 size_t length); 68 int setInputFromMemory(uint32_t index, const ANeuralNetworksOperandType* type, 69 const Memory* memory, size_t offset, size_t length); 70 int setOutput(uint32_t index, const ANeuralNetworksOperandType* type, void* buffer, 71 size_t length); 72 int setOutputFromMemory(uint32_t index, const ANeuralNetworksOperandType* type, 73 const Memory* memory, size_t offset, size_t length); 74 int startCompute(sp<Event>* event); 75 76private: 77 const ModelBuilder* mModel; 78 [[maybe_unused]] const ExecutionPlan* mPlan; 79 80 // The information we'll send to the driver about the inputs and outputs. 81 // Note that we build this in two steps: 82 // 1. As the arguments are specified, set the corresponding mInputs or mOutputs element. 83 // If set from a pointer, don't set the location in the RequestArgument but store it 84 // instead in mInputBuffers or mOutputBuffers. 85 // 2. Once we have all the inputs and outputs, if needed, allocate shared memory for 86 // the m*Buffers entries. Copy the input values into the shared memory. 87 // We do this to avoid creating a lot of shared memory objects if we have a lot of 88 // parameters specified via pointers. We also avoid copying in the case where 89 // some of the nodes will interpreted on the CPU anyway. 90 std::vector<ModelArgumentInfo> mInputs; 91 std::vector<ModelArgumentInfo> mOutputs; 92 MemoryTracker mMemories; 93}; 94 95// class StepExecutor is used to execute a single "step" in a 96// potentially multiple step execution process. The graph associated 97// with that step is executed in its entirety on a single device (or 98// on the CPU). 99class StepExecutor { 100public: 101 // executionBuilder 102 // Describes the full (possibly multiple-"step") execution. 103 // model 104 // The model to be executed by the executor. Possibly a 105 // submodel of the model from executionBuilder. 106 // driver, preparedModel 107 // The device on which to execute the "step", and the prepared 108 // model to execute on that device. (Both are nullptr in the 109 // case of CPU.) 110 StepExecutor(const ExecutionBuilder* executionBuilder, 111 const ModelBuilder* model, 112 sp<IDevice> driver, sp<IPreparedModel> preparedModel); 113 114 // Map inputs and outputs from ExecutionBuilder to StepExecutor, 115 // in the case where we have a single-"step" execution (i.e., the executor 116 // is executing the entire model from the ExecutionBuilder). 117 void mapInputsAndOutputsTrivially(); 118 119 // Map inputs and outputs from ExecutionBuilder to StepExecutor, 120 // one at a time. Note that these are input/output indexes, not 121 // operand indexes. 122 void mapInput(uint32_t builderIndex, uint32_t executorIndex) { 123 mapInputOrOutput(mExecutionBuilder->mInputs[builderIndex], 124 &mInputs[executorIndex]); 125 } 126 void mapOutput(uint32_t builderIndex, uint32_t executorIndex) { 127 mapInputOrOutput(mExecutionBuilder->mOutputs[builderIndex], 128 &mOutputs[executorIndex]); 129 } 130 131 // TODO: inter-partition temporaries 132 133 int startCompute(sp<Event>* event); 134 135private: 136 int allocatePointerArgumentsToPool(std::vector<ModelArgumentInfo>* args, Memory* memory); 137 int startComputeOnDevice(sp<Event>* event); 138 int startComputeOnCpu(sp<Event>* event); 139 140 void mapInputOrOutput(const ModelArgumentInfo& builderInputOrOutput, 141 ModelArgumentInfo* executorInputOrOutput); 142 143 // describes the full (possibly multiple-"step") execution 144 const ExecutionBuilder* mExecutionBuilder; 145 146 // model to be executed on the executor, in both original and 147 // compiled forms; and device on which to execute it 148 const ModelBuilder* mModel; 149 sp<IDevice> mDriver; // nullptr if CPU execution 150 sp<IPreparedModel> mPreparedModel; // nullptr if CPU execution or if bypassing ExecutionPlan 151 152 // The information we'll send to the driver about the inputs and outputs. 153 // Note that we build this in two steps: 154 // 1. As the arguments are specified, set the corresponding mInputs or mOutputs element. 155 // If set from a pointer, don't set the location in the RequestArgument but store it 156 // instead in mInputBuffers or mOutputBuffers. 157 // 2. Once we have all the inputs and outputs, if needed, allocate shared memory for 158 // the m*Buffers entries. Copy the input values into the shared memory. 159 // We do this to avoid creating a lot of shared memory objects if we have a lot of 160 // parameters specified via pointers. We also avoid copying in the case where 161 // some of the nodes will interpreted on the CPU anyway. 162 std::vector<ModelArgumentInfo> mInputs; 163 std::vector<ModelArgumentInfo> mOutputs; 164 MemoryTracker mMemories; 165}; 166 167} // namespace nn 168} // namespace android 169 170#endif // ANDROID_ML_NN_RUNTIME_EXECUTION_BUILDER_H 171