ExecutionPlan.h revision 891b10f7048c62a37a74c4b570be220089dfd55e
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;
34b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Grossclass ExecutionBuilder;
358913ae3283de7752aed108c1b26aef1adacb049fDavid Grossclass ExecutionPlan;
3691e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletclass Memory;
3791e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletclass ModelBuilder;
38b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Grossclass StepExecutor;
3991e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet
4091e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletclass ExecutionStep {
418913ae3283de7752aed108c1b26aef1adacb049fDavid Grossprivate:
428913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    typedef std::vector<std::pair<uint32_t, uint32_t>> RemapVectorType;
43b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    typedef std::set<std::pair<uint32_t, uint32_t>> SubModelOutputSetType;
448913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
4591e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletpublic:
46f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross    enum OperandKind { INPUT, OUTPUT };
47f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross
488913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    ExecutionStep(ExecutionPlan* plan,
498913ae3283de7752aed108c1b26aef1adacb049fDavid Gross                  uint32_t stepIndex,
508913ae3283de7752aed108c1b26aef1adacb049fDavid Gross                  std::shared_ptr<ModelBuilder> model,
518913ae3283de7752aed108c1b26aef1adacb049fDavid Gross                  std::shared_ptr<Device> device);
5291e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet    int addOperation(int operationIndex, const ModelBuilder& fromModel);
5391e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet    int addOperand(uint32_t fromOperandIndex, uint32_t* toOperandIndex,
54f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross                   const ModelBuilder& fromModel, OperandKind kind);
5591e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet
568913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    // Each vector entry is of the form (fromModel index, subModel index)
578913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    const RemapVectorType& getSubModelInputs() const {
588913ae3283de7752aed108c1b26aef1adacb049fDavid Gross        return mSubModelInputs;
598913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    }
608913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
61b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    size_t countSubModelOutputs() const;
62b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross
638913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    void recordSubModelOutput(uint32_t fromModelIndex) {
648913ae3283de7752aed108c1b26aef1adacb049fDavid Gross        const auto it = mOperandMap.find(fromModelIndex);
658913ae3283de7752aed108c1b26aef1adacb049fDavid Gross        nnAssert(it != mOperandMap.end());
668913ae3283de7752aed108c1b26aef1adacb049fDavid Gross        mSubModelOutputs.insert(std::make_pair(fromModelIndex, it->second));
678913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    }
688913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
69b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // If this step has a submodel output of unknown size, sets
70b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // *hasOutputOfUnknownSize to true; otherwise, leaves it
71b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // unchanged.
72891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    int finishSubModel(const ModelBuilder* fromModel, bool* hasOutputOfUnknownSize);
73891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross
74891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    std::shared_ptr<ModelBuilder> getSubModel() const { return mSubModel; }
75891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    std::shared_ptr<Device> getDevice() const { return mDevice; }
76891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross
77891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    // only available after calling finishSubModel()
78891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    sp<IPreparedModel> getPreparedSubModel() const { return mPreparedSubModel; }
79891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross
80891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    // Map inputs and outputs from ExecutionBuilder to StepExecutor.
81891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    void mapInputsAndOutputs(std::shared_ptr<StepExecutor> stepExecutor) const;
828913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
838913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    void dump() const;
8491e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletprivate:
85f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross    // TODO: Some of the data is working state information that
86f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross    // shouldn't be needed after we've constructed but not executed
87f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross    // the step.
88f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross
898913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    ExecutionPlan* mPlan;
908913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    uint32_t mIndex;  // index of step within plan
9191e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet    std::shared_ptr<ModelBuilder> mSubModel;
928913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    std::shared_ptr<Device> mDevice;  // nullptr signifies CPU
931f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    sp<IPreparedModel> mPreparedSubModel;  // not used for CPU
94f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross
95f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross    // Inputs of original model that are also inputs of this submodel:
96f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross    //     (fromModel index, subModel index)
978913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    RemapVectorType mModelInputs;
98f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross    // Outputs of original model that are also outputs of this submodel:
99f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross    //     (fromModel index, subModel index)
1008913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    RemapVectorType mModelOutputs;
101f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross    // Temporaries of original model that are inputs of this submodel:
102f4e1c640547a44c7a37209e81ee5f3831b7d0fdcDavid Gross    //     (fromModel index, subModel index)
1038913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    RemapVectorType mSubModelInputs;
1048913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    // Temporaries of original model that are outputs of this submodel:
1058913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    //     (fromModel index, subModel index)
106b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    SubModelOutputSetType mSubModelOutputs;
10791e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet    // Converts operand indexes from the main model to the submodel.
10891e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet    std::unordered_map<uint32_t, uint32_t> mOperandMap;
109891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    // Converts input indexes from the submodel to the main model
110891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    // (these are input indexes, not operand indexes).  This vector
111891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    // only describes inputs of the submodel that are also inputs of
112891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    // the main model -- that is, mModelInputs but not mSubModelInputs.
113891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    std::vector<uint32_t> mInputIndexSubModelToFromModel;
114891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    // Converts output indexes from the submodel to the main model
115891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    // (these are output indexes, not operand indexes).  This vector
116891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    // only describes outputs of the submodel that are also outputs of
117891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    // the main model -- that is, mModelOutputs but not mSubModelOutputs.
118891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    std::vector<uint32_t> mOutputIndexSubModelToFromModel;
11991e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet};
12091e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet
12191e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouilletclass ExecutionPlan {
1228913ae3283de7752aed108c1b26aef1adacb049fDavid Grosspublic:
1231f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    ExecutionPlan(const ExecutionPlan&) = delete;
1241f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    ExecutionPlan& operator=(const ExecutionPlan&) = delete;
1258913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
1261f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    ExecutionPlan() { }
1271f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    ~ExecutionPlan() { delete mBody; }
1281f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
129b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // Controller is part of the interface to a mechanism for
130b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // performing an execution in N steps.
131b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    //
132b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // Usage pattern:
133b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // - Instantiate Controller with ExecutionPlan::makeController().
134b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // - Call ExecutionPlan::next() on Controller N+1 times.  The first N times,
135b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    //   *executor is set to point to a new StepExecutor corresponding
136b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    //   to that step.  The N+1st time, *executor is set to nullptr,
137b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    //   signifying there are no more steps.
138b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // - If ExecutionPlan::next() returns anything other than ANEURALNETWORKS_NO_ERROR,
139b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    //   a problem has occurred.
140b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    class Controller {
141b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross        friend class ExecutionPlan;
142b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    private:
143b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross        static const size_t kBadStepIndex = ~size_t(0);
144b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross
145b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross        Controller(const ExecutionPlan* plan, const ExecutionBuilder* executionBuilder) :
146b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross                mPlan(plan), mExecutionBuilder(executionBuilder), mNextStepIndex(0) {}
147b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross        Controller() {}  // used for error state
148b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross
149b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross        const ExecutionPlan* mPlan = nullptr;
150b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross        const ExecutionBuilder* mExecutionBuilder = nullptr;
151b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross        size_t mNextStepIndex = kBadStepIndex;
152b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    };
153b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross
154b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    Controller makeController(const ExecutionBuilder* executionBuilder) const;
155b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross
156b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    int next(Controller* controller, std::shared_ptr<StepExecutor>* executor) const;
157b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross
1581f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    std::shared_ptr<ExecutionStep> createNewStep(const std::shared_ptr<Device> device);
1591f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
1601f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    void becomeSingleStep(const std::shared_ptr<Device> device,
1611f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross                          const ModelBuilder* model);
1621f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
163891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross    int finish(const ModelBuilder* fromModel);
1648913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
1658913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    void recordTemporaryDef(uint32_t fromModelIndex, uint32_t stepIndex) {
1661f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        auto& temporaryToDefiningStep = compound()->mTemporaryToDefiningStep;
1671f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        nnAssert(temporaryToDefiningStep.count(fromModelIndex) == 0);
1681f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        temporaryToDefiningStep.insert(std::make_pair(fromModelIndex, stepIndex));
16991e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet    }
1708913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
1718913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    void dump() const;
1728913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
1731f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    // TODO: This member function is only temporary, until we finish
1741f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    // fully integrating ExecutionPlan with the compilation and
175b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // execution phases of the NN API.
1761f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    //
177b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // Returns true if the plan is "in scope for execution" -- i.e.,
178b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // the structure of the plan is such that the
179b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // currently-implemented execution system ought to be able to
180b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // handle it.  May return true even if something went wrong with
181b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // the partitioning and compilation process.
1821f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    //
183b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // true - single partition (even if compilation failed)
184b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    // false - multiple partitions
185b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross    bool shouldBeExecutable() const;
1861f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
1878913ae3283de7752aed108c1b26aef1adacb049fDavid Grossprivate:
1888913ae3283de7752aed108c1b26aef1adacb049fDavid Gross    void findSubModelOutputs();
1898913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
1901f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    struct Body {
1911f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        virtual ~Body() {}
1921f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        virtual void dump() const = 0;
193891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross        virtual int finish(const ModelBuilder* fromModel) = 0;
194891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross        bool mSuccessfulFinish = false;
1951f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    };
1961f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
1971f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    struct SimpleBody : Body {
1981f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        SimpleBody(std::shared_ptr<Device> device, const ModelBuilder* model) :
1991f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross                mDevice(device), mModel(model) {}
2008913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
2011f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        void dump() const override;
202891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross        int finish(const ModelBuilder* fromModel) override;
2038913ae3283de7752aed108c1b26aef1adacb049fDavid Gross
2041f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        std::shared_ptr<Device> mDevice;  // nullptr signifies CPU
2051f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        const ModelBuilder* mModel;
2061f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        sp<IPreparedModel> mPreparedModel;  // not used for CPU
2071f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    };
2081f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
2091f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    struct CompoundBody : Body {
2101f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        void dump() const override;
211891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross        int finish(const ModelBuilder* fromModel) override;
2121f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
2131f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        // TODO: Some of the data is working state information that
2141f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        // shouldn't be needed after we've constructed but not
2151f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        // executed the plan.
2161f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
2171f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        std::vector<std::shared_ptr<ExecutionStep>> mSteps;
2181f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
2191f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        // Map from original operand index to defining step index.
2201f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        // Used for all (and only) TEMPORARY_VARIABLEs.
2211f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        std::unordered_map<uint32_t, uint32_t> mTemporaryToDefiningStep;
2221f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
223b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross        // Total number of submodel outputs across all steps.
224b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross        size_t mSubModelOutputCount = 0;
225b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross
226891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross        bool mHasSubModelOutputOfUnknownSize = false;
2271f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    private:
2281f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        void findSubModelOutputs();
2291f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    };
2301f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross
2311f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    enum { EMPTY, SIMPLE, COMPOUND } mState = EMPTY;
2321f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    Body* mBody = nullptr;
2331f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    CompoundBody* compound() {
2341f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        nnAssert(mState == COMPOUND);
2351f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross        return static_cast<CompoundBody*>(mBody);
2361f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross    }
23791e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet};
23891e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet
23991e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet}  // namespace nn
24091e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet}  // namespace android
24191e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet
24291e8417c4c395e3922d12abfd956b93b71121976Jean-Luc Brouillet#endif  // ANDROID_ML_NN_RUNTIME_EXECUTION_PLAN_H
243