From 353fbf5adc75d04afe49d2c49789c766bdf00bec Mon Sep 17 00:00:00 2001 From: lz Date: Mon, 27 Jun 2022 09:30:09 +0800 Subject: [PATCH] change micro benchmark metric to cos-sim --- .../component/const_blocks/calib_output.cc | 66 ++++++++++++++----- .../fp32/convolution_winograd_fp32_coder.cc | 2 +- .../nnacl_serializer/nnacl_fp32_serializer.cc | 3 +- .../nnacl_serializer/nnacl_int8_serializer.cc | 8 +-- 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/mindspore/lite/tools/converter/micro/coder/generator/component/const_blocks/calib_output.cc b/mindspore/lite/tools/converter/micro/coder/generator/component/const_blocks/calib_output.cc index c446d547590..1c9e082ba0a 100644 --- a/mindspore/lite/tools/converter/micro/coder/generator/component/const_blocks/calib_output.cc +++ b/mindspore/lite/tools/converter/micro/coder/generator/component/const_blocks/calib_output.cc @@ -159,8 +159,8 @@ int CompareOutputs(MSTensorHandleArray outputs, CalibTensor **calib_tensors, int printf("error, outputs and calibs size is mismatch\n"); return kMSStatusLiteError; } - float total_error = 0; size_t outputs_num = outputs.handle_num; + bool is_success = true; for (size_t i = 0; i < outputs_num; ++i) { MicroTensor *output = (MicroTensor *)outputs.handle_list[i]; if (!output || !output->data) { @@ -178,6 +178,7 @@ int CompareOutputs(MSTensorHandleArray outputs, CalibTensor **calib_tensors, int printf("error, output elements num is not equal to calib\n"); return kMSStatusLiteError; } + float cosin = 0.f, dot = 0.f, normx = 0.f, normy = 0.f; switch (output->type) { case kMSDataTypeNumberTypeFloat32: { float *float_output = (float *)output->data; @@ -187,21 +188,27 @@ int CompareOutputs(MSTensorHandleArray outputs, CalibTensor **calib_tensors, int printf("error, output data is nan or inf\n"); return kMSStatusLiteError; } - total_error += fabsf(float_output[j] - calib[i].data_[j]); + dot += float_output[j] * calib[i].data_[j]; + normx += float_output[j] * float_output[j]; + normy += calib[i].data_[j] * calib[i].data_[j]; } break; } case kMSDataTypeNumberTypeInt8: { int8_t *int_output = (int8_t *)output->data; for (size_t j = 0; j < elements; ++j) { - total_error += fabsf(int_output[j] - calib[i].data_[j]); + dot += (float) (int_output[j] * calib[i].data_[j]); + normx += (float) (int_output[j] * int_output[j]); + normy += (float)(calib[i].data_[j] * calib[i].data_[j]); } break; } case kMSDataTypeNumberTypeUInt8: { uint8_t *int_output = (uint8_t *)output->data; for (size_t j = 0; j < elements; ++j) { - total_error += fabsf(int_output[j] - calib[i].data_[j]); + dot += (float) (int_output[j] * calib[i].data_[j]); + normx += (float) (int_output[j] * int_output[j]); + normy += (float)(calib[i].data_[j] * calib[i].data_[j]); } break; } @@ -209,20 +216,29 @@ int CompareOutputs(MSTensorHandleArray outputs, CalibTensor **calib_tensors, int case kMSDataTypeNumberTypeUInt32: { int32_t *int_output = (int32_t *)output->data; for (size_t j = 0; j < elements; ++j) { - total_error += fabsf(int_output[j] - calib[i].data_[j]); + dot += (float) (int_output[j] * calib[i].data_[j]); + normx += (float) (int_output[j] * int_output[j]); + normy += (float)(calib[i].data_[j] * calib[i].data_[j]); } break; } default: { - printf("unsupported tensor data type\n"); + printf("unsupported tensor data type.\n"); } } + cosin = dot / (sqrt(normx) * sqrt(normy)); + if (cosin < 0.9999) { + printf("cos-similarity of %s is %f, less than 0.9999.\n", output->name, cosin); + is_success = false; + } else { + printf("cos-similarity of %s is %f.\n", output->name, cosin); + } } - if (total_error > kToleranceVal) { - printf("compare outputs failed, total error: %f\n", total_error); + if (!is_success) { + printf("compare outputs failed.\n"); return kMSStatusLiteError; } - printf("compare outputs success, total error: %f\n", total_error); + printf("compare outputs success.\n"); return kMSStatusSuccess; } @@ -393,10 +409,11 @@ int CompareOutputs(MSTensorHandleArray *outputs, TensorArray *tensor_array) { printf("error, calib tensor is NULL.\n"); return kMSStatusLiteError; } - float total_error = 0; + bool is_success = true; size_t outputs_num = outputs->handle_num; for (size_t i = 0; i < outputs_num; ++i) { MicroTensor *output = (MicroTensor *)outputs->handle_list[i]; + float cosin = 0.f, dot = 0.f, normx = 0.f, normy = 0.f; if (output == NULL){ printf("error, output is nullptr.\n"); return kMSStatusLiteError; @@ -429,21 +446,27 @@ int CompareOutputs(MSTensorHandleArray *outputs, TensorArray *tensor_array) { printf("error, output data is nan or inf\n"); return kMSStatusLiteError; } - total_error += fabsf(float_output[j] - calib_tensors[i].data_[j]); + dot += float_output[j] * calib_tensors[i].data_[j]; + normx += float_output[j] * float_output[j]; + normy += calib_tensors[i].data_[j] * calib_tensors[i].data_[j]; } break; } case kMSDataTypeNumberTypeInt8: { int8_t *int_output = (int8_t *)output->data; for (size_t j = 0; j < elements; ++j) { - total_error += fabsf(int_output[j] - calib_tensors[i].data_[j]); + dot += (float) (int_output[j] * calib_tensors[i].data_[j]); + normx += (float) (int_output[j] * int_output[j]); + normy += (float)(calib_tensors[i].data_[j] * calib_tensors[i].data_[j]); } break; } case kMSDataTypeNumberTypeUInt8: { uint8_t *int_output = (uint8_t *)output->data; for (size_t j = 0; j < elements; ++j) { - total_error += fabsf(int_output[j] - calib_tensors[i].data_[j]); + dot += (float) (int_output[j] * calib_tensors[i].data_[j]); + normx += (float) (int_output[j] * int_output[j]); + normy += (float)(calib_tensors[i].data_[j] * calib_tensors[i].data_[j]); } break; } @@ -451,7 +474,9 @@ int CompareOutputs(MSTensorHandleArray *outputs, TensorArray *tensor_array) { case kMSDataTypeNumberTypeUInt32: { int32_t *int_output = (int32_t *)output->data; for (size_t j = 0; j < elements; ++j) { - total_error += fabsf(int_output[j] - calib_tensors[i].data_[j]); + dot += (float) (int_output[j] * calib_tensors[i].data_[j]); + normx += (float) (int_output[j] * int_output[j]); + normy += (float)(calib_tensors[i].data_[j] * calib_tensors[i].data_[j]); } break; } @@ -459,12 +484,19 @@ int CompareOutputs(MSTensorHandleArray *outputs, TensorArray *tensor_array) { printf("unsupported tensor data type\n"); } } + cosin = dot / (sqrt(normx) * sqrt(normy)); + if (cosin < 0.9999) { + printf("cos-similarity of %s is %f, less than 0.9999.\n", output->name, cosin); + is_success = false; + } else { + printf("cos-similarity of %s is %f.\n", output->name, cosin); + } } - if (total_error > kToleranceVal) { - printf("compare outputs failed, total error: %f\n", total_error); + if (!is_success) { + printf("compare outputs failed.\n"); return kMSStatusLiteError; } - printf("compare outputs success, total error: %f.\n", total_error); + printf("compare outputs success.\n"); return kMSStatusSuccess; } )RAW"; diff --git a/mindspore/lite/tools/converter/micro/coder/opcoders/nnacl/fp32/convolution_winograd_fp32_coder.cc b/mindspore/lite/tools/converter/micro/coder/opcoders/nnacl/fp32/convolution_winograd_fp32_coder.cc index 556f851aa9e..7dfdfad1e04 100644 --- a/mindspore/lite/tools/converter/micro/coder/opcoders/nnacl/fp32/convolution_winograd_fp32_coder.cc +++ b/mindspore/lite/tools/converter/micro/coder/opcoders/nnacl/fp32/convolution_winograd_fp32_coder.cc @@ -270,7 +270,7 @@ int ConvolutionWinogradFP32Coder::DoCode(CoderContext *const context) { code.CodeFunction("memset", gemm_out_, "0", gemm_out_size_); code.CodeFunction("memset", tmp_data_, "0", tmp_data_size_); code.CodeFunction("memset", col_buffer_, "0", col_buffer_size_); - code << "\t\tfloat *tmp_buffer_address_list[4] = {" << allocator_->GetRuntimeAddr(trans_input_) << ", " + code << " float *tmp_buffer_address_list[4] = {" << allocator_->GetRuntimeAddr(trans_input_) << ", " << allocator_->GetRuntimeAddr(gemm_out_) << ", " << allocator_->GetRuntimeAddr(tmp_data_) << ", " << allocator_->GetRuntimeAddr(col_buffer_) << "};\n"; code.CodeStruct("conv_parameter", *conv_param_); diff --git a/mindspore/lite/tools/converter/micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.cc b/mindspore/lite/tools/converter/micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.cc index c4f327473eb..6f9f9a7218b 100644 --- a/mindspore/lite/tools/converter/micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.cc +++ b/mindspore/lite/tools/converter/micro/coder/opcoders/serializers/nnacl_serializer/nnacl_fp32_serializer.cc @@ -61,7 +61,8 @@ void NNaclFp32Serializer::CodeStruct(const std::string &name, const SoftmaxParam } void NNaclFp32Serializer::CodeStruct(const std::string &name, const ConvParameter &conv_parameter) { - code << "int thread_num = MSMIN(" << gThreadNum << ", " << conv_parameter.output_h_ << ");\n"; + code << gThreadNum << " = 1;\n"; + code << " int thread_num = MSMIN(" << gThreadNum << ", " << conv_parameter.output_h_ << ");\n"; CodeBaseStruct( "ConvParameter", name, conv_parameter.op_parameter_, "{0}", conv_parameter.kernel_h_, conv_parameter.kernel_w_, conv_parameter.stride_h_, conv_parameter.stride_w_, conv_parameter.dilation_h_, conv_parameter.dilation_w_, diff --git a/mindspore/lite/tools/converter/micro/coder/opcoders/serializers/nnacl_serializer/nnacl_int8_serializer.cc b/mindspore/lite/tools/converter/micro/coder/opcoders/serializers/nnacl_serializer/nnacl_int8_serializer.cc index a650493f070..eaf6a7ed06f 100644 --- a/mindspore/lite/tools/converter/micro/coder/opcoders/serializers/nnacl_serializer/nnacl_int8_serializer.cc +++ b/mindspore/lite/tools/converter/micro/coder/opcoders/serializers/nnacl_serializer/nnacl_int8_serializer.cc @@ -49,7 +49,7 @@ void NNaclInt8Serializer::CodeStruct(const std::string &name, const ConvParamete quant_arg_in, quant_arg_w, quant_arg_out, real_multiplier, left_shift, right_shift, quant_multiplier, out_act_min, out_act_max, quant_arg.input_arg_num_, quant_arg.filter_arg_num_, quant_arg.output_arg_num_, quant_arg.per_channel_); - code << "int thread_num = MSMIN(" << gThreadNum << ", " << conv_parameter.output_h_ << ");\n"; + code << " int thread_num = MSMIN(" << gThreadNum << ", " << conv_parameter.output_h_ << ");\n"; CodeBaseStruct( "ConvParameter", name, conv_parameter.op_parameter_, conv_quant_arg, conv_parameter.kernel_h_, conv_parameter.kernel_w_, conv_parameter.stride_h_, conv_parameter.stride_w_, conv_parameter.dilation_h_, @@ -100,10 +100,10 @@ void NNaclInt8Serializer::CodeStruct(const std::string &name, const PoolingParam MS_CHECK_PTR_IF_NULL(in_quant_args); MS_CHECK_PTR_IF_NULL(out_quant_args); - code << "static QuantArg " << in_quant_name << " = " << *in_quant_args << ";\n"; - code << "static QuantArg " << out_quant_name << " = " << *out_quant_args << ";\n"; + code << " static QuantArg " << in_quant_name << " = " << *in_quant_args << ";\n"; + code << " static QuantArg " << out_quant_name << " = " << *out_quant_args << ";\n"; - code << "static QuantArg *" << quant_name << "[2] = {" + code << " static QuantArg *" << quant_name << "[2] = {" << " &" << in_quant_name << ", " << " &" << out_quant_name << "};\n";