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