| 73 | } |
| 74 | |
| 75 | void WeightQuantAndCoding(std::unique_ptr<MNN::OpT>& op, const modelConfig& config, const PostTreatContext* context) { |
| 76 | const auto opType = op->type; |
| 77 | // config.weightQuantBits only control weight quantization for float convolution |
| 78 | // by default, do coding for convint8 and depthwiseconvint8, if there is any |
| 79 | |
| 80 | if (opType != MNN::OpType_Convolution && opType != MNN::OpType_ConvolutionDepthwise && |
| 81 | opType != MNN::OpType_Deconvolution && opType != MNN::OpType_DeconvolutionDepthwise && |
| 82 | opType != MNN::OpType_ConvInt8 && opType != MNN::OpType_DepthwiseConvInt8) { |
| 83 | return; |
| 84 | } |
| 85 | auto param = op->main.AsConvolution2D(); |
| 86 | auto& common = param->common; |
| 87 | if (param->quanParameter.get() != nullptr) { |
| 88 | return; |
| 89 | } |
| 90 | bool useHqq = config.useHQQ; |
| 91 | auto weightQuantBits = config.weightQuantBits; |
| 92 | bool asymmetricQuantFlag = config.weightQuantAsymmetric; |
| 93 | auto weightQuantBlock = config.weightQuantBlock; |
| 94 | // Read or write config in proto |
| 95 | if (context->quantInfo.find(std::make_pair(context->subgraph, op->name)) != context->quantInfo.end()) { |
| 96 | auto param = context->quantInfo.find(std::make_pair(context->subgraph, op->name))->second; |
| 97 | if (param->weight_size() > 0) { |
| 98 | auto weight = param->weight(0); |
| 99 | if (weight.has_asymmetric()) { |
| 100 | asymmetricQuantFlag = weight.asymmetric(); |
| 101 | } |
| 102 | if (weight.has_bits()) { |
| 103 | weightQuantBits = weight.bits(); |
| 104 | } |
| 105 | if (weight.has_block_size()) { |
| 106 | weightQuantBlock = weight.block_size(); |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | if (useHqq) { |
| 111 | // HQQ must use asym |
| 112 | asymmetricQuantFlag = true; |
| 113 | } |
| 114 | if (nullptr != context->quantMutableInfo) { |
| 115 | auto& proto = context->proto; |
| 116 | auto layer = context->quantMutableInfo->add_layer(); |
| 117 | layer->set_op_name(op->name); |
| 118 | if (!context->subgraph.empty()) { |
| 119 | layer->set_subgraph_name(context->subgraph); |
| 120 | } |
| 121 | auto conv = layer->mutable_conv(); |
| 122 | conv->set_input_channel(common->inputCount); |
| 123 | conv->set_output_channel(common->outputCount); |
| 124 | conv->clear_kernel_size(); |
| 125 | conv->add_kernel_size(common->kernelX); |
| 126 | conv->add_kernel_size(common->kernelY); |
| 127 | auto weight = layer->add_weight(); |
| 128 | weight->set_bits(weightQuantBits); |
| 129 | weight->set_asymmetric(asymmetricQuantFlag); |
| 130 | weight->set_block_size(weightQuantBlock); |
| 131 | weight->set_name(op->name); |
| 132 | } |
no test coverage detected