alibaba / MNN

MNN is a blazing fast, lightweight deep learning framework, battle-tested by business-critical use cases in Alibaba
http://www.mnn.zone/
8.72k stars 1.67k forks source link

tensorflow模型转为mnn格式,用fastTestTf.py工具测试是success,但是用c++跑每次结果都不一样 #1867

Closed Richard-coder closed 1 year ago

Richard-coder commented 2 years ago

平台(如果交叉编译请再附上交叉编译目标平台):

ubuntu x86 cpu:

Github版本:

Github Version: 1.2和 master, master 的commit id 是 344629419f710b39559e616f1af7bb7bd29617db

编译方式:

Compiling cmake

tensorflow模型转为mnn格式,用fastTestTf.py工具测试是success,但是用c++跑每次结果都不一样

因为模型是tf 1.6写的,所以我对fastTestTf.py脚本做了一些修改,对结果没影响

模型地址 链接:https://pan.baidu.com/s/11Eip1A2kRamT4n_G5q40dA 提取码:9i0g

c++测试代码

#include "Backend.hpp"
#include "Interpreter.hpp"
#include "MNNDefine.h"
#include "Interpreter.hpp"
#include "Tensor.hpp"
#include <math.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <math.h>
#include "tic_toc.h"
using namespace MNN;
using namespace cv;

int main()
{
  cv::Mat src=cv::imread("/home/zwz/place_recognition/code_reference/netvlad_tf_open-master/demo/query/query1.jpg", 1);
  //cv::Mat src=cv::imread("/home/zwz/place_recognition/data/lenovo_data_simple/query/09/599160053306.png", 1);
  cv::cvtColor(src, src, cv::COLOR_BGR2GRAY);
  if(src.empty()) return -1;
  int forward = MNN_FORWARD_CPU;
  int precision  = 1;
  int power      = 1;
  int memory     = 1;
  ////int threads    = 1;
  ////int INPUT_SIZE = 28;
  // 1. 创建Interpreter, 通过磁盘文件创建: static Interpreter* createFromFile(const char* file);
  std::shared_ptr<Interpreter> net(Interpreter::createFromFile("/home/zwz/Downloads/MNN_1_2_0/build/freeze.mnn"));
  MNN::ScheduleConfig config;
  // 2. 调度配置,
  // numThread决定并发数的多少,但具体线程数和并发效率,不完全取决于numThread
  // 推理时,主选后端由type指定,默认为CPU。在主选后端不支持模型中的算子时,启用由backupType指定的备选后端。
  ////config.numThread = threads;
  config.type      = static_cast<MNNForwardType>(forward);
  MNN::BackendConfig backendConfig;
  // 3. 后端配置
  // memory、power、precision分别为内存、功耗和精度偏好
  backendConfig.precision = (MNN::BackendConfig::PrecisionMode)precision;
  backendConfig.power = (MNN::BackendConfig::PowerMode) power;
  backendConfig.memory = (MNN::BackendConfig::MemoryMode) memory;
  config.backendConfig = &backendConfig;
  // 4. 创建session
  auto session = net->createSession(config);

  // preprocessing
  int raw_image_height = src.rows;
  int raw_image_width  = src.cols;
  // 5. 输入数据
  // wrapping input tensor, convert nhwc to nchw
  TicToc time_1;
  time_1.tic();
  std::vector<int> dims{1, raw_image_height, raw_image_width, 1};
  auto nhwc_Tensor = MNN::Tensor::create<float>(dims, NULL, MNN::Tensor::TENSORFLOW);
  auto nhwc_data   = nhwc_Tensor->host<float>();
  auto nhwc_size   = nhwc_Tensor->size();
  ::memcpy(nhwc_data, src.data, nhwc_size);

  std::string input_tensor = "image";
  // 获取输入tensor
  // 拷贝数据, 通过这类拷贝数据的方式,用户只需要关注自己创建的tensor的数据布局,
  // copyFromHostTensor会负责处理数据布局上的转换(如需)和后端间的数据拷贝(如需)。
  auto inputTensor  = net->getSessionInput(session, nullptr);
  inputTensor->copyFromHostTensor(nhwc_Tensor);

  net->resizeTensor(inputTensor, dims);
  net->resizeSession(session);
  net->releaseModel();
  // 6. 运行会话
  net->runSession(session);

  // 7. 获取输出
  std::string output_tensor_name0 = "pred/l2_normalize";
  // 获取输出tensor
  MNN::Tensor *tensor_scores  = net->getSessionOutput(session, output_tensor_name0.c_str());

  MNN::Tensor tensor_scores_host(tensor_scores, tensor_scores->getDimensionType());
  // 拷贝数据
  tensor_scores->copyToHostTensor(&tensor_scores_host);
  std::cout<<time_1.toc()<<std::endl;
  // post processing steps
  auto scores_dataPtr  = tensor_scores_host.host<float>();
  for (int i = 0; i < 4096; ++i)
  {
    float val = scores_dataPtr[i];

  }
  std::cout<<scores_dataPtr[0]<<std::endl;
  std::cout<<scores_dataPtr[1]<<std::endl;
  std::cout<<scores_dataPtr[2]<<std::endl;

  return 0;
}
wangzhaode commented 2 years ago

fastTestTf.py实际调用的是TeseConvertResult.out, 也是用C++写的推理,你仔细对比一下看看自己实现是否有错误