2019-04-17 10:49:11 +08:00
|
|
|
//
|
|
|
|
// writeFb.cpp
|
|
|
|
// MNNConverter
|
|
|
|
//
|
|
|
|
// Created by MNN on 2019/01/31.
|
|
|
|
// Copyright © 2018, Alibaba Group Holding Limited
|
|
|
|
//
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
2019-11-15 14:22:45 +08:00
|
|
|
#include <set>
|
2019-04-17 10:49:11 +08:00
|
|
|
|
2019-11-15 14:22:45 +08:00
|
|
|
#include "MNN_generated.h"
|
|
|
|
#include "half.hpp"
|
2019-07-11 13:56:52 +08:00
|
|
|
#include "logkit.h"
|
|
|
|
#include "writeFb.hpp"
|
2019-04-17 10:49:11 +08:00
|
|
|
|
2019-11-15 14:22:45 +08:00
|
|
|
int writeFb(std::unique_ptr<MNN::NetT>& netT, const std::string& MNNModelFile, bool benchmarkModel,
|
|
|
|
bool saveHalfFloat) {
|
2019-04-17 10:49:11 +08:00
|
|
|
if (benchmarkModel) {
|
|
|
|
for (auto& op : netT->oplists) {
|
|
|
|
const auto opType = op->type;
|
|
|
|
switch (opType) {
|
|
|
|
case MNN::OpType_Convolution:
|
|
|
|
case MNN::OpType_Deconvolution:
|
|
|
|
case MNN::OpType_ConvolutionDepthwise: {
|
|
|
|
auto param = op->main.AsConvolution2D();
|
|
|
|
param->weight.clear();
|
|
|
|
param->bias.clear();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MNN::OpType_TfQuantizedConv2D: {
|
|
|
|
auto param = op->main.AsTfQuantizedConv2D();
|
|
|
|
param->weight.clear();
|
|
|
|
param->bias.clear();
|
|
|
|
}
|
|
|
|
case MNN::OpType_MatMul: {
|
|
|
|
auto param = op->main.AsMatMul();
|
|
|
|
param->weight.clear();
|
|
|
|
param->bias.clear();
|
|
|
|
}
|
|
|
|
case MNN::OpType_BatchNorm: {
|
|
|
|
auto param = op->main.AsBatchNorm();
|
|
|
|
param->slopeData.clear();
|
|
|
|
param->meanData.clear();
|
|
|
|
param->varData.clear();
|
|
|
|
param->biasData.clear();
|
|
|
|
param->Adata.clear();
|
|
|
|
param->Bdata.clear();
|
|
|
|
}
|
|
|
|
case MNN::OpType_Scale: {
|
|
|
|
auto param = op->main.AsScale();
|
|
|
|
param->scaleData.clear();
|
|
|
|
param->biasData.clear();
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-15 14:22:45 +08:00
|
|
|
|
|
|
|
if (saveHalfFloat) {
|
|
|
|
for (auto& op : netT->oplists) {
|
|
|
|
const auto opType = op->type;
|
|
|
|
switch (opType) {
|
2020-03-22 20:16:29 +08:00
|
|
|
case MNN::OpType_Convolution:
|
|
|
|
case MNN::OpType_ConvolutionDepthwise: {
|
2019-11-15 14:22:45 +08:00
|
|
|
auto param = op->main.AsConvolution2D();
|
2020-07-16 17:56:21 +08:00
|
|
|
if (param->quanParameter.get() == nullptr) {
|
|
|
|
const int weightSize = param->weight.size();
|
|
|
|
// const int biasSize = param->bias.size();
|
|
|
|
std::vector<half_float::half> quantizedFp16Weight;
|
|
|
|
quantizedFp16Weight.resize(weightSize);
|
|
|
|
std::transform(param->weight.begin(), param->weight.end(), quantizedFp16Weight.begin(),
|
|
|
|
[](float w) { return half_float::half(w); });
|
|
|
|
// std::vector<half_float::half> quantizedFp16Bias;
|
|
|
|
// quantizedFp16Bias.resize(biasSize);
|
|
|
|
// std::transform(param->bias.begin(), param->bias.end(), quantizedFp16Bias.begin(), [](float
|
|
|
|
// b){return half_float::half(b); });
|
|
|
|
param->weight.clear();
|
|
|
|
// param->bias.clear();
|
2019-11-15 14:22:45 +08:00
|
|
|
|
2020-07-16 17:56:21 +08:00
|
|
|
param->quanParameter.reset(new MNN::IDSTQuanT);
|
|
|
|
param->quanParameter->type = 3;
|
|
|
|
int8_t* halfWeight = reinterpret_cast<int8_t*>(quantizedFp16Weight.data());
|
|
|
|
param->quanParameter->buffer.assign(halfWeight, halfWeight + sizeof(half_float::half) * weightSize);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MNN::OpType_Const: {
|
|
|
|
auto blob = op->main.AsBlob();
|
|
|
|
if (blob->dataType == MNN::DataType_DT_FLOAT) {
|
|
|
|
blob->dataType = MNN::DataType_DT_HALF;
|
|
|
|
blob->uint8s.resize(sizeof(half_float::half) * blob->float32s.size());
|
|
|
|
auto size = blob->float32s.size();
|
|
|
|
auto dst = (half_float::half*)blob->uint8s.data();
|
|
|
|
for (int i=0; i<size; ++i) {
|
|
|
|
dst[i] = blob->float32s[i];
|
|
|
|
}
|
|
|
|
blob->float32s.clear();
|
|
|
|
}
|
2019-11-15 14:22:45 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
- build:
- unify schema building in core and converter;
- add more build script for android;
- add linux build script for python;
- ops impl:
- add floor mod support in binary;
- use eltwise impl in add/max/sub/mul binary for optimization;
- remove fake double support in cast;
- fix 5d support for concat;
- add adjX and adjY support for batch matmul;
- optimize conv2d back prop filter;
- add pad mode support for conv3d;
- fix bug in conv2d & conv depthwise with very small feature map;
- optimize binary without broacast;
- add data types support for gather;
- add gather ND support;
- use uint8 data type in gather v2;
- add transpose support for matmul;
- add matrix band part;
- add dim != 4 support for padding, reshape & tensor convert;
- add pad type support for pool3d;
- make ops based on TensorFlow Lite quantization optional;
- add all & any support for reduction;
- use type in parameter as output type in reduction;
- add int support for unary;
- add variable weight support for conv2d;
- fix conv2d depthwise weights initialization;
- fix type support for transpose;
- fix grad outputs count for reduce grad and reshape grad;
- fix priorbox & detection output;
- fix metal softmax error;
- python:
- add runSessionWithCallBackInfo interface;
- add max nodes limit (1400) for visualization tool;
- fix save error in python3;
- align default dim;
- convert:
- add extra design for optimization;
- add more post converting optimizers;
- add caffe v1 weights blob support;
- add cast, unary, conv transpose support for onnx model;
- optimize batchnorm, conv with variable weights, prelu, reshape, slice, upsample for onnx model;
- add cos/sin/atan/tan support for unary for tensorflow model;
- add any/all support for reduction for tensorflow model;
- add elu, conv3d, pool3d support for tensorflow model;
- optimize argmax, batchnorm, concat, batch to space, conv with variable weights, prelu, slice for tensorflow model;
- others:
- fix size computer lock;
- fix thread pool deadlock;
- add express & parameters in express;
- rewrite blitter chooser without static map;
- add tests for expr;
2019-10-29 13:37:26 +08:00
|
|
|
std::set<std::string> notSupportOps;
|
|
|
|
for (auto& op : netT->oplists) {
|
|
|
|
if (op->type == MNN::OpType_Extra) {
|
|
|
|
if (op->main.AsExtra()->engine != "MNN") {
|
|
|
|
notSupportOps.insert(op->main.AsExtra()->engine + "::" + op->main.AsExtra()->type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::ostringstream notSupportInfo;
|
|
|
|
if (!notSupportOps.empty()) {
|
|
|
|
for (auto name : notSupportOps) {
|
|
|
|
notSupportInfo << name << " | ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DCHECK_EQ(notSupportOps.size(), 0) << "These Op Not Support: " << notSupportInfo.str();
|
2019-07-11 13:56:52 +08:00
|
|
|
flatbuffers::FlatBufferBuilder builderOutput(1024);
|
|
|
|
builderOutput.ForceDefaults(true);
|
|
|
|
auto len = MNN::Net::Pack(builderOutput, netT.get());
|
|
|
|
builderOutput.Finish(len);
|
|
|
|
int sizeOutput = builderOutput.GetSize();
|
|
|
|
auto bufferOutput = builderOutput.GetBufferPointer();
|
2019-04-17 10:49:11 +08:00
|
|
|
|
2019-09-01 19:25:26 +08:00
|
|
|
std::ofstream output(MNNModelFile, std::ofstream::binary);
|
2019-07-11 13:56:52 +08:00
|
|
|
output.write((const char*)bufferOutput, sizeOutput);
|
2019-04-17 10:49:11 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|