ExecutionPlan.h revision 1f4381539b7e89c42336ee7cd1addb9a4c317b34
191e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet/* 291e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * Copyright (C) 2017 The Android Open Source Project 391e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * 491e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * Licensed under the Apache License, Version 2.0 (the "License"); 591e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * you may not use this file except in compliance with the License. 691e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * You may obtain a copy of the License at 791e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * 891e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * http://www.apache.org/licenses/LICENSE-2.0 991e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * 1091e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * Unless required by applicable law or agreed to in writing, software 1191e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * distributed under the License is distributed on an "AS IS" BASIS, 1291e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1391e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * See the License for the specific language governing permissions and 1491e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet * limitations under the License. 1591e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet */ 1691e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet 1791e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet// Classes used to plan how to execute a model across multiple devices. 1891e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet 1991e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet#ifndef ANDROID_ML_NN_RUNTIME_EXECUTION_PLAN_H 2091e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet#define ANDROID_ML_NN_RUNTIME_EXECUTION_PLAN_H 2191e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet 2291e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet#include "HalInterfaces.h" 2391e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet#include "Memory.h" 2491e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet#include "NeuralNetworks.h" 2591e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet#include "Utils.h" 2691e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet 278913ae3283de7752aed108c1b26aef1adacb049fDavid Gross#include <set> 288913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 2991e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletnamespace android { 3091e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletnamespace nn { 3191e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet 3291e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletclass CompilationBuilder; 3391e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletclass Device; 348913ae3283de7752aed108c1b26aef1adacb049fDavid Grossclass ExecutionPlan; 3591e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletclass Memory; 3691e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletclass ModelBuilder; 3791e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet 3891e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletclass ExecutionStep { 398913ae3283de7752aed108c1b26aef1adacb049fDavid Grossprivate: 408913ae3283de7752aed108c1b26aef1adacb049fDavid Gross typedef std::vector<std::pair<uint32_t, uint32_t>> RemapVectorType; 418913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 4291e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletpublic: 43f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross enum OperandKind { INPUT, OUTPUT }; 44f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross 458913ae3283de7752aed108c1b26aef1adacb049fDavid Gross ExecutionStep(ExecutionPlan* plan, 468913ae3283de7752aed108c1b26aef1adacb049fDavid Gross uint32_t stepIndex, 478913ae3283de7752aed108c1b26aef1adacb049fDavid Gross std::shared_ptr<ModelBuilder> model, 488913ae3283de7752aed108c1b26aef1adacb049fDavid Gross std::shared_ptr<Device> device); 4991e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet int addOperation(int operationIndex, const ModelBuilder& fromModel); 5091e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet int addOperand(uint32_t fromOperandIndex, uint32_t* toOperandIndex, 51f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross const ModelBuilder& fromModel, OperandKind kind); 5291e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet 538913ae3283de7752aed108c1b26aef1adacb049fDavid Gross // Each vector entry is of the form (fromModel index, subModel index) 548913ae3283de7752aed108c1b26aef1adacb049fDavid Gross const RemapVectorType& getSubModelInputs() const { 558913ae3283de7752aed108c1b26aef1adacb049fDavid Gross return mSubModelInputs; 568913ae3283de7752aed108c1b26aef1adacb049fDavid Gross } 578913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 588913ae3283de7752aed108c1b26aef1adacb049fDavid Gross void recordSubModelOutput(uint32_t fromModelIndex) { 598913ae3283de7752aed108c1b26aef1adacb049fDavid Gross const auto it = mOperandMap.find(fromModelIndex); 608913ae3283de7752aed108c1b26aef1adacb049fDavid Gross nnAssert(it != mOperandMap.end()); 618913ae3283de7752aed108c1b26aef1adacb049fDavid Gross mSubModelOutputs.insert(std::make_pair(fromModelIndex, it->second)); 628913ae3283de7752aed108c1b26aef1adacb049fDavid Gross } 638913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 641f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross int finishSubModel(); 658913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 668913ae3283de7752aed108c1b26aef1adacb049fDavid Gross void dump() const; 6791e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletprivate: 68f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross // TODO: Some of the data is working state information that 69f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross // shouldn't be needed after we've constructed but not executed 70f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross // the step. 71f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross 728913ae3283de7752aed108c1b26aef1adacb049fDavid Gross ExecutionPlan* mPlan; 738913ae3283de7752aed108c1b26aef1adacb049fDavid Gross uint32_t mIndex; // index of step within plan 7491e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet std::shared_ptr<ModelBuilder> mSubModel; 758913ae3283de7752aed108c1b26aef1adacb049fDavid Gross std::shared_ptr<Device> mDevice; // nullptr signifies CPU 761f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross sp<IPreparedModel> mPreparedSubModel; // not used for CPU 77f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross 78f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross // Inputs of original model that are also inputs of this submodel: 79f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross // (fromModel index, subModel index) 808913ae3283de7752aed108c1b26aef1adacb049fDavid Gross RemapVectorType mModelInputs; 81f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross // Outputs of original model that are also outputs of this submodel: 82f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross // (fromModel index, subModel index) 838913ae3283de7752aed108c1b26aef1adacb049fDavid Gross RemapVectorType mModelOutputs; 84f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross // Temporaries of original model that are inputs of this submodel: 85f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross // (fromModel index, subModel index) 868913ae3283de7752aed108c1b26aef1adacb049fDavid Gross RemapVectorType mSubModelInputs; 878913ae3283de7752aed108c1b26aef1adacb049fDavid Gross // Temporaries of original model that are outputs of this submodel: 888913ae3283de7752aed108c1b26aef1adacb049fDavid Gross // (fromModel index, subModel index) 898913ae3283de7752aed108c1b26aef1adacb049fDavid Gross std::set<std::pair<uint32_t, uint32_t>> mSubModelOutputs; 9091e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet // Converts operand indexes from the main model to the submodel. 9191e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet std::unordered_map<uint32_t, uint32_t> mOperandMap; 9291e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet}; 9391e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet 9491e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletclass ExecutionPlan { 958913ae3283de7752aed108c1b26aef1adacb049fDavid Grosspublic: 961f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross ExecutionPlan(const ExecutionPlan&) = delete; 971f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross ExecutionPlan& operator=(const ExecutionPlan&) = delete; 988913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 991f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross ExecutionPlan() { } 1001f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross ~ExecutionPlan() { delete mBody; } 1011f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1021f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross std::shared_ptr<ExecutionStep> createNewStep(const std::shared_ptr<Device> device); 1031f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1041f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross void becomeSingleStep(const std::shared_ptr<Device> device, 1051f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross const ModelBuilder* model); 1061f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1071f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross int finish(); 1088913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 1098913ae3283de7752aed108c1b26aef1adacb049fDavid Gross void recordTemporaryDef(uint32_t fromModelIndex, uint32_t stepIndex) { 1101f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross auto& temporaryToDefiningStep = compound()->mTemporaryToDefiningStep; 1111f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross nnAssert(temporaryToDefiningStep.count(fromModelIndex) == 0); 1121f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross temporaryToDefiningStep.insert(std::make_pair(fromModelIndex, stepIndex)); 11391e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet } 1148913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 1158913ae3283de7752aed108c1b26aef1adacb049fDavid Gross void dump() const; 1168913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 1171f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // TODO: This member function is only temporary, until we finish 1181f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // fully integrating ExecutionPlan with the compilation and 1191f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // execution phases of the NN API. The return value is as follows: 1201f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // 1211f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // NO_ERROR 1221f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // There's exactly one partition, and it was successfully compiled. 1231f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // 1241f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // If device is not nullptr, *device has been set (set to nullptr 1251f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // in the case of CPU execution). 1261f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // 1271f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // If preparedModel is not nullptr, *preparedModel has been set 1281f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // (set to nullptr in the case of CPU execution). 1291f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // 1301f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // OP_FAILED 1311f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // There's exactly one partition, but it was not successfully compiled. 1321f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // 1331f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // BAD_STATE 1341f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // There are zero or multiple partitions. 1351f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // 1361f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross int getSimplePlan(std::shared_ptr<Device>* device = nullptr, 1371f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross sp<IPreparedModel>* preparedModel = nullptr) const; 1381f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1398913ae3283de7752aed108c1b26aef1adacb049fDavid Grossprivate: 1408913ae3283de7752aed108c1b26aef1adacb049fDavid Gross void findSubModelOutputs(); 1418913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 1421f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross struct Body { 1431f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross virtual ~Body() {} 1441f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross virtual void dump() const = 0; 1451f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross virtual int finish() = 0; 1461f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross }; 1471f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1481f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross struct SimpleBody : Body { 1491f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross SimpleBody(std::shared_ptr<Device> device, const ModelBuilder* model) : 1501f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross mDevice(device), mModel(model) {} 1518913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 1521f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross void dump() const override; 1531f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross int finish() override; 1548913ae3283de7752aed108c1b26aef1adacb049fDavid Gross 1551f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross std::shared_ptr<Device> mDevice; // nullptr signifies CPU 1561f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross const ModelBuilder* mModel; 1571f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross sp<IPreparedModel> mPreparedModel; // not used for CPU 1581f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross bool mSuccessfulFinish = false; 1591f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross }; 1601f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1611f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross struct CompoundBody : Body { 1621f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross void dump() const override; 1631f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross int finish() override; 1641f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1651f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // TODO: Some of the data is working state information that 1661f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // shouldn't be needed after we've constructed but not 1671f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // executed the plan. 1681f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1691f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross std::vector<std::shared_ptr<ExecutionStep>> mSteps; 1701f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1711f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // Map from original operand index to defining step index. 1721f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // Used for all (and only) TEMPORARY_VARIABLEs. 1731f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross std::unordered_map<uint32_t, uint32_t> mTemporaryToDefiningStep; 1741f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1751f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross private: 1761f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross void findSubModelOutputs(); 1771f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross }; 1781f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1791f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross enum { EMPTY, SIMPLE, COMPOUND } mState = EMPTY; 1801f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross Body* mBody = nullptr; 1811f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross CompoundBody* compound() { 1821f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross nnAssert(mState == COMPOUND); 1831f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross return static_cast<CompoundBody*>(mBody); 1841f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross } 18591e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet}; 18691e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet 18791e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet} // namespace nn 18891e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet} // namespace android 18991e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet 19091e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet#endif // ANDROID_ML_NN_RUNTIME_EXECUTION_PLAN_H 191