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