ExecutionBuilder.cpp revision 105807d963d969197fe78185ed588bfad3dc0ea5
1707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet/* 2707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * Copyright (C) 2017 The Android Open Source Project 3707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * 4707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * Licensed under the Apache License, Version 2.0 (the "License"); 5707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * you may not use this file except in compliance with the License. 6707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * You may obtain a copy of the License at 7707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * 8707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * http://www.apache.org/licenses/LICENSE-2.0 9707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * 10707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * Unless required by applicable law or agreed to in writing, software 11707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * distributed under the License is distributed on an "AS IS" BASIS, 12707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * See the License for the specific language governing permissions and 14707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * limitations under the License. 15707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet */ 16707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 17707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet#define LOG_TAG "RequestBuilder" 18707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 19707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet#include "RequestBuilder.h" 20707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 21707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet#include "CpuExecutor.h" 22707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet#include "HalInterfaces.h" 23707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet#include "Manager.h" 24707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet#include "ModelBuilder.h" 25707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 26689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler#include <mutex> 27389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet#include <thread> 28689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler#include <vector> 29689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 30707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletnamespace android { 31707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletnamespace nn { 32707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 33389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouilletint ModelArgumentInfo::setFromPointer(const Operand& operand, 34389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet const ANeuralNetworksOperandType* type, void* data, 35389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet uint32_t length) { 36389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet int n = updateDimensionInfo(operand, type); 37389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 38389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet return n; 39389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet } 40389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet state = ModelArgumentInfo::POINTER; 41389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet locationAndDimension.location = {.poolIndex = RUN_TIME, .offset = 0, .length = length}; 42389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet buffer = data; 43389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 44389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet} 45389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 46389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouilletint ModelArgumentInfo::setFromMemory(const Operand& operand, const ANeuralNetworksOperandType* type, 47389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet uint32_t poolIndex, uint32_t offset, uint32_t length) { 48389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet int n = updateDimensionInfo(operand, type); 49389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 50389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet return n; 51389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet } 52389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet state = ModelArgumentInfo::MEMORY; 53389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet locationAndDimension.location = {.poolIndex = poolIndex, .offset = offset, .length = length}; 54389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet buffer = nullptr; 55389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 56389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet} 57389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 58389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouilletint ModelArgumentInfo::updateDimensionInfo(const Operand& operand, 59389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet const ANeuralNetworksOperandType* newType) { 60389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet if (newType == nullptr) { 61389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet locationAndDimension.dimensions = hidl_vec<uint32_t>(); 62389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet } else { 63389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet uint32_t count = newType->dimensions.count; 64389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet if (static_cast<OperandType>(newType->type) != operand.type || 65389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet count != operand.dimensions.size()) { 66389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_setInput/Output incompatible types"; 67389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 68389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet } 69389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet for (uint32_t i = 0; i < count; i++) { 70389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet locationAndDimension.dimensions[i] = newType->dimensions.data[i]; 71389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet } 72389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet } 73389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 74389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet} 75389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 768b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc BrouilletRequestBuilder::RequestBuilder(const ModelBuilder* model) 77389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet : mModel(model), 78389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet mInputs(model->inputCount()), 79389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet mOutputs(model->outputCount()), 80389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet mMemories(model->getMemories()) { 81707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(DEBUG) << "RequestBuilder::RequestBuilder"; 828b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& p : mInputs) { 83389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet p.state = ModelArgumentInfo::UNSPECIFIED; 848b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 858b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& p : mOutputs) { 86389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet p.state = ModelArgumentInfo::UNSPECIFIED; 878b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 88707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 89707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 90707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletint RequestBuilder::setInput(uint32_t index, const ANeuralNetworksOperandType* type, 91707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet const void* buffer, uint32_t length) { 92707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet uint32_t count = static_cast<uint32_t>(mInputs.size()); 93707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (index >= count) { 94707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_setInput bad index " << index << " " << count; 95707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 96707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 97389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet return mInputs[index].setFromPointer(mModel->getInputOperand(index), type, 98389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet const_cast<void*>(buffer), length); 99707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 100707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 1018b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletint RequestBuilder::setInputFromMemory(uint32_t index, const ANeuralNetworksOperandType* type, 1028b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet const Memory* memory, uint32_t offset, uint32_t length) { 1038b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t count = static_cast<uint32_t>(mInputs.size()); 1048b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (index >= count) { 1058b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_setInputFromMemory bad index " << index << " " 1068b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet << count; 1078b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 1088b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 109105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang if (!memory->validateSize(offset, length)) { 110105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang return ANEURALNETWORKS_BAD_DATA; 111105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang } 112389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet uint32_t poolIndex = mMemories.add(memory); 113389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet return mInputs[index].setFromMemory(mModel->getInputOperand(index), type, poolIndex, offset, 114389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet length); 115707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 116707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 117707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletint RequestBuilder::setOutput(uint32_t index, const ANeuralNetworksOperandType* type, void* buffer, 118707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet uint32_t length) { 119707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet uint32_t count = static_cast<uint32_t>(mOutputs.size()); 120707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (index >= count) { 121707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_setOutput bad index " << index << " " << count; 122707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 123707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 124389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet return mOutputs[index].setFromPointer(mModel->getOutputOperand(index), type, buffer, length); 125707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 126707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 1278b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletint RequestBuilder::setOutputFromMemory(uint32_t index, const ANeuralNetworksOperandType* type, 1288b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet const Memory* memory, uint32_t offset, uint32_t length) { 1298b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t count = static_cast<uint32_t>(mOutputs.size()); 1308b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (index >= count) { 1318b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_setOutputFromMemory bad index " << index << " " 1328b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet << count; 1338b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 1348b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 135105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang if (!memory->validateSize(offset, length)) { 136105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang return ANEURALNETWORKS_BAD_DATA; 137105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang } 138389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet uint32_t poolIndex = mMemories.add(memory); 139389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet return mOutputs[index].setFromMemory(mModel->getOutputOperand(index), type, poolIndex, offset, 140389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet length); 141707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 142707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 143689d892203c06c66c7bb2e374462a8434e40b75fMichael Butlerint RequestBuilder::startCompute(sp<Event>* event) { 144689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler *event = nullptr; 145689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 146707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // TODO validate that we have full types for all inputs and outputs, 147707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // that the graph is not cyclic, 148f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni /* 149f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni TODO: For non-optional inputs, also verify that buffers are not null. 150f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni 1518b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& p : mInputs) { 152389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet if (p.state == ModelArgumentInfo::UNSPECIFIED) { 153707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_startCompute not all inputs specified"; 154707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 155707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 156707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 157f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni */ 1588b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& p : mOutputs) { 159389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet if (p.state == ModelArgumentInfo::UNSPECIFIED) { 160707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_startCompute not all outputs specified"; 161707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 162707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 163707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 164707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(DEBUG) << "RequestBuilder::startCompute"; 165707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 166707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet std::shared_ptr<Device> device = DeviceManager::get()->getAvailableDriver(); 167707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet Model model; 168707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet mModel->setHidlModel(&model); 169707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 170689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler return device == nullptr ? startComputeOnCpu(model, event) 171707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet : startComputeOnDevice(device->getInterface(), model, event); 172707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 173707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 174707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet// Figures out how to place each of the input or outputs in a buffer. This just does the layout, 1758b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet// it does not copy data. Aligns each input a bit. 1768b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletint RequestBuilder::allocatePointerArgumentsToPool(std::vector<ModelArgumentInfo>* args, 1778b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet Memory* memory) { 1788b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t nextPoolIndex = mMemories.size(); 179707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet int64_t total = 0; 1808b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& info : *args) { 1818b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (info.state == ModelArgumentInfo::POINTER) { 1828b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet DataLocation& loc = info.locationAndDimension.location; 1838b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // TODO Good enough alignment? 1848b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet total += alignBytesNeeded(static_cast<uint32_t>(total), loc.length); 1858b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet loc.poolIndex = nextPoolIndex; 1868b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet loc.offset = static_cast<uint32_t>(total); 1878b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet total += loc.length; 1888b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 1898b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet }; 190707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (total > 0xFFFFFFFF) { 191707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_startCompute Size of all inputs or outputs exceeds " 192707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet "2^32."; 193707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 194707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 1958b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet hidl_memory hidlMemory; 1968b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (total > 0) { 197389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet memory->create(total); // TODO check error 1988b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet mMemories.add(memory); 1998b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 200707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 201707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 202707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 2038b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletstatic void copyLocationAndDimension(const std::vector<ModelArgumentInfo>& argumentInfos, 2048b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet hidl_vec<InputOutputInfo>* ioInfos) { 2058b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet size_t count = argumentInfos.size(); 2068b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet ioInfos->resize(count); 2078b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (size_t i = 0; i < count; i++) { 2088b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet (*ioInfos)[i] = argumentInfos[i].locationAndDimension; 2098b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 2108b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet} 2118b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet 212389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouilletint RequestBuilder::startComputeOnDevice(sp<IDevice> driver, const Model& model, sp<Event>* event) { 213689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler *event = nullptr; 214689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 2158b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LOG(DEBUG) << "RequestBuilder::startComputeOnDevice1"; 216707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // TODO Dangerous! In async, the model will outlive it here. Safe for now 217707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet sp<IPreparedModel> preparedModel = driver->prepareModel(model); 218707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (preparedModel == nullptr) { 219707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_OP_FAILED; 220707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 221707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 2228b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // Layout the input and output data 2238b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet int n = allocatePointerArgumentsToPool(&mInputs, &mInputPointerArguments); 224707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 225707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return n; 226707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 2278b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet n = allocatePointerArgumentsToPool(&mOutputs, &mOutputPointerArguments); 228707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 229707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return n; 230707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 231707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 2328b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // Copy the input data that was specified via a pointer. 2338b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // mInputPointerArguments.update(); 2348b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& info : mInputs) { 2358b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (info.state == ModelArgumentInfo::POINTER) { 2368b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet DataLocation& loc = info.locationAndDimension.location; 2372150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet uint8_t* data = nullptr; 2382150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet int n = mInputPointerArguments.getPointer(&data); 2392150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 2402150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet return n; 2412150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet } 2428b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet memcpy(data + loc.offset, info.buffer, loc.length); 2438b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 244707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 2458b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // TODO: Add mInputPointerArguments.commit() and .update() at all the right places 246707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 247707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet Request request; 2488b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet copyLocationAndDimension(mInputs, &request.inputs); 2498b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet copyLocationAndDimension(mOutputs, &request.outputs); 2508b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t count = mMemories.size(); 2518b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet request.pools.resize(count); 2528b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (uint32_t i = 0; i < count; i++) { 2538b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet request.pools[i] = mMemories[i]->getHidlMemory(); 2548b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 255707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 256689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // Prepare the event for asynchronous execution. The sp<Event> object is 257689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // returned when the request has been successfully launched, otherwise a 258689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // nullptr is returned. The sp is used for ref-counting purposes. Without 259689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // it, the HIDL service could attempt to communicate with a dead event 260689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // object. 261689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // 262689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: Explain the "dead event" problem further, either here or 263689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // in the design document. 264689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler sp<Event> eventSp = new Event(); 265689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 2668b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LOG(DEBUG) << "Before preparedModel->execute() " << toString(request); 267707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // Execute the request. 268689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: What happens to the Event if the service dies abnormally 269689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // -- won't that keep the Event live forever, because the service 270689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // never has the opportunity to bump the reference count down? Or 271689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // maybe the HIDL infrastructure handles this magically? At worst, 272689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // it seems like this is a small memory leak, if the Event stays 273689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // alive forever. 274689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler if (!preparedModel->execute(request, eventSp)) { 275707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(DEBUG) << "**Execute failed**"; 276707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_OP_FAILED; 277707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 278707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 279689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: Remove this synchronization point when the block of code below is 280689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // removed. 281689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler Event::Status status = eventSp->wait(); 282689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler if (status != Event::Status::SUCCESS) { 283689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler LOG(DEBUG) << "**Execute async failed**"; 284689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler return ANEURALNETWORKS_OP_FAILED; 285689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler } 286689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 287707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // Copy the output data from shared memory to the output buffers. 288689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: Move this block of code somewhere else. It should not be in the 289689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // startCompute function. 290689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: outputMemory->update(); outputMemory->commit() 2918b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& info : mOutputs) { 2928b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (info.state == ModelArgumentInfo::POINTER) { 2938b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet DataLocation& loc = info.locationAndDimension.location; 2942150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet uint8_t* data = nullptr; 2952150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet int n = mOutputPointerArguments.getPointer(&data); 2962150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 2972150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet return n; 2982150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet } 2998b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet memcpy(info.buffer, data + loc.offset, loc.length); 3008b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 301707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 302707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(DEBUG) << "RequestBuilder::startComputeOnDevice completed"; 303707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 304689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler *event = eventSp; 305707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 306707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 307707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 308689d892203c06c66c7bb2e374462a8434e40b75fMichael Butlerstatic void asyncStartComputeOnCpu(const Model& model, const Request& request, 309689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler const std::vector<RunTimePoolInfo>& runTimePoolInfos, 310689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler const sp<IEvent>& event) { 311689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler CpuExecutor executor; 312689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler int err = executor.run(model, request, runTimePoolInfos); 313689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler Status executionStatus = err == ANEURALNETWORKS_NO_ERROR ? Status::SUCCESS : Status::ERROR; 314689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler event->notify(executionStatus); 315689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler} 316689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 317689d892203c06c66c7bb2e374462a8434e40b75fMichael Butlerint RequestBuilder::startComputeOnCpu([[maybe_unused]] const Model& model, sp<Event>* event) { 318707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // TODO: use a thread pool 319689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 320689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // Prepare the event for asynchronous execution. The sp<Event> object is 321689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // returned when the request has been successfully launched, otherwise a 322689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // nullptr is returned. 323689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler sp<Event> eventSp = new Event(); 324689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler *event = nullptr; 325707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 326707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet std::vector<RunTimePoolInfo> runTimePoolInfos; 3278b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t count = mMemories.size(); 3288b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet runTimePoolInfos.resize(count); 3298b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (uint32_t i = 0; i < count; i++) { 3308b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet const Memory* mem = mMemories[i]; 3318b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet runTimePoolInfos[i].set(mem->getHidlMemory()); 3328b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 3338b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // Create as many pools as there are input / output. 3348b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet auto fixPointerArguments = [&runTimePoolInfos](std::vector<ModelArgumentInfo>& argumentInfos) { 3358b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (ModelArgumentInfo& argumentInfo : argumentInfos) { 3368b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (argumentInfo.state == ModelArgumentInfo::POINTER) { 337389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet RunTimePoolInfo runTimeInfo = { 338389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet .buffer = static_cast<uint8_t*>(argumentInfo.buffer)}; 3398b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet argumentInfo.locationAndDimension.location.poolIndex = 340389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet static_cast<uint32_t>(runTimePoolInfos.size()); 3418b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet argumentInfo.locationAndDimension.location.offset = 0; 3428b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet runTimePoolInfos.push_back(runTimeInfo); 3438b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 3448b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 3458b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet }; 3468b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet fixPointerArguments(mInputs); 3478b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet fixPointerArguments(mOutputs); 348707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 3498b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet Request request; 3508b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet copyLocationAndDimension(mInputs, &request.inputs); 3518b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet copyLocationAndDimension(mOutputs, &request.outputs); 352707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 353689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: should model be moved with a std::cref? 354689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler std::thread thread(asyncStartComputeOnCpu, model, std::move(request), 355689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler std::move(runTimePoolInfos), eventSp); 356689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler eventSp->bind_thread(std::move(thread)); 357689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 358689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler *event = eventSp; 359689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler return ANEURALNETWORKS_NO_ERROR; 360707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 361707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 362389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet} // namespace nn 363389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet} // namespace android 364