ExecutionBuilder.cpp revision 689d892203c06c66c7bb2e374462a8434e40b75f
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 <thread> 27689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler#include <mutex> 28689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler#include <vector> 29689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 30707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletnamespace android { 31707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletnamespace nn { 32707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 338b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc BrouilletRequestBuilder::RequestBuilder(const ModelBuilder* model) 348b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet : mModel(model), 358b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet mInputs(model->inputCount()), 368b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet mOutputs(model->outputCount()), 378b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet mMemories(model->getMemories()) { 38707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(DEBUG) << "RequestBuilder::RequestBuilder"; 398b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& p : mInputs) { 408b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet p.state = ModelArgumentInfo::MISSING; 418b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 428b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& p : mOutputs) { 438b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet p.state = ModelArgumentInfo::MISSING; 448b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 45707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 46707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 47707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletint RequestBuilder::setInput(uint32_t index, const ANeuralNetworksOperandType* type, 48707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet const void* buffer, uint32_t length) { 49707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet uint32_t count = static_cast<uint32_t>(mInputs.size()); 50707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (index >= count) { 51707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_setInput bad index " << index << " " << count; 52707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 53707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 548b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet ModelArgumentInfo& info = mInputs[index]; 558b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.state = ModelArgumentInfo::POINTER; 568b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.locationAndDimension.location = {.poolIndex = RUN_TIME, .offset = 0, .length = length}; 578b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet updateDimensionInfo(&info, type, mModel->getInputOperandIndex(index)); 588b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.buffer = const_cast<void*>(buffer); 59707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 60707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 61707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 628b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletint RequestBuilder::setInputFromMemory(uint32_t index, const ANeuralNetworksOperandType* type, 638b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet const Memory* memory, uint32_t offset, uint32_t length) { 648b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t count = static_cast<uint32_t>(mInputs.size()); 658b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (index >= count) { 668b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_setInputFromMemory bad index " << index << " " 678b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet << count; 688b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 698b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 708b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet ModelArgumentInfo& info = mInputs[index]; 718b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.state = ModelArgumentInfo::MEMORY; 728b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.locationAndDimension.location = {.poolIndex = mMemories.add(memory), 738b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet .offset = offset, 748b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet .length = length}; 758b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet updateDimensionInfo(&info, type, mModel->getInputOperandIndex(index)); 768b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.buffer = nullptr; 778b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 78707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 79707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 80707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletint RequestBuilder::setOutput(uint32_t index, const ANeuralNetworksOperandType* type, void* buffer, 81707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet uint32_t length) { 82707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet uint32_t count = static_cast<uint32_t>(mOutputs.size()); 83707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (index >= count) { 84707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_setOutput bad index " << index << " " << count; 85707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 86707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 878b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet ModelArgumentInfo& info = mOutputs[index]; 888b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.state = ModelArgumentInfo::POINTER; 898b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.locationAndDimension.location = {.poolIndex = RUN_TIME, .offset = 0, .length = length}; 908b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet updateDimensionInfo(&info, type, mModel->getOutputOperandIndex(index)); 918b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.buffer = const_cast<void*>(buffer); 92707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 93707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 94707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 958b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletint RequestBuilder::setOutputFromMemory(uint32_t index, const ANeuralNetworksOperandType* type, 968b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet const Memory* memory, uint32_t offset, uint32_t length) { 978b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t count = static_cast<uint32_t>(mOutputs.size()); 988b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (index >= count) { 998b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_setOutputFromMemory bad index " << index << " " 1008b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet << count; 1018b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 1028b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 1038b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet ModelArgumentInfo& info = mOutputs[index]; 1048b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.state = ModelArgumentInfo::MEMORY; 1058b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.locationAndDimension.location = {.poolIndex = mMemories.add(memory), 1068b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet .offset = offset, 1078b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet .length = length}; 1088b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet updateDimensionInfo(&info, type, mModel->getOutputOperandIndex(index)); 1098b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.buffer = nullptr; 1108b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 111707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 112707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 1138b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletint RequestBuilder::updateDimensionInfo(ModelArgumentInfo* info, 1148b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet const ANeuralNetworksOperandType* newType, 1158b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t operandIndex) { 116707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (newType == nullptr) { 1178b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info->locationAndDimension.dimensions = hidl_vec<uint32_t>(); 118707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } else { 119707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet const Operand& operand = mModel->getOperand(operandIndex); 120707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet uint32_t count = newType->dimensions.count; 121707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (static_cast<OperandType>(newType->type) != operand.type || 122707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet count != operand.dimensions.size()) { 123707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_setInput/Output incompatible types"; 124707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 125707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 126707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet for (uint32_t i = 0; i < count; i++) { 1278b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info->locationAndDimension.dimensions[i] = newType->dimensions.data[i]; 128707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 129707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 130707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 131707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 132707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 133689d892203c06c66c7bb2e374462a8434e40b75fMichael Butlerint RequestBuilder::startCompute(sp<Event>* event) { 134689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler *event = nullptr; 135689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 136707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // TODO validate that we have full types for all inputs and outputs, 137707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // that the graph is not cyclic, 138f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni /* 139f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni TODO: For non-optional inputs, also verify that buffers are not null. 140f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni 1418b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& p : mInputs) { 1428b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (p.state == ModelArgumentInfo::MISSING) { 143707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_startCompute not all inputs specified"; 144707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 145707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 146707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 147f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni */ 1488b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& p : mOutputs) { 1498b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (p.state == ModelArgumentInfo::MISSING) { 150707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_startCompute not all outputs specified"; 151707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 152707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 153707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 154707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(DEBUG) << "RequestBuilder::startCompute"; 155707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 156707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet std::shared_ptr<Device> device = DeviceManager::get()->getAvailableDriver(); 157707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet Model model; 158707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet mModel->setHidlModel(&model); 159707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 160689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler return device == nullptr ? startComputeOnCpu(model, event) 161707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet : startComputeOnDevice(device->getInterface(), model, event); 162707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 163707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 164707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet// Figures out how to place each of the input or outputs in a buffer. This just does the layout, 1658b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet// it does not copy data. Aligns each input a bit. 1668b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletint RequestBuilder::allocatePointerArgumentsToPool(std::vector<ModelArgumentInfo>* args, 1678b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet Memory* memory) { 1688b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t nextPoolIndex = mMemories.size(); 169707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet int64_t total = 0; 1708b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& info : *args) { 1718b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (info.state == ModelArgumentInfo::POINTER) { 1728b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet DataLocation& loc = info.locationAndDimension.location; 1738b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // TODO Good enough alignment? 1748b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet total += alignBytesNeeded(static_cast<uint32_t>(total), loc.length); 1758b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet loc.poolIndex = nextPoolIndex; 1768b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet loc.offset = static_cast<uint32_t>(total); 1778b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet total += loc.length; 1788b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 1798b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet }; 180707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (total > 0xFFFFFFFF) { 181707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(ERROR) << "ANeuralNetworksRequest_startCompute Size of all inputs or outputs exceeds " 182707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet "2^32."; 183707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_BAD_DATA; 184707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 1858b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet hidl_memory hidlMemory; 1868b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (total > 0) { 1878b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet memory->create(total); // TODO check error 1888b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet mMemories.add(memory); 1898b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 190707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 191707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 192707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 1938b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletstatic void copyLocationAndDimension(const std::vector<ModelArgumentInfo>& argumentInfos, 1948b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet hidl_vec<InputOutputInfo>* ioInfos) { 1958b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet size_t count = argumentInfos.size(); 1968b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet ioInfos->resize(count); 1978b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (size_t i = 0; i < count; i++) { 1988b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet (*ioInfos)[i] = argumentInfos[i].locationAndDimension; 1998b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 2008b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet} 2018b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet 202689d892203c06c66c7bb2e374462a8434e40b75fMichael Butlerint RequestBuilder::startComputeOnDevice(sp<IDevice> driver, const Model& model, 203689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler sp<Event>* event) { 204689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler *event = nullptr; 205689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 2068b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LOG(DEBUG) << "RequestBuilder::startComputeOnDevice1"; 207707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // TODO Dangerous! In async, the model will outlive it here. Safe for now 208707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet sp<IPreparedModel> preparedModel = driver->prepareModel(model); 209707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (preparedModel == nullptr) { 210707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_OP_FAILED; 211707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 212707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 2138b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // Layout the input and output data 2148b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet int n = allocatePointerArgumentsToPool(&mInputs, &mInputPointerArguments); 215707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 216707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return n; 217707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 2188b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet n = allocatePointerArgumentsToPool(&mOutputs, &mOutputPointerArguments); 219707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (n != ANEURALNETWORKS_NO_ERROR) { 220707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return n; 221707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 222707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 2238b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // Copy the input data that was specified via a pointer. 2248b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // mInputPointerArguments.update(); 2258b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& info : mInputs) { 2268b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (info.state == ModelArgumentInfo::POINTER) { 2278b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet DataLocation& loc = info.locationAndDimension.location; 2288b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint8_t* data = mInputPointerArguments.getPointer(); 2298b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet memcpy(data + loc.offset, info.buffer, loc.length); 2308b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 231707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 2328b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // TODO: Add mInputPointerArguments.commit() and .update() at all the right places 233707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 234707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet Request request; 2358b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet copyLocationAndDimension(mInputs, &request.inputs); 2368b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet copyLocationAndDimension(mOutputs, &request.outputs); 2378b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t count = mMemories.size(); 2388b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet request.pools.resize(count); 2398b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (uint32_t i = 0; i < count; i++) { 2408b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet request.pools[i] = mMemories[i]->getHidlMemory(); 2418b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 242707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 243689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // Prepare the event for asynchronous execution. The sp<Event> object is 244689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // returned when the request has been successfully launched, otherwise a 245689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // nullptr is returned. The sp is used for ref-counting purposes. Without 246689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // it, the HIDL service could attempt to communicate with a dead event 247689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // object. 248689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // 249689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: Explain the "dead event" problem further, either here or 250689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // in the design document. 251689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler sp<Event> eventSp = new Event(); 252689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 2538b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LOG(DEBUG) << "Before preparedModel->execute() " << toString(request); 254707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // Execute the request. 255689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: What happens to the Event if the service dies abnormally 256689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // -- won't that keep the Event live forever, because the service 257689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // never has the opportunity to bump the reference count down? Or 258689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // maybe the HIDL infrastructure handles this magically? At worst, 259689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // it seems like this is a small memory leak, if the Event stays 260689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // alive forever. 261689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler if (!preparedModel->execute(request, eventSp)) { 262707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(DEBUG) << "**Execute failed**"; 263707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_OP_FAILED; 264707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 265707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 266689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: Remove this synchronization point when the block of code below is 267689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // removed. 268689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler Event::Status status = eventSp->wait(); 269689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler if (status != Event::Status::SUCCESS) { 270689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler LOG(DEBUG) << "**Execute async failed**"; 271689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler return ANEURALNETWORKS_OP_FAILED; 272689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler } 273689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 274707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // Copy the output data from shared memory to the output buffers. 275689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: Move this block of code somewhere else. It should not be in the 276689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // startCompute function. 277689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: outputMemory->update(); outputMemory->commit() 2788b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (auto& info : mOutputs) { 2798b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (info.state == ModelArgumentInfo::POINTER) { 2808b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet DataLocation& loc = info.locationAndDimension.location; 2818b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint8_t* data = mOutputPointerArguments.getPointer(); 2828b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet memcpy(info.buffer, data + loc.offset, loc.length); 2838b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 284707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 285707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LOG(DEBUG) << "RequestBuilder::startComputeOnDevice completed"; 286707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 287689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler *event = eventSp; 288707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return ANEURALNETWORKS_NO_ERROR; 289707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 290707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 291689d892203c06c66c7bb2e374462a8434e40b75fMichael Butlerstatic void asyncStartComputeOnCpu(const Model& model, const Request& request, 292689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler const std::vector<RunTimePoolInfo>& runTimePoolInfos, 293689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler const sp<IEvent>& event) { 294689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler CpuExecutor executor; 295689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler int err = executor.run(model, request, runTimePoolInfos); 296689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler Status executionStatus = err == ANEURALNETWORKS_NO_ERROR ? Status::SUCCESS : Status::ERROR; 297689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler event->notify(executionStatus); 298689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler} 299689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 300689d892203c06c66c7bb2e374462a8434e40b75fMichael Butlerint RequestBuilder::startComputeOnCpu([[maybe_unused]] const Model& model, sp<Event>* event) { 301707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // TODO: use a thread pool 302689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 303689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // Prepare the event for asynchronous execution. The sp<Event> object is 304689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // returned when the request has been successfully launched, otherwise a 305689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // nullptr is returned. 306689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler sp<Event> eventSp = new Event(); 307689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler *event = nullptr; 308707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 309707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet std::vector<RunTimePoolInfo> runTimePoolInfos; 3108b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet uint32_t count = mMemories.size(); 3118b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet runTimePoolInfos.resize(count); 3128b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (uint32_t i = 0; i < count; i++) { 3138b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet const Memory* mem = mMemories[i]; 3148b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet runTimePoolInfos[i].set(mem->getHidlMemory()); 3158b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 3168b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // Create as many pools as there are input / output. 3178b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet auto fixPointerArguments = [&runTimePoolInfos](std::vector<ModelArgumentInfo>& argumentInfos) { 3188b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (ModelArgumentInfo& argumentInfo : argumentInfos) { 3198b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (argumentInfo.state == ModelArgumentInfo::POINTER) { 3208b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet RunTimePoolInfo runTimeInfo = {.buffer = static_cast<uint8_t*>(argumentInfo.buffer)}; 3218b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet argumentInfo.locationAndDimension.location.poolIndex = 3228b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet static_cast<uint32_t>(runTimePoolInfos.size()); 3238b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet argumentInfo.locationAndDimension.location.offset = 0; 3248b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet runTimePoolInfos.push_back(runTimeInfo); 3258b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 3268b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 3278b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet }; 3288b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet fixPointerArguments(mInputs); 3298b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet fixPointerArguments(mOutputs); 330707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 3318b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet Request request; 3328b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet copyLocationAndDimension(mInputs, &request.inputs); 3338b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet copyLocationAndDimension(mOutputs, &request.outputs); 334707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 335689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler // TODO: should model be moved with a std::cref? 336689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler std::thread thread(asyncStartComputeOnCpu, model, std::move(request), 337689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler std::move(runTimePoolInfos), eventSp); 338689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler eventSp->bind_thread(std::move(thread)); 339689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 340689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler *event = eventSp; 341689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler return ANEURALNETWORKS_NO_ERROR; 342707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} 343707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 344707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} // namespace nn 345707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet} // namespace android 346