From f9a1c5ec48d61a8514d72586d1591307b7b09200 Mon Sep 17 00:00:00 2001 From: xiaying Date: Thu, 8 Aug 2024 16:57:10 +0800 Subject: [PATCH 1/4] MNN:Bugfix: Fix bug for issue 2967 --- source/core/TensorUtils.cpp | 14 +++++++++++ test/core/RegionFuse.cpp | 2 +- test/op/SplitTest.cpp | 48 +++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/source/core/TensorUtils.cpp b/source/core/TensorUtils.cpp index 587d0c170..c67cd077c 100644 --- a/source/core/TensorUtils.cpp +++ b/source/core/TensorUtils.cpp @@ -538,10 +538,24 @@ static bool _ClipDst(int* stride, int srcOffset, int dstOffset, const int* srcSi if (0 != srcOffset || 0 != dstOffset) { return false; } + int srcMax = 0; for (int i=0; i()); + input->setName("input"); + // set input data + auto size = input->getInfo()->size; + auto iptr = input->writeMap(); + for (int i=0; iunMap(); + auto inputTran = _Reshape(_Transpose(input, {0, 2, 1}), {8, 9}, NCHW); + std::vector startDims = {1, 0}; + std::vector sizeDims = {4, 9}; + auto start = _Const(startDims.data(), {2}, NCHW, halide_type_of()); + auto sizeVar = _Const(sizeDims.data(), {2}, NCHW, halide_type_of()); + + auto output = _Slice(inputTran, start, sizeVar); + auto oinfo = output->getInfo(); + if (oinfo->dim.size() != 2) { + FUNC_PRINT(1); + return false; + } + if (oinfo->dim[1] != 9 || oinfo->dim[0] != 4) { + FUNC_PRINT(1); + return false; + } + auto optr = output->readMap(); + for (int i=0; i<4; ++i) { + for (int j=0; j<9; ++j) { + int expect = (i+1)*10+j; + int compute = optr[i*9+j]; + if (expect != compute) { + MNN_ERROR("Error for i=%d - j=%d, %d:%d\n", i, j, expect, compute); + return false; + } + } + } + return true; + } +}; +MNNTestSuiteRegister(SliceTest, "op/slice"); From db538226d5f95b690dd817467d4d8be6122674dc Mon Sep 17 00:00:00 2001 From: xiaying Date: Thu, 8 Aug 2024 17:00:35 +0800 Subject: [PATCH 2/4] MNN:Bugfix: Fix bug for metal and vulkan-buffer's batchmatmul run extra l time --- source/backend/metal/MetalLoop.mm | 3 +-- source/backend/vulkan/buffer/execution/VulkanLoop.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/source/backend/metal/MetalLoop.mm b/source/backend/metal/MetalLoop.mm index be64819ff..8f51e8622 100644 --- a/source/backend/metal/MetalLoop.mm +++ b/source/backend/metal/MetalLoop.mm @@ -215,7 +215,6 @@ virtual ErrorCode onResize(const std::vector& inputs, const std::vecto auto AStride = cmd->view()->GetAs(1)->stride()->data(); auto BStride = cmd->view()->GetAs(2)->stride()->data(); auto OStride = cmd->view()->GetAs(0)->stride()->data(); - int totalSize = mLoop->loopNumber() * size[0] * size[1] * size[2]; auto param = reinterpret_cast([mParam contents]); param->size[3] = mLoop->loopNumber(); for (int i=0; i<3; ++i) { @@ -240,7 +239,7 @@ virtual void onEncode(const std::vector &inputs, const std::vectorview()->GetAs(1)->stride()->data(); auto BStride = cmd->view()->GetAs(2)->stride()->data(); auto OStride = cmd->view()->GetAs(0)->stride()->data(); - int totalSize = mLoop->loopNumber() * size[0] * size[1] * size[2]; + size_t totalSize = mLoop->loopNumber() * size[0] * size[2]; [encoder setComputePipelineState:mPipeline]; for (int i=0; iindexes()->size(); ++i) { MetalBackend::setTensor(mTensors[cmd->indexes()->data()[i]], encoder, i); diff --git a/source/backend/vulkan/buffer/execution/VulkanLoop.cpp b/source/backend/vulkan/buffer/execution/VulkanLoop.cpp index 38ac9451e..a696d4360 100644 --- a/source/backend/vulkan/buffer/execution/VulkanLoop.cpp +++ b/source/backend/vulkan/buffer/execution/VulkanLoop.cpp @@ -62,7 +62,7 @@ class VulkanBatchMatMul : public VulkanBasicExecution { auto AStride = cmd->view()->GetAs(1)->stride()->data(); auto BStride = cmd->view()->GetAs(2)->stride()->data(); auto OStride = cmd->view()->GetAs(0)->stride()->data(); - int totalSize = mLoop->loopNumber() * size[0] * size[1] * size[2]; + int totalSize = mLoop->loopNumber() * size[0] * size[2]; auto param = reinterpret_cast(mParam->map()); param->size[3] = mLoop->loopNumber(); auto vkBn = static_cast(backend()); From b4e140e46f907935d3b7f03ab475730df26cab63 Mon Sep 17 00:00:00 2001 From: xiaying Date: Thu, 8 Aug 2024 20:03:53 +0800 Subject: [PATCH 3/4] Android:Bugfix: Fix bug for cmake error for ndk 27 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b85353bb3..006ae131f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.6) # Versioning stuff file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/include/MNN/MNNDefine.h" MNN_DEFINE) string(REGEX MATCH "MNN_VERSION_MAJOR [0-9]+" MNN_VERSION_MAJOR_DEFINE ${MNN_DEFINE}) From 88394677fe8e30eb0fcc3dabe11199ef5b33f745 Mon Sep 17 00:00:00 2001 From: xiaying Date: Thu, 8 Aug 2024 20:23:13 +0800 Subject: [PATCH 4/4] Tools:Bugfix: Revert modelCompare --- tools/cpp/CMakeLists.txt | 3 + tools/cpp/modelCompare.cpp | 266 +++++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 tools/cpp/modelCompare.cpp diff --git a/tools/cpp/CMakeLists.txt b/tools/cpp/CMakeLists.txt index eca3a884a..134340106 100644 --- a/tools/cpp/CMakeLists.txt +++ b/tools/cpp/CMakeLists.txt @@ -16,6 +16,9 @@ list(APPEND MNN_CPP_TOOLS SequenceModuleTest.out) add_executable(mergeInplaceForCPU ${CMAKE_CURRENT_LIST_DIR}/mergeInplaceForCPU.cpp) list(APPEND MNN_CPP_TOOLS mergeInplaceForCPU) +add_executable(modelCompare.out ${CMAKE_CURRENT_LIST_DIR}/modelCompare.cpp) +list(APPEND MNN_CPP_TOOLS modelCompare.out) + add_executable(MNNV2Basic.out ${CMAKE_CURRENT_LIST_DIR}/MNNV2Basic.cpp) list(APPEND MNN_CPP_TOOLS MNNV2Basic.out) if (MNN_USE_SSE) diff --git a/tools/cpp/modelCompare.cpp b/tools/cpp/modelCompare.cpp new file mode 100644 index 000000000..e86fc3e2b --- /dev/null +++ b/tools/cpp/modelCompare.cpp @@ -0,0 +1,266 @@ +// +// modelCompare.cpp +// MNN +// +// Created by MNN on 2019/01/22. +// Copyright © 2018, Alibaba Group Holding Limited +// + +#define MNN_OPEN_TIME_TRACE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core/TensorUtils.hpp" +#include "rapidjson/document.h" + +template +inline T stringConvert(const char* number) { + std::istringstream os(number); + T v; + os >> v; + return v; +} + +using namespace MNN; + +static void compareNet(Interpreter* net, Interpreter* net2, MNNForwardType expectType, float tolerance, + const std::map>& inputs, const std::string& stopOp, BackendConfig::PrecisionMode precision, int modeNum) { + std::vector> correctResult; + int index; + MNN::ScheduleConfig expectConfig; + BackendConfig backendConfig; + backendConfig.precision = precision; + expectConfig.type = expectType; + expectConfig.backendConfig = &backendConfig; + expectConfig.mode = modeNum; + auto expectSession = net->createSession(expectConfig); + auto compareSession = net2->createSession(expectConfig); + + bool allCorrect = true; + + MNN::TensorCallBackWithInfo beginCallBack = [&](const std::vector& t, const OperatorInfo* op) { + if (op->name() == stopOp) { + return false; + } + return true; + }; + MNN::TensorCallBackWithInfo saveExpect = [&](const std::vector& t, const OperatorInfo* op) { + if (op->name() == stopOp) { + return false; + } + if (op->type() == "Raster") { + return true; + } + for (int i=0; ielementSize() <= 0) { + return true; + } + if (tensor->buffer().device == 0 && tensor->buffer().host == nullptr) { + return true; + } + std::shared_ptr copyTensor(MNN::Tensor::createHostTensorFromDevice(tensor, true)); + correctResult.emplace_back(copyTensor); + } + return true; + }; + MNN::TensorCallBackWithInfo compareExpect = [&](const std::vector& t, const OperatorInfo* op) { + if (op->name() == stopOp) { + return false; + } + if (op->type() == "Raster") { + return true; + } + for (int i=0; ielementSize() <= 0) { + return true; + } + if (tensor->buffer().device == 0 && tensor->buffer().host == nullptr) { + return true; + } + std::shared_ptr copyTensor(MNN::Tensor::createHostTensorFromDevice(tensor, true)); + auto expectTensor = correctResult[index++]; + auto correct = TensorUtils::compareTensors(copyTensor.get(), expectTensor.get(), tolerance, true); + if (!correct) { + MNN_PRINT("%s - %d is error\n", op->name().c_str(), i); + allCorrect = false; + } + } + return allCorrect; + }; + + for (auto& iter : inputs) { + Tensor* expectInput = net->getSessionInput(expectSession, iter.first.empty() ? NULL : iter.first.c_str()); + expectInput->copyFromHostTensor(iter.second.get()); + Tensor* compareInput = net->getSessionInput(compareSession, iter.first.empty() ? NULL : iter.first.c_str()); + compareInput->copyFromHostTensor(iter.second.get()); + } + correctResult.clear(); + net->runSessionWithCallBackInfo(expectSession, beginCallBack, saveExpect); + index = 0; + net2->runSessionWithCallBackInfo(compareSession, beginCallBack, compareExpect); + if (allCorrect) { + MNN_PRINT("Correct ! Run second pass\n"); + } else { + return; + } + index = 0; + for (auto& iter : inputs) { + Tensor* compareInput = net->getSessionInput(compareSession, iter.first.empty() ? NULL : iter.first.c_str()); + compareInput->copyFromHostTensor(iter.second.get()); + } + net2->runSessionWithCallBackInfo(compareSession, beginCallBack, compareExpect); + if (allCorrect) { + MNN_PRINT("Correct !\n"); + } +} + +int main(int argc, const char* argv[]) { + if (argc < 3) { + MNN_PRINT("Usage: ./modelCompare.out origin.mnn origin_quant.mnn [0.05]"); + } + // read args + std::string cmd = argv[0]; + std::string pwd = "./"; + auto rslash = cmd.rfind("/"); + if (rslash != std::string::npos) { + pwd = cmd.substr(0, rslash + 1); + } + + const char* fileName = argv[1]; + + const char* compareFileName = argv[2]; + + float tolerance = 0.05f; + if (argc > 3) { + tolerance = stringConvert(argv[3]); + } + MNN_PRINT("Tolerance Rate: %f\n", tolerance); + + // create net + MNN_PRINT("Open Model %s, %s\n", fileName, compareFileName); + std::shared_ptr net = + std::shared_ptr(MNN::Interpreter::createFromFile(fileName)); + net->setSessionMode(Interpreter::Session_Debug); + std::shared_ptr net2 = + std::shared_ptr(MNN::Interpreter::createFromFile(compareFileName)); + net2->setSessionMode(Interpreter::Session_Debug); + + // create session for get input info + ScheduleConfig config; + config.type = MNN_FORWARD_CPU; + auto session = net->createSession(config); + + std::map> inputs; + std::vector inputNames; + do { + rapidjson::Document document; + std::ostringstream jsonNameOs; + jsonNameOs << pwd << "/input.json"; + std::ifstream fileNames(jsonNameOs.str().c_str()); + if (fileNames.fail()) { + break; + } + std::ostringstream output; + output << fileNames.rdbuf(); + auto outputStr = output.str(); + document.Parse(outputStr.c_str()); + if (document.HasParseError()) { + MNN_ERROR("Invalid json\n"); + break; + } + 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); + } + } + } while (false); + if (!inputNames.empty()) { + MNN_PRINT("Find input.json, use inputs:"); + for (auto& n : inputNames) { + MNN_PRINT(" %s, ", n.c_str()); + } + MNN_PRINT("\n"); + for (auto name : inputNames) { + auto inputTensor = net->getSessionInput(session, name.c_str()); + std::shared_ptr givenTensor(new Tensor(inputTensor, inputTensor->getDimensionType())); + { + std::ostringstream fileName; + fileName << pwd << name << ".txt"; + std::ifstream input(fileName.str().c_str()); + MNN_ASSERT(!input.fail()); + + int size_w = inputTensor->width(); + int size_h = inputTensor->height(); + int bpp = inputTensor->channel(); + int batch = inputTensor->batch(); + // auto backend = net->getBackend(session, inputTensor); + // MNN_ASSERT(!input.fail()); + MNN_PRINT("Input: %d,%d,%d,%d\n", size_w, size_h, bpp, batch); + auto inputData = givenTensor->host(); + auto size = givenTensor->size() / sizeof(float); + for (int i = 0; i < size; ++i) { + input >> inputData[i]; + } + inputs.insert(std::make_pair(name, givenTensor)); + } + + } + } else { + auto inputTensor = net->getSessionInput(session, NULL); + std::shared_ptr givenTensor(new Tensor(inputTensor, inputTensor->getDimensionType())); + { + std::ostringstream fileName; + fileName << pwd << "input_0" + << ".txt"; + std::ifstream input(fileName.str().c_str()); + + int size_w = inputTensor->width(); + int size_h = inputTensor->height(); + int bpp = inputTensor->channel(); + int batch = inputTensor->batch(); + // auto backend = net->getBackend(session, inputTensor); + // MNN_ASSERT(!input.fail()); + MNN_PRINT("Input: %d,%d,%d,%d\n", size_w, size_h, bpp, batch); + auto inputData = givenTensor->host(); + auto size = givenTensor->size() / sizeof(float); + for (int i = 0; i < size; ++i) { + input >> inputData[i]; + } + inputs.insert(std::make_pair("", givenTensor)); + } + } + net->releaseSession(session); + BackendConfig::PrecisionMode precision = BackendConfig::Precision_Normal; + if (argc > 4) { + precision = (BackendConfig::PrecisionMode)atoi(argv[4]); + } + FUNC_PRINT(precision); + int modeNum = 1; + if(argc > 5) { + modeNum = atoi(argv[5]);//set gpu mode + } + FUNC_PRINT(modeNum); + std::string stopOp = ""; + if (argc > 6) { + stopOp = argv[6]; + } + FUNC_PRINT_ALL(stopOp.c_str(), s); + compareNet(net.get(), net2.get(), MNN_FORWARD_CPU, tolerance, inputs, stopOp, precision, modeNum); + + return 0; +}