int main()

in tools/cpp/SequenceModuleTest.cpp [96:392]


int main(int argc, char *argv[]) {
    if (argc < 5) {
        MNN_ERROR("Usage: ./SequenceModuleTest.out ${test.mnn} [forwardType] [shapeMutable] ${testTime} ${Dir} ${Dir1} ......\n");
        return 0;
    }
#ifdef OPEN_TRACE
    _initTensorStatic();
#endif

    std::string modelName = argv[1];
    auto type = (MNNForwardType)atoi(argv[2]);
    int numberThread = atoi(argv[3]);
    int testTime = atoi(argv[4]);
    int offset = 5;
    MNN_PRINT("Test %s, type = %d\n", modelName.c_str(), type);
    // create session
    MNN::ScheduleConfig config;
    config.type      = type;
    /*modeNum means gpuMode for GPU usage, Or means numThread for CPU usage.*/
    // If type not fount, let it failed
    config.backupType = type;
    config.numThread = numberThread;
    BackendConfig backendConfig;
#ifdef OPEN_TRACE
    backendConfig.precision = MNN::BackendConfig::Precision_High;
#endif
    config.backendConfig     = &backendConfig;
    
    MNN::Express::Module::Config mConfig;
    mConfig.shapeMutable = true;
    mConfig.rearrange = true;
    std::shared_ptr<Executor::RuntimeManager> rtmgr(Executor::RuntimeManager::createRuntimeManager(config));
#ifdef OPEN_TRACE
    rtmgr->setMode(MNN::Interpreter::Session_Debug);
#endif
    std::shared_ptr<Module> net;
    for (int index = offset; index < argc; ++index) {
        std::string directName = argv[index];
        rapidjson::Document document;
        std::map<std::string, float> inputInfo;
        std::map<std::string, std::vector<int>> inputShape;
        std::vector<std::string> inputNames;
        std::vector<std::string> outputNames;
        std::ostringstream jsonNameOs;
        jsonNameOs << argv[index] << "/input.json";
        std::ifstream fileNames(jsonNameOs.str().c_str());
        std::ostringstream output;
        output << fileNames.rdbuf();
        auto outputStr = output.str();
        document.Parse(outputStr.c_str());
        if (document.HasParseError()) {
            MNN_ERROR("Invalid json\n");
            continue;
        }
        if (document.HasMember("inputs")) {
            auto inputsInfo = document["inputs"].GetArray();
            for (auto iter = inputsInfo.begin(); iter !=inputsInfo.end(); iter++) {
                auto obj = iter->GetObject();
                std::string name = obj["name"].GetString();
                inputNames.emplace_back(name);
                MNN_PRINT("%s\n", name.c_str());
                if (obj.HasMember("value")) {
                    float value = obj["value"].GetFloat();
                    inputInfo.insert(std::make_pair(name, value));
                }
                if (obj.HasMember("shape")) {
                    auto dims = obj["shape"].GetArray();
                    std::vector<int> shapes;
                    for (auto iter = dims.begin(); iter != dims.end(); iter++) {
                        shapes.emplace_back(iter->GetInt());
                    }
                    inputShape.insert(std::make_pair(name, shapes));
                }
            }
        }
        if (document.HasMember("outputs")) {
            auto array = document["outputs"].GetArray();
            for (auto iter = array.begin(); iter !=array.end(); iter++) {
                std::string name = iter->GetString();
                MNN_PRINT("output: %s\n", name.c_str());
                outputNames.emplace_back(name);
            }
        }
        if (nullptr == net.get()) {
            net.reset(Module::load(inputNames, outputNames, modelName.c_str(), rtmgr, &mConfig));
            if (net == nullptr) {
                MNN_PRINT("Error: can't load module\n");
                return 0;
            }
            break;
        }
    }
    net->traceOrOptimize(MNN::Interpreter::Session_Resize_Check);

    // First Test
    auto testCorrect = [&]() {
        std::vector<bool> correctInputs(argc-offset);
        for (int index = offset; index < argc; ++index) {
            MNN_PRINT("Test for %s\n", argv[index]);
            std::string directName = argv[index];
            rapidjson::Document document;
            std::map<std::string, float> inputInfo;
            std::map<std::string, std::vector<int>> inputShape;
            std::vector<std::string> inputNames;
            std::vector<std::string> outputNames;
            std::ostringstream jsonNameOs;
            jsonNameOs << argv[index] << "/input.json";
            std::ifstream fileNames(jsonNameOs.str().c_str());
            std::ostringstream output;
            output << fileNames.rdbuf();
            auto outputStr = output.str();
            document.Parse(outputStr.c_str());
            if (document.HasParseError()) {
                MNN_ERROR("Invalid json\n");
                continue;
            }
            if (document.HasMember("inputs")) {
                auto inputsInfo = document["inputs"].GetArray();
                for (auto iter = inputsInfo.begin(); iter !=inputsInfo.end(); iter++) {
                    auto obj = iter->GetObject();
                    std::string name = obj["name"].GetString();
                    inputNames.emplace_back(name);
                    MNN_PRINT("%s\n", name.c_str());
                    if (obj.HasMember("value")) {
                        float value = obj["value"].GetFloat();
                        inputInfo.insert(std::make_pair(name, value));
                    }
                    if (obj.HasMember("shape")) {
                        auto dims = obj["shape"].GetArray();
                        std::vector<int> shapes;
                        for (auto iter = dims.begin(); iter != dims.end(); iter++) {
                            shapes.emplace_back(iter->GetInt());
                        }
                        inputShape.insert(std::make_pair(name, shapes));
                    }
                }
            }
            if (document.HasMember("outputs")) {
                auto array = document["outputs"].GetArray();
                for (auto iter = array.begin(); iter !=array.end(); iter++) {
                    std::string name = iter->GetString();
                    MNN_PRINT("output: %s\n", name.c_str());
                    outputNames.emplace_back(name);
                }
            }
            auto mInfo = net->getInfo();

            std::vector<VARP> inputs(mInfo->inputs.size());
            for (int i=0; i<inputs.size(); ++i) {
                inputs[i] = _Input(mInfo->inputs[i].dim, mInfo->inputs[i].order, mInfo->inputs[i].type);
            }
            // Load inputs
            for (int i=0; i<inputs.size(); ++i) {
                auto inputName = inputNames[i];
                // Resize
                auto shapeIter = inputShape.find(inputName);
                if (shapeIter != inputShape.end()) {
                    auto s = shapeIter->second;
                    inputs[i] = _Input(s, mInfo->defaultFormat, mInfo->inputs[i].type);
                }
                auto info = inputs[i]->getInfo();
                if (info->type == halide_type_of<float>()){
                    auto ptr = inputs[i]->writeMap<float>();
                    LOAD_DATA(float)
                } else {
                    auto floatVar = _Input(info->dim, info->order, halide_type_of<float>());
                    auto ptr = floatVar->writeMap<float>();
                    LOAD_DATA(float)
                    auto temp = _Cast(floatVar, info->type);
                    inputs[i]->input(temp);
                }
                inputs[i] = _Convert(inputs[i], mInfo->inputs[i].order);
            }
            bool modelError = false;
            // Module Branch
            auto outputs = net->onForward(inputs);
            for (int i=0; i<outputNames.size(); ++i) {
                auto output = outputs[i];
                bool success = compareOutput(output, directName, outputNames[i], mInfo->defaultFormat, i);
                if (!success) {
                    modelError = true;
                    MNN_ERROR("Error for output %s\n", outputNames[i].c_str());
                }
            }
            correctInputs[index-offset] = !modelError;
        }
        return correctInputs;
    };
    auto correctInfo = testCorrect();
    MNN_PRINT("Resize optimize for net\n");
    net->traceOrOptimize(MNN::Interpreter::Session_Resize_Fix);
    auto optCorrectInfo = testCorrect();
    for (int i=0; i<correctInfo.size(); ++i) {
        MNN_PRINT("Correct Json %d: before opt: %d, after opt: %d\n", i, (int)correctInfo[i], (int)optCorrectInfo[i]);
    }
    if (testTime > 0) {
        MNN_PRINT("Test Speed for %d times\n", testTime);
        // Prepare All Input
        std::vector<std::vector<MNN::Express::VARP>> allInputs;
        for (int index = offset; index < argc; ++index) {
            std::string directName = argv[index];
            rapidjson::Document document;
            std::map<std::string, float> inputInfo;
            std::map<std::string, std::vector<int>> inputShape;
            std::vector<std::string> inputNames;
            std::vector<std::string> outputNames;
            std::ostringstream jsonNameOs;
            jsonNameOs << argv[index] << "/input.json";
            std::ifstream fileNames(jsonNameOs.str().c_str());
            std::ostringstream output;
            output << fileNames.rdbuf();
            auto outputStr = output.str();
            document.Parse(outputStr.c_str());
            if (document.HasParseError()) {
                MNN_ERROR("Invalid json\n");
                continue;
            }
            if (document.HasMember("inputs")) {
                auto inputsInfo = document["inputs"].GetArray();
                for (auto iter = inputsInfo.begin(); iter !=inputsInfo.end(); iter++) {
                    auto obj = iter->GetObject();
                    std::string name = obj["name"].GetString();
                    inputNames.emplace_back(name);
                    if (obj.HasMember("value")) {
                        float value = obj["value"].GetFloat();
                        inputInfo.insert(std::make_pair(name, value));
                    }
                    if (obj.HasMember("shape")) {
                        auto dims = obj["shape"].GetArray();
                        std::vector<int> shapes;
                        for (auto iter = dims.begin(); iter != dims.end(); iter++) {
                            shapes.emplace_back(iter->GetInt());
                        }
                        inputShape.insert(std::make_pair(name, shapes));
                    }
                }
            }
            if (document.HasMember("outputs")) {
                auto array = document["outputs"].GetArray();
                for (auto iter = array.begin(); iter !=array.end(); iter++) {
                    std::string name = iter->GetString();
                    outputNames.emplace_back(name);
                }
            }
            auto mInfo = net->getInfo();
            
            std::vector<VARP> inputs(mInfo->inputs.size());
            for (int i=0; i<inputs.size(); ++i) {
                inputs[i] = _Input(mInfo->inputs[i].dim, mInfo->inputs[i].order, mInfo->inputs[i].type);
            }
            // Load inputs
            for (int i=0; i<inputs.size(); ++i) {
                auto inputName = inputNames[i];
                // Resize
                auto shapeIter = inputShape.find(inputName);
                if (shapeIter != inputShape.end()) {
                    auto s = shapeIter->second;
                    inputs[i] = _Input(s, mInfo->defaultFormat, mInfo->inputs[i].type);
                }
                auto info = inputs[i]->getInfo();
                if (info->type == halide_type_of<float>()){
                    auto ptr = inputs[i]->writeMap<float>();
                    LOAD_DATA(float)
                } else {
                    auto floatVar = _Input(info->dim, info->order, halide_type_of<float>());
                    auto ptr = floatVar->writeMap<float>();
                    LOAD_DATA(float)
                    auto temp = _Cast(floatVar, info->type);
                    inputs[i]->input(temp);
                }
                inputs[i] = _Convert(inputs[i], mInfo->inputs[i].order);
                inputs[i].fix(VARP::CONSTANT);
            }
            allInputs.emplace_back(inputs);
        }
        std::vector<float> times(testTime, 0.0f);
        for (int t=0; t<testTime; ++t) {
            Timer _l;
            for (auto& v : allInputs) {
                auto output = net->onForward(v);
                for (auto o : output) {
                    ((MNN::Tensor*)o->getTensor())->wait(MNN::Tensor::MAP_TENSOR_READ, true);
                }
            }
            times[t] = _l.durationInUs() / 1000.0f;
        }
        auto minTime = std::min_element(times.begin(), times.end());
        auto maxTime = std::max_element(times.begin(), times.end());
        float sum    = 0.0f;
        for (auto time : times) {
            sum += time;
        }
        MNN_PRINT("Avg= %f ms, min= %f ms, max= %f ms\n", sum / (float)testTime, *minTime, *maxTime);
    }

    return 0;
}