From 77fa973046962d48aff248618b7d039da592b254 Mon Sep 17 00:00:00 2001 From: daquexian Date: Tue, 6 Aug 2019 14:02:55 +0800 Subject: [PATCH 1/6] Move op implementation to ModelBuilderImpl.cpp --- dnnlibrary/CMakeLists.txt | 1 + dnnlibrary/ModelBuilder.cpp | 597 +---------------------------- dnnlibrary/ModelBuilderImpl.cpp | 601 ++++++++++++++++++++++++++++++ generate_code.py | 2 +- include/dnnlibrary/ModelBuilder.h | 3 +- 5 files changed, 608 insertions(+), 596 deletions(-) create mode 100644 dnnlibrary/ModelBuilderImpl.cpp diff --git a/dnnlibrary/CMakeLists.txt b/dnnlibrary/CMakeLists.txt index 0042cc0..b676319 100644 --- a/dnnlibrary/CMakeLists.txt +++ b/dnnlibrary/CMakeLists.txt @@ -9,6 +9,7 @@ set(dnnlibrary_src operand_helper.h flatbuffers_helper.h ModelBuilder.cpp + ModelBuilderImpl.cpp Model.cpp DaqReader.cpp NeuralNetworksWrapper.cpp diff --git a/dnnlibrary/ModelBuilder.cpp b/dnnlibrary/ModelBuilder.cpp index 71e98c8..2f12c86 100644 --- a/dnnlibrary/ModelBuilder.cpp +++ b/dnnlibrary/ModelBuilder.cpp @@ -38,597 +38,6 @@ void ModelBuilder::RegisterOperand(const std::string &name, operand_types_.insert({name, operand_type}); } -ModelBuilder::Index ModelBuilder::AddInput(string name, const uint32_t batch, - const uint32_t height, - const uint32_t width, - const uint32_t depth) { - const vector dimen{batch, height, width, depth}; - return AddInput(name, {Type::TENSOR_FLOAT32, dimen}); -} - -ModelBuilder::Index ModelBuilder::AddInput(std::string name, - const OperandType &operand_type) { - const auto index = AddNewOperand(operand_type); - - shaper_.AddShape(name, operand_type.dimensions); - input_index_vec_.push_back(index); - dnn_model_->AddInput(name, shaper_[name]); - RegisterOperand(name, index, operand_type); - return index; -} - -// ModelBuilder auto generated methods start -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddConv( - const std::string &input, const std::string &weight, - const dnn::optional &bias, int32_t padding_left, - int32_t padding_right, int32_t padding_top, int32_t padding_bottom, - int32_t stride_x, int32_t stride_y, int32_t fuse_code, - const std::string &output, - const dnn::optional &output_quant_info) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - imm_blob_inputs_.insert(weight); - const auto weight_idx = operand_indexes_.at(weight); - input_indexes.push_back(weight_idx); - uint32_t bias_idx_val; - css bias_val = bias.value_or(weight + "_b"); - if (!bias.has_value()) { - const auto weight_dimen = shaper_[weight]; - const Shape bias_dimen{weight_dimen[0]}; - const auto &weight_type = operand_types_.at(weight).type; - if (weight_type == Type::TENSOR_FLOAT32) { - bias_idx_val = - FillOperand(bias_val, {Type::TENSOR_FLOAT32, bias_dimen}, 0.f); - } else if (weight_type == Type::TENSOR_QUANT8_ASYMM) { - const auto input_scale = operand_types_.at(input).operandType.scale; - const auto weight_scale = - operand_types_.at(weight).operandType.scale; - bias_idx_val = FillOperand( - bias_val, - {Type::TENSOR_INT32, bias_dimen, input_scale * weight_scale}, - 0); - } else { - throw std::invalid_argument("Unknown type " + - typeToStr(weight_type)); - } - } else { - bias_idx_val = operand_indexes_.at(bias.value()); - } - input_indexes.push_back(bias_idx_val); - AddScalarOperands(input_indexes, padding_left, padding_right, padding_top, - padding_bottom, stride_x, stride_y, fuse_code); - shaper_.Conv(input, weight, padding_left, padding_right, padding_top, - padding_bottom, stride_x, stride_y, output); - const OperandType operand_type = GetOperandType( - operand_types_.at(input).type, shaper_[output], output_quant_info); - const auto output_idx = - AddOperation(ANEURALNETWORKS_CONV_2D, input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddAvePool( - const std::string &input, int32_t padding_left, int32_t padding_right, - int32_t padding_top, int32_t padding_bottom, int32_t stride_x, - int32_t stride_y, int32_t kernel_width, int32_t kernel_height, - int32_t fuse_code, const std::string &output, - const dnn::optional &output_quant_info) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - AddScalarOperands(input_indexes, padding_left, padding_right, padding_top, - padding_bottom, stride_x, stride_y, kernel_width, - kernel_height, fuse_code); - shaper_.Pool(input, padding_left, padding_right, padding_top, - padding_bottom, stride_x, stride_y, kernel_width, - kernel_height, output); - const OperandType operand_type = GetOperandType( - operand_types_.at(input).type, shaper_[output], output_quant_info); - const auto output_idx = AddOperation(ANEURALNETWORKS_AVERAGE_POOL_2D, - input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddMaxPool( - const std::string &input, int32_t padding_left, int32_t padding_right, - int32_t padding_top, int32_t padding_bottom, int32_t stride_x, - int32_t stride_y, int32_t kernel_width, int32_t kernel_height, - int32_t fuse_code, const std::string &output, - const dnn::optional &output_quant_info) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - AddScalarOperands(input_indexes, padding_left, padding_right, padding_top, - padding_bottom, stride_x, stride_y, kernel_width, - kernel_height, fuse_code); - shaper_.Pool(input, padding_left, padding_right, padding_top, - padding_bottom, stride_x, stride_y, kernel_width, - kernel_height, output); - const OperandType operand_type = GetOperandType( - operand_types_.at(input).type, shaper_[output], output_quant_info); - const auto output_idx = AddOperation(ANEURALNETWORKS_MAX_POOL_2D, - input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddReLU(const std::string &input, - const std::string &output) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - shaper_.Relu(input, output); - const OperandType operand_type = - GetOperandType(operand_types_.at(input).type, shaper_[output]); - const auto output_idx = - AddOperation(ANEURALNETWORKS_RELU, input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddSoftmax(const std::string &input, - float beta, - const std::string &output) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - AddScalarOperands(input_indexes, beta); - shaper_.Softmax(input, output); - const OperandType operand_type = - GetOperandType(operand_types_.at(input).type, shaper_[output]); - const auto output_idx = - AddOperation(ANEURALNETWORKS_SOFTMAX, input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddFC( - const std::string &input, const std::string &weight, - const dnn::optional &bias, int32_t fuse_code, - const std::string &output, - const dnn::optional &output_quant_info) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - imm_blob_inputs_.insert(weight); - const auto weight_idx = operand_indexes_.at(weight); - input_indexes.push_back(weight_idx); - uint32_t bias_idx_val; - css bias_val = bias.value_or(weight + "_b"); - if (!bias.has_value()) { - const auto weight_dimen = shaper_[weight]; - const Shape bias_dimen{weight_dimen[0]}; - const auto &weight_type = operand_types_.at(weight).type; - if (weight_type == Type::TENSOR_FLOAT32) { - bias_idx_val = - FillOperand(bias_val, {Type::TENSOR_FLOAT32, bias_dimen}, 0.f); - } else if (weight_type == Type::TENSOR_QUANT8_ASYMM) { - const auto input_scale = operand_types_.at(input).operandType.scale; - const auto weight_scale = - operand_types_.at(weight).operandType.scale; - bias_idx_val = FillOperand( - bias_val, - {Type::TENSOR_INT32, bias_dimen, input_scale * weight_scale}, - 0); - } else { - throw std::invalid_argument("Unknown type " + - typeToStr(weight_type)); - } - } else { - bias_idx_val = operand_indexes_.at(bias.value()); - } - input_indexes.push_back(bias_idx_val); - AddScalarOperands(input_indexes, fuse_code); - shaper_.FC(input, weight, output); - const OperandType operand_type = GetOperandType( - operand_types_.at(input).type, shaper_[output], output_quant_info); - const auto output_idx = AddOperation(ANEURALNETWORKS_FULLY_CONNECTED, - input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddAdd( - const std::string &input1, const std::string &input2, int32_t fuse_code, - const std::string &output, - const dnn::optional &output_quant_info) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input1); - const auto input1_idx = operand_indexes_.at(input1); - input_indexes.push_back(input1_idx); - imm_blob_inputs_.insert(input2); - const auto input2_idx = operand_indexes_.at(input2); - input_indexes.push_back(input2_idx); - AddScalarOperands(input_indexes, fuse_code); - shaper_.Eltwise(input1, input2, output); - const OperandType operand_type = GetOperandType( - operand_types_.at(input1).type, shaper_[output], output_quant_info); - const auto output_idx = - AddOperation(ANEURALNETWORKS_ADD, input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddConcat( - const std::vector &inputs, int32_t axis, - const std::string &output) { - IndexSeq input_indexes; - for (const auto &x : inputs) { - imm_blob_inputs_.insert(x); - input_indexes.push_back(operand_indexes_.at(x)); - } - AddScalarOperands(input_indexes, axis); - shaper_.Concat(inputs, axis, output); - const OperandType operand_type = - GetOperandType(operand_types_.at(inputs[0]).type, shaper_[output]); - const auto output_idx = AddOperation(ANEURALNETWORKS_CONCATENATION, - input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddDepthwiseConv( - const std::string &input, const std::string &weight, - const dnn::optional &bias, int32_t padding_left, - int32_t padding_right, int32_t padding_top, int32_t padding_bottom, - int32_t stride_x, int32_t stride_y, int32_t depth_multiplier, - int32_t fuse_code, const std::string &output, - const dnn::optional &output_quant_info) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - imm_blob_inputs_.insert(weight); - const auto weight_idx = operand_indexes_.at(weight); - input_indexes.push_back(weight_idx); - uint32_t bias_idx_val; - css bias_val = bias.value_or(weight + "_b"); - if (!bias.has_value()) { - const auto weight_dimen = shaper_[weight]; - const Shape bias_dimen{weight_dimen[0]}; - const auto &weight_type = operand_types_.at(weight).type; - if (weight_type == Type::TENSOR_FLOAT32) { - bias_idx_val = - FillOperand(bias_val, {Type::TENSOR_FLOAT32, bias_dimen}, 0.f); - } else if (weight_type == Type::TENSOR_QUANT8_ASYMM) { - const auto input_scale = operand_types_.at(input).operandType.scale; - const auto weight_scale = - operand_types_.at(weight).operandType.scale; - bias_idx_val = FillOperand( - bias_val, - {Type::TENSOR_INT32, bias_dimen, input_scale * weight_scale}, - 0); - } else { - throw std::invalid_argument("Unknown type " + - typeToStr(weight_type)); - } - } else { - bias_idx_val = operand_indexes_.at(bias.value()); - } - input_indexes.push_back(bias_idx_val); - AddScalarOperands(input_indexes, padding_left, padding_right, padding_top, - padding_bottom, stride_x, stride_y, depth_multiplier, - fuse_code); - shaper_.DepthwiseConv(input, weight, padding_left, padding_right, - padding_top, padding_bottom, stride_x, stride_y, - output); - const OperandType operand_type = GetOperandType( - operand_types_.at(input).type, shaper_[output], output_quant_info); - const auto output_idx = AddOperation(ANEURALNETWORKS_DEPTHWISE_CONV_2D, - input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 28 -ModelBuilder::Index ModelBuilder::AddBatchToSpaceND( - const std::string &input, const std::vector &block_sizes, - const std::string &output) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - const auto block_sizes_idx = AddTensorFromBuffer( - "input_block_sizes_of_" + output, &block_sizes[0], - {Type::TENSOR_INT32, Shape{static_cast(block_sizes.size())}}); - input_indexes.push_back(block_sizes_idx); - shaper_.BatchToSpace(input, block_sizes, output); - const OperandType operand_type = - GetOperandType(operand_types_.at(input).type, shaper_[output]); - const auto output_idx = AddOperation(ANEURALNETWORKS_BATCH_TO_SPACE_ND, - input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 28 -#if __ANDROID_API__ >= 28 -ModelBuilder::Index ModelBuilder::AddSpaceToBatchND( - const std::string &input, const std::vector &block_sizes, - const std::vector &pads, const std::string &output) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - const auto block_sizes_idx = AddTensorFromBuffer( - "input_block_sizes_of_" + output, &block_sizes[0], - {Type::TENSOR_INT32, Shape{static_cast(block_sizes.size())}}); - input_indexes.push_back(block_sizes_idx); - const auto pads_idx = AddTensorFromBuffer( - "input_pads_of_" + output, &pads[0], - {Type::TENSOR_INT32, Shape{static_cast(pads.size())}}); - input_indexes.push_back(pads_idx); - shaper_.SpaceToBatch(input, block_sizes, pads, output); - const OperandType operand_type = - GetOperandType(operand_types_.at(input).type, shaper_[output]); - const auto output_idx = AddOperation(ANEURALNETWORKS_SPACE_TO_BATCH_ND, - input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 28 -#if __ANDROID_API__ >= 28 -ModelBuilder::Index ModelBuilder::AddStridedSlice( - const std::string &input, const std::vector &starts, - const std::vector &ends, const std::vector &strides, - int32_t begin_mask, int32_t end_mask, int32_t shrink_axis_mask, - const std::string &output) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - const auto starts_idx = AddTensorFromBuffer( - "input_starts_of_" + output, &starts[0], - {Type::TENSOR_INT32, Shape{static_cast(starts.size())}}); - input_indexes.push_back(starts_idx); - const auto ends_idx = AddTensorFromBuffer( - "input_ends_of_" + output, &ends[0], - {Type::TENSOR_INT32, Shape{static_cast(ends.size())}}); - input_indexes.push_back(ends_idx); - const auto strides_idx = AddTensorFromBuffer( - "input_strides_of_" + output, &strides[0], - {Type::TENSOR_INT32, Shape{static_cast(strides.size())}}); - input_indexes.push_back(strides_idx); - AddScalarOperands(input_indexes, begin_mask, end_mask, shrink_axis_mask); - shaper_.StridedSlice(input, starts, ends, strides, begin_mask, end_mask, - shrink_axis_mask, output); - const OperandType operand_type = - GetOperandType(operand_types_.at(input).type, shaper_[output]); - const auto output_idx = AddOperation(ANEURALNETWORKS_STRIDED_SLICE, - input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 28 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddMul( - const std::string &input1, const std::string &input2, int32_t fuse_code, - const std::string &output, - const dnn::optional &output_quant_info) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input1); - const auto input1_idx = operand_indexes_.at(input1); - input_indexes.push_back(input1_idx); - imm_blob_inputs_.insert(input2); - const auto input2_idx = operand_indexes_.at(input2); - input_indexes.push_back(input2_idx); - AddScalarOperands(input_indexes, fuse_code); - shaper_.Eltwise(input1, input2, output); - const OperandType operand_type = GetOperandType( - operand_types_.at(input1).type, shaper_[output], output_quant_info); - const auto output_idx = - AddOperation(ANEURALNETWORKS_MUL, input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddAdd(const std::string &input, float scalar, - int32_t fuse_code, - const std::string &output) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - const auto scalar_idx = FillOperand("input_scalar_of_" + output, - {Type::TENSOR_FLOAT32, {1}}, scalar); - input_indexes.push_back(scalar_idx); - AddScalarOperands(input_indexes, fuse_code); - shaper_.Eltwise(input, output); - const OperandType operand_type = - GetOperandType(operand_types_.at(input).type, shaper_[output]); - const auto output_idx = - AddOperation(ANEURALNETWORKS_ADD, input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddMul(const std::string &input, float scalar, - int32_t fuse_code, - const std::string &output) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - const auto scalar_idx = FillOperand("input_scalar_of_" + output, - {Type::TENSOR_FLOAT32, {1}}, scalar); - input_indexes.push_back(scalar_idx); - AddScalarOperands(input_indexes, fuse_code); - shaper_.Eltwise(input, output); - const OperandType operand_type = - GetOperandType(operand_types_.at(input).type, shaper_[output]); - const auto output_idx = - AddOperation(ANEURALNETWORKS_MUL, input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddDequantize(const std::string &input, - const std::string &output) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - shaper_.Identity(input, output); - const OperandType operand_type = - GetOperandType(Type::TENSOR_FLOAT32, shaper_[output]); - const auto output_idx = AddOperation(ANEURALNETWORKS_DEQUANTIZE, - input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -#if __ANDROID_API__ >= 27 -ModelBuilder::Index ModelBuilder::AddLRN(const std::string &input, - int32_t radius, float bias, - float alpha, float beta, - const std::string &output) { - IndexSeq input_indexes; - imm_blob_inputs_.insert(input); - const auto input_idx = operand_indexes_.at(input); - input_indexes.push_back(input_idx); - AddScalarOperands(input_indexes, radius, bias, alpha, beta); - shaper_.Identity(input, output); - const OperandType operand_type = - GetOperandType(operand_types_.at(input).type, shaper_[output]); - const auto output_idx = - AddOperation(ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION, - input_indexes, operand_type)[0]; - RegisterOperand(output, output_idx, operand_type); - imm_blob_outputs_.insert(output); - return output_idx; -} -#endif // __ANDROID_API__ >= 27 -// ModelBuilder auto generated methods end - -ModelBuilder::Index ModelBuilder::AddDepthWiseConv( - const string &input_name, int32_t strideX, int32_t strideY, - int32_t paddingLeft, int32_t paddingRight, int32_t paddingBottom, - int32_t paddingTop, int32_t activation, int32_t depthMultiplier, - const string &weight_name, const dnn::optional &bias_name, - const string &output_name, - const dnn::optional &output_quant_info) { - return AddDepthwiseConv(input_name, weight_name, bias_name, paddingLeft, - paddingRight, paddingTop, paddingBottom, strideX, - strideY, depthMultiplier, activation, output_name, - output_quant_info); -} - -ModelBuilder::Index ModelBuilder::AddConv( - const string &input_name, int32_t strideX, int32_t strideY, - int32_t paddingLeft, int32_t paddingRight, int32_t paddingTop, - int32_t paddingBottom, int32_t activation, const string &weight_name, - const dnn::optional &bias_name, const string &output_name, - const dnn::optional &output_quant_info) { - return AddConv(input_name, weight_name, bias_name, paddingLeft, - paddingRight, paddingTop, paddingBottom, strideX, strideY, - activation, output_name, output_quant_info); -} - -ModelBuilder::Index ModelBuilder::AddPool( - const string &input_name, int32_t strideX, int32_t strideY, - int32_t paddingLeft, int32_t paddingRight, int32_t paddingTop, - int32_t paddingBottom, int32_t height, int32_t width, int32_t activation, - PoolingType poolingType, const string &output_name, - const dnn::optional &output_quant_info) { - if (height == -1 && width == -1) { - VLOG(5) << "Global pool, input: " << input_name; - const auto inputDimen = shaper_[input_name]; - height = inputDimen[1]; - width = inputDimen[2]; - strideX = width; - strideY = height; - } - switch (poolingType) { - case PoolingType::AVE_POOL: - return AddAvePool(input_name, paddingLeft, paddingRight, paddingTop, - paddingBottom, strideX, strideY, width, height, - activation, output_name, output_quant_info); - break; - case PoolingType::MAX_POOL: - return AddMaxPool(input_name, paddingLeft, paddingRight, paddingTop, - paddingBottom, strideX, strideY, width, height, - activation, output_name, output_quant_info); - break; - } -} - -ModelBuilder::Index ModelBuilder::AddSoftMax(const string &input_name, - float beta, - const string &output_name) { - return AddSoftmax(input_name, beta, output_name); -} - -ModelBuilder::Index ModelBuilder::AddFC( - const string &input_name, int32_t activation, const string &weight_name, - const dnn::optional &bias_name, const string &output_name, - const dnn::optional &output_quant_info) { - return AddFC(input_name, weight_name, bias_name, activation, output_name, - output_quant_info); -} - -ModelBuilder::Index ModelBuilder::AddOperationAdd(const string &input_name, - float scalar, - string output_name) { - return AddAdd(input_name, scalar, ANEURALNETWORKS_FUSED_NONE, output_name); -} - -ModelBuilder::Index ModelBuilder::AddOperationAdd( - const string &input1_name, const string &input2_name, - const string &output_name, - const dnn::optional &output_quant_info) { - return AddAdd(input1_name, input2_name, ANEURALNETWORKS_FUSED_NONE, - output_name, output_quant_info); -} - -ModelBuilder::Index ModelBuilder::AddMul(const string &input_name, float scalar, - const string &output_name) { - return AddMul(input_name, scalar, ANEURALNETWORKS_FUSED_NONE, output_name); -} - -ModelBuilder::Index ModelBuilder::AddMul( - const string &input1_name, const string &input2_name, - const string &output_name, - const dnn::optional &output_quant_info) { - return AddMul(input1_name, input2_name, ANEURALNETWORKS_FUSED_NONE, - output_name, output_quant_info); -} -//--------------------------------------------------------------------------------------------------// - OperandType ModelBuilder::GetOperandType(const Type &type) { return {type, {}}; } @@ -927,11 +336,13 @@ dnn::optional> ModelBuilder::GetDevices() { nnapi_->ANeuralNetworksDevice_getName(nn_device, &nn_name_ptr); const std::string device_name(nn_name_ptr); int64_t feature_level; - nnapi_->ANeuralNetworksDevice_getFeatureLevel(nn_device, &feature_level); + nnapi_->ANeuralNetworksDevice_getFeatureLevel(nn_device, + &feature_level); int type; nnapi_->ANeuralNetworksDevice_getType(nn_device, &type); const char *nn_version_ptr; - nnapi_->ANeuralNetworksDevice_getVersion(nn_device, &nn_version_ptr); + nnapi_->ANeuralNetworksDevice_getVersion(nn_device, + &nn_version_ptr); const std::string version(nn_version_ptr); Device device{device_name, feature_level, type, version}; devices.push_back(device); diff --git a/dnnlibrary/ModelBuilderImpl.cpp b/dnnlibrary/ModelBuilderImpl.cpp new file mode 100644 index 0000000..bb0d69d --- /dev/null +++ b/dnnlibrary/ModelBuilderImpl.cpp @@ -0,0 +1,601 @@ +// +// Created by daquexian on 2019/8/6. +// +// This file is mostly generated by generate_code.py based on ops.yml +#include + +#include +#include +#include + +namespace dnn { +using namespace android::nn::wrapper; + +// ModelBuilder auto generated methods start +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddConv( + const std::string &input, const std::string &weight, + const dnn::optional &bias, int32_t padding_left, + int32_t padding_right, int32_t padding_top, int32_t padding_bottom, + int32_t stride_x, int32_t stride_y, int32_t fuse_code, + const std::string &output, + const dnn::optional &output_quant_info) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + imm_blob_inputs_.insert(weight); + const auto weight_idx = operand_indexes_.at(weight); + input_indexes.push_back(weight_idx); + uint32_t bias_idx_val; + css bias_val = bias.value_or(weight + "_b"); + if (!bias.has_value()) { + const auto weight_dimen = shaper_[weight]; + const Shape bias_dimen{weight_dimen[0]}; + const auto &weight_type = operand_types_.at(weight).type; + if (weight_type == Type::TENSOR_FLOAT32) { + bias_idx_val = + FillOperand(bias_val, {Type::TENSOR_FLOAT32, bias_dimen}, 0.f); + } else if (weight_type == Type::TENSOR_QUANT8_ASYMM) { + const auto input_scale = operand_types_.at(input).operandType.scale; + const auto weight_scale = + operand_types_.at(weight).operandType.scale; + bias_idx_val = FillOperand( + bias_val, + {Type::TENSOR_INT32, bias_dimen, input_scale * weight_scale}, + 0); + } else { + throw std::invalid_argument("Unknown type " + + typeToStr(weight_type)); + } + } else { + bias_idx_val = operand_indexes_.at(bias.value()); + } + input_indexes.push_back(bias_idx_val); + AddScalarOperands(input_indexes, padding_left, padding_right, padding_top, + padding_bottom, stride_x, stride_y, fuse_code); + shaper_.Conv(input, weight, padding_left, padding_right, padding_top, + padding_bottom, stride_x, stride_y, output); + const OperandType operand_type = GetOperandType( + operand_types_.at(input).type, shaper_[output], output_quant_info); + const auto output_idx = + AddOperation(ANEURALNETWORKS_CONV_2D, input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddAvePool( + const std::string &input, int32_t padding_left, int32_t padding_right, + int32_t padding_top, int32_t padding_bottom, int32_t stride_x, + int32_t stride_y, int32_t kernel_width, int32_t kernel_height, + int32_t fuse_code, const std::string &output, + const dnn::optional &output_quant_info) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + AddScalarOperands(input_indexes, padding_left, padding_right, padding_top, + padding_bottom, stride_x, stride_y, kernel_width, + kernel_height, fuse_code); + shaper_.Pool(input, padding_left, padding_right, padding_top, + padding_bottom, stride_x, stride_y, kernel_width, + kernel_height, output); + const OperandType operand_type = GetOperandType( + operand_types_.at(input).type, shaper_[output], output_quant_info); + const auto output_idx = AddOperation(ANEURALNETWORKS_AVERAGE_POOL_2D, + input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddMaxPool( + const std::string &input, int32_t padding_left, int32_t padding_right, + int32_t padding_top, int32_t padding_bottom, int32_t stride_x, + int32_t stride_y, int32_t kernel_width, int32_t kernel_height, + int32_t fuse_code, const std::string &output, + const dnn::optional &output_quant_info) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + AddScalarOperands(input_indexes, padding_left, padding_right, padding_top, + padding_bottom, stride_x, stride_y, kernel_width, + kernel_height, fuse_code); + shaper_.Pool(input, padding_left, padding_right, padding_top, + padding_bottom, stride_x, stride_y, kernel_width, + kernel_height, output); + const OperandType operand_type = GetOperandType( + operand_types_.at(input).type, shaper_[output], output_quant_info); + const auto output_idx = AddOperation(ANEURALNETWORKS_MAX_POOL_2D, + input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddReLU(const std::string &input, + const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + shaper_.Relu(input, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(input).type, shaper_[output]); + const auto output_idx = + AddOperation(ANEURALNETWORKS_RELU, input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddSoftmax(const std::string &input, + float beta, + const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + AddScalarOperands(input_indexes, beta); + shaper_.Softmax(input, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(input).type, shaper_[output]); + const auto output_idx = + AddOperation(ANEURALNETWORKS_SOFTMAX, input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddFC( + const std::string &input, const std::string &weight, + const dnn::optional &bias, int32_t fuse_code, + const std::string &output, + const dnn::optional &output_quant_info) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + imm_blob_inputs_.insert(weight); + const auto weight_idx = operand_indexes_.at(weight); + input_indexes.push_back(weight_idx); + uint32_t bias_idx_val; + css bias_val = bias.value_or(weight + "_b"); + if (!bias.has_value()) { + const auto weight_dimen = shaper_[weight]; + const Shape bias_dimen{weight_dimen[0]}; + const auto &weight_type = operand_types_.at(weight).type; + if (weight_type == Type::TENSOR_FLOAT32) { + bias_idx_val = + FillOperand(bias_val, {Type::TENSOR_FLOAT32, bias_dimen}, 0.f); + } else if (weight_type == Type::TENSOR_QUANT8_ASYMM) { + const auto input_scale = operand_types_.at(input).operandType.scale; + const auto weight_scale = + operand_types_.at(weight).operandType.scale; + bias_idx_val = FillOperand( + bias_val, + {Type::TENSOR_INT32, bias_dimen, input_scale * weight_scale}, + 0); + } else { + throw std::invalid_argument("Unknown type " + + typeToStr(weight_type)); + } + } else { + bias_idx_val = operand_indexes_.at(bias.value()); + } + input_indexes.push_back(bias_idx_val); + AddScalarOperands(input_indexes, fuse_code); + shaper_.FC(input, weight, output); + const OperandType operand_type = GetOperandType( + operand_types_.at(input).type, shaper_[output], output_quant_info); + const auto output_idx = AddOperation(ANEURALNETWORKS_FULLY_CONNECTED, + input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddAdd( + const std::string &input1, const std::string &input2, int32_t fuse_code, + const std::string &output, + const dnn::optional &output_quant_info) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input1); + const auto input1_idx = operand_indexes_.at(input1); + input_indexes.push_back(input1_idx); + imm_blob_inputs_.insert(input2); + const auto input2_idx = operand_indexes_.at(input2); + input_indexes.push_back(input2_idx); + AddScalarOperands(input_indexes, fuse_code); + shaper_.Eltwise(input1, input2, output); + const OperandType operand_type = GetOperandType( + operand_types_.at(input1).type, shaper_[output], output_quant_info); + const auto output_idx = + AddOperation(ANEURALNETWORKS_ADD, input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddConcat( + const std::vector &inputs, int32_t axis, + const std::string &output) { + IndexSeq input_indexes; + for (const auto &x : inputs) { + imm_blob_inputs_.insert(x); + input_indexes.push_back(operand_indexes_.at(x)); + } + AddScalarOperands(input_indexes, axis); + shaper_.Concat(inputs, axis, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(inputs[0]).type, shaper_[output]); + const auto output_idx = AddOperation(ANEURALNETWORKS_CONCATENATION, + input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddDepthwiseConv( + const std::string &input, const std::string &weight, + const dnn::optional &bias, int32_t padding_left, + int32_t padding_right, int32_t padding_top, int32_t padding_bottom, + int32_t stride_x, int32_t stride_y, int32_t depth_multiplier, + int32_t fuse_code, const std::string &output, + const dnn::optional &output_quant_info) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + imm_blob_inputs_.insert(weight); + const auto weight_idx = operand_indexes_.at(weight); + input_indexes.push_back(weight_idx); + uint32_t bias_idx_val; + css bias_val = bias.value_or(weight + "_b"); + if (!bias.has_value()) { + const auto weight_dimen = shaper_[weight]; + const Shape bias_dimen{weight_dimen[0]}; + const auto &weight_type = operand_types_.at(weight).type; + if (weight_type == Type::TENSOR_FLOAT32) { + bias_idx_val = + FillOperand(bias_val, {Type::TENSOR_FLOAT32, bias_dimen}, 0.f); + } else if (weight_type == Type::TENSOR_QUANT8_ASYMM) { + const auto input_scale = operand_types_.at(input).operandType.scale; + const auto weight_scale = + operand_types_.at(weight).operandType.scale; + bias_idx_val = FillOperand( + bias_val, + {Type::TENSOR_INT32, bias_dimen, input_scale * weight_scale}, + 0); + } else { + throw std::invalid_argument("Unknown type " + + typeToStr(weight_type)); + } + } else { + bias_idx_val = operand_indexes_.at(bias.value()); + } + input_indexes.push_back(bias_idx_val); + AddScalarOperands(input_indexes, padding_left, padding_right, padding_top, + padding_bottom, stride_x, stride_y, depth_multiplier, + fuse_code); + shaper_.DepthwiseConv(input, weight, padding_left, padding_right, + padding_top, padding_bottom, stride_x, stride_y, + output); + const OperandType operand_type = GetOperandType( + operand_types_.at(input).type, shaper_[output], output_quant_info); + const auto output_idx = AddOperation(ANEURALNETWORKS_DEPTHWISE_CONV_2D, + input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 28 +ModelBuilder::Index ModelBuilder::AddBatchToSpaceND( + const std::string &input, const std::vector &block_sizes, + const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + const auto block_sizes_idx = AddTensorFromBuffer( + "input_block_sizes_of_" + output, &block_sizes[0], + {Type::TENSOR_INT32, Shape{static_cast(block_sizes.size())}}); + input_indexes.push_back(block_sizes_idx); + shaper_.BatchToSpace(input, block_sizes, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(input).type, shaper_[output]); + const auto output_idx = AddOperation(ANEURALNETWORKS_BATCH_TO_SPACE_ND, + input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 28 +#if __ANDROID_API__ >= 28 +ModelBuilder::Index ModelBuilder::AddSpaceToBatchND( + const std::string &input, const std::vector &block_sizes, + const std::vector &pads, const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + const auto block_sizes_idx = AddTensorFromBuffer( + "input_block_sizes_of_" + output, &block_sizes[0], + {Type::TENSOR_INT32, Shape{static_cast(block_sizes.size())}}); + input_indexes.push_back(block_sizes_idx); + const auto pads_idx = AddTensorFromBuffer( + "input_pads_of_" + output, &pads[0], + {Type::TENSOR_INT32, Shape{static_cast(pads.size())}}); + input_indexes.push_back(pads_idx); + shaper_.SpaceToBatch(input, block_sizes, pads, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(input).type, shaper_[output]); + const auto output_idx = AddOperation(ANEURALNETWORKS_SPACE_TO_BATCH_ND, + input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 28 +#if __ANDROID_API__ >= 28 +ModelBuilder::Index ModelBuilder::AddStridedSlice( + const std::string &input, const std::vector &starts, + const std::vector &ends, const std::vector &strides, + int32_t begin_mask, int32_t end_mask, int32_t shrink_axis_mask, + const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + const auto starts_idx = AddTensorFromBuffer( + "input_starts_of_" + output, &starts[0], + {Type::TENSOR_INT32, Shape{static_cast(starts.size())}}); + input_indexes.push_back(starts_idx); + const auto ends_idx = AddTensorFromBuffer( + "input_ends_of_" + output, &ends[0], + {Type::TENSOR_INT32, Shape{static_cast(ends.size())}}); + input_indexes.push_back(ends_idx); + const auto strides_idx = AddTensorFromBuffer( + "input_strides_of_" + output, &strides[0], + {Type::TENSOR_INT32, Shape{static_cast(strides.size())}}); + input_indexes.push_back(strides_idx); + AddScalarOperands(input_indexes, begin_mask, end_mask, shrink_axis_mask); + shaper_.StridedSlice(input, starts, ends, strides, begin_mask, end_mask, + shrink_axis_mask, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(input).type, shaper_[output]); + const auto output_idx = AddOperation(ANEURALNETWORKS_STRIDED_SLICE, + input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 28 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddMul( + const std::string &input1, const std::string &input2, int32_t fuse_code, + const std::string &output, + const dnn::optional &output_quant_info) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input1); + const auto input1_idx = operand_indexes_.at(input1); + input_indexes.push_back(input1_idx); + imm_blob_inputs_.insert(input2); + const auto input2_idx = operand_indexes_.at(input2); + input_indexes.push_back(input2_idx); + AddScalarOperands(input_indexes, fuse_code); + shaper_.Eltwise(input1, input2, output); + const OperandType operand_type = GetOperandType( + operand_types_.at(input1).type, shaper_[output], output_quant_info); + const auto output_idx = + AddOperation(ANEURALNETWORKS_MUL, input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddAdd(const std::string &input, float scalar, + int32_t fuse_code, + const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + const auto scalar_idx = FillOperand("input_scalar_of_" + output, + {Type::TENSOR_FLOAT32, {1}}, scalar); + input_indexes.push_back(scalar_idx); + AddScalarOperands(input_indexes, fuse_code); + shaper_.Eltwise(input, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(input).type, shaper_[output]); + const auto output_idx = + AddOperation(ANEURALNETWORKS_ADD, input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddMul(const std::string &input, float scalar, + int32_t fuse_code, + const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + const auto scalar_idx = FillOperand("input_scalar_of_" + output, + {Type::TENSOR_FLOAT32, {1}}, scalar); + input_indexes.push_back(scalar_idx); + AddScalarOperands(input_indexes, fuse_code); + shaper_.Eltwise(input, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(input).type, shaper_[output]); + const auto output_idx = + AddOperation(ANEURALNETWORKS_MUL, input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddDequantize(const std::string &input, + const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + shaper_.Identity(input, output); + const OperandType operand_type = + GetOperandType(Type::FLOAT32, shaper_[output]); + const auto output_idx = AddOperation(ANEURALNETWORKS_DEQUANTIZE, + input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddLRN(const std::string &input, + int32_t radius, float bias, + float alpha, float beta, + const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + AddScalarOperands(input_indexes, radius, bias, alpha, beta); + shaper_.Identity(input, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(input).type, shaper_[output]); + const auto output_idx = + AddOperation(ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION, + input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +// ModelBuilder auto generated methods end + +// Methods for backward compatibility +ModelBuilder::Index ModelBuilder::AddInput(const std::string name, + const uint32_t batch, + const uint32_t height, + const uint32_t width, + const uint32_t depth) { + const std::vector dimen{batch, height, width, depth}; + return AddInput(name, {Type::TENSOR_FLOAT32, dimen}); +} + +ModelBuilder::Index ModelBuilder::AddInput(std::string name, + const OperandType &operand_type) { + const auto index = AddNewOperand(operand_type); + + shaper_.AddShape(name, operand_type.dimensions); + input_index_vec_.push_back(index); + dnn_model_->AddInput(name, shaper_[name]); + RegisterOperand(name, index, operand_type); + return index; +} + +ModelBuilder::Index ModelBuilder::AddDepthWiseConv( + const std::string &input_name, int32_t strideX, int32_t strideY, + int32_t paddingLeft, int32_t paddingRight, int32_t paddingBottom, + int32_t paddingTop, int32_t activation, int32_t depthMultiplier, + const std::string &weight_name, const dnn::optional &bias_name, + const std::string &output_name, + const dnn::optional &output_quant_info) { + return AddDepthwiseConv(input_name, weight_name, bias_name, paddingLeft, + paddingRight, paddingTop, paddingBottom, strideX, + strideY, depthMultiplier, activation, output_name, + output_quant_info); +} + +ModelBuilder::Index ModelBuilder::AddConv( + const std::string &input_name, int32_t strideX, int32_t strideY, + int32_t paddingLeft, int32_t paddingRight, int32_t paddingTop, + int32_t paddingBottom, int32_t activation, const std::string &weight_name, + const dnn::optional &bias_name, const std::string &output_name, + const dnn::optional &output_quant_info) { + return AddConv(input_name, weight_name, bias_name, paddingLeft, + paddingRight, paddingTop, paddingBottom, strideX, strideY, + activation, output_name, output_quant_info); +} + +ModelBuilder::Index ModelBuilder::AddPool( + const std::string &input_name, int32_t strideX, int32_t strideY, + int32_t paddingLeft, int32_t paddingRight, int32_t paddingTop, + int32_t paddingBottom, int32_t height, int32_t width, int32_t activation, + PoolingType poolingType, const std::string &output_name, + const dnn::optional &output_quant_info) { + if (height == -1 && width == -1) { + VLOG(5) << "Global pool, input: " << input_name; + const auto inputDimen = shaper_[input_name]; + height = inputDimen[1]; + width = inputDimen[2]; + strideX = width; + strideY = height; + } + switch (poolingType) { + case PoolingType::AVE_POOL: + return AddAvePool(input_name, paddingLeft, paddingRight, paddingTop, + paddingBottom, strideX, strideY, width, height, + activation, output_name, output_quant_info); + break; + case PoolingType::MAX_POOL: + return AddMaxPool(input_name, paddingLeft, paddingRight, paddingTop, + paddingBottom, strideX, strideY, width, height, + activation, output_name, output_quant_info); + break; + } +} + +ModelBuilder::Index ModelBuilder::AddFC( + const std::string &input_name, int32_t activation, + const std::string &weight_name, const dnn::optional &bias_name, + const std::string &output_name, + const dnn::optional &output_quant_info) { + return AddFC(input_name, weight_name, bias_name, activation, output_name, + output_quant_info); +} + +ModelBuilder::Index ModelBuilder::AddOperationAdd(const std::string &input_name, + float scalar, + std::string output_name) { + return AddAdd(input_name, scalar, ANEURALNETWORKS_FUSED_NONE, output_name); +} + +ModelBuilder::Index ModelBuilder::AddOperationAdd( + const std::string &input1_name, const std::string &input2_name, + const std::string &output_name, + const dnn::optional &output_quant_info) { + return AddAdd(input1_name, input2_name, ANEURALNETWORKS_FUSED_NONE, + output_name, output_quant_info); +} + +ModelBuilder::Index ModelBuilder::AddMul(const std::string &input_name, + float scalar, + const std::string &output_name) { + return AddMul(input_name, scalar, ANEURALNETWORKS_FUSED_NONE, output_name); +} + +ModelBuilder::Index ModelBuilder::AddMul( + const std::string &input1_name, const std::string &input2_name, + const std::string &output_name, + const dnn::optional &output_quant_info) { + return AddMul(input1_name, input2_name, ANEURALNETWORKS_FUSED_NONE, + output_name, output_quant_info); +} +} // namespace dnn diff --git a/generate_code.py b/generate_code.py index d19587e..0e3705d 100644 --- a/generate_code.py +++ b/generate_code.py @@ -304,7 +304,7 @@ def generate_model_builder(): ''' ) cogoutl('#endif // __ANDROID_API__ >= {}'.format(op['api'])) - update_code('dnnlibrary/src/ModelBuilder.cpp', 'ModelBuilder auto generated methods') + update_code('dnnlibrary/ModelBuilderImpl.cpp', 'ModelBuilder auto generated methods') for i, op in enumerate(cfg): if len(op['input']) == 0: continue diff --git a/include/dnnlibrary/ModelBuilder.h b/include/dnnlibrary/ModelBuilder.h index 980b306..7de9642 100644 --- a/include/dnnlibrary/ModelBuilder.h +++ b/include/dnnlibrary/ModelBuilder.h @@ -87,8 +87,7 @@ class ModelBuilder { android::nn::wrapper::OperandType GetOperandType( const QuantInfo &quant_info, const Shape &dims); - - const NnApi* nnapi_ = nullptr; + const NnApi *nnapi_ = nullptr; public: ModelBuilder(); From b5dd437cfaf09218057ad023090590510cdaceb7 Mon Sep 17 00:00:00 2001 From: daquexian Date: Tue, 6 Aug 2019 14:11:43 +0800 Subject: [PATCH 2/6] Support two simple op: tanh and floor --- common/daq.fbs | 14 +- dnnlibrary/ModelBuilderImpl.cpp | 34 ++ include/common/daq_generated.h | 420 ++++++++++++++++--------- include/dnnlibrary/ModelBuilder.h | 8 + include/tools/onnx2daq/OnnxConverter.h | 2 + ops.yml | 8 + tools/onnx2daq/OnnxConverter.cpp | 61 +++- 7 files changed, 399 insertions(+), 148 deletions(-) diff --git a/common/daq.fbs b/common/daq.fbs index 1244de7..95158dc 100644 --- a/common/daq.fbs +++ b/common/daq.fbs @@ -7,7 +7,7 @@ enum DataType:byte { Float32 = 0, Int8, Int32, Float16, Bool8, enum FuseCode:byte { None = 0, Relu, Relu1, Relu6 } enum LayerType:byte { Conv2D = 0, AvePool, MaxPool, Relu, Softmax, FC, Add, Concat, DepthwiseConv2D, BatchToSpace, SpaceToBatch, StridedSlice, Mul, AddScalar, MulScalar, - Dequantize, LRN} + Dequantize, LRN, Tanh, Floor} table Tensor { data_type:DataType; @@ -164,6 +164,16 @@ table LRN { output:string; } +table Tanh { + input:string; + output:string; +} + +table Floor { + input:string; + output:string; +} + table Layer { type:LayerType; conv2d_param:Conv2D; @@ -183,6 +193,8 @@ table Layer { mul_scalar_param:MulScalar; dequantize_param:Dequantize; lrn_param:LRN; + tanh_param:Tanh; + floor_param:Floor; } table Model { diff --git a/dnnlibrary/ModelBuilderImpl.cpp b/dnnlibrary/ModelBuilderImpl.cpp index bb0d69d..febaf81 100644 --- a/dnnlibrary/ModelBuilderImpl.cpp +++ b/dnnlibrary/ModelBuilderImpl.cpp @@ -487,6 +487,40 @@ ModelBuilder::Index ModelBuilder::AddLRN(const std::string &input, return output_idx; } #endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddTanh(const std::string &input, + const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + shaper_.Identity(input, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(input).type, shaper_[output]); + const auto output_idx = + AddOperation(ANEURALNETWORKS_TANH, input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 +ModelBuilder::Index ModelBuilder::AddFloor(const std::string &input, + const std::string &output) { + IndexSeq input_indexes; + imm_blob_inputs_.insert(input); + const auto input_idx = operand_indexes_.at(input); + input_indexes.push_back(input_idx); + shaper_.Identity(input, output); + const OperandType operand_type = + GetOperandType(operand_types_.at(input).type, shaper_[output]); + const auto output_idx = + AddOperation(ANEURALNETWORKS_FLOOR, input_indexes, operand_type)[0]; + RegisterOperand(output, output_idx, operand_type); + imm_blob_outputs_.insert(output); + return output_idx; +} +#endif // __ANDROID_API__ >= 27 // ModelBuilder auto generated methods end // Methods for backward compatibility diff --git a/include/common/daq_generated.h b/include/common/daq_generated.h index c665a9c..c866f71 100644 --- a/include/common/daq_generated.h +++ b/include/common/daq_generated.h @@ -48,6 +48,10 @@ struct Dequantize; struct LRN; +struct Tanh; + +struct Floor; + struct Layer; struct Model; @@ -144,78 +148,68 @@ inline const char *EnumNameFuseCode(FuseCode e) { } enum class LayerType : int8_t { - Conv2D = 0, - AvePool = 1, - MaxPool = 2, - Relu = 3, - Softmax = 4, - FC = 5, - Add = 6, - Concat = 7, - DepthwiseConv2D = 8, - BatchToSpace = 9, - SpaceToBatch = 10, - StridedSlice = 11, - Mul = 12, - AddScalar = 13, - MulScalar = 14, - Dequantize = 15, - LRN = 16, - MIN = Conv2D, - MAX = LRN + Conv2D = 0, + AvePool = 1, + MaxPool = 2, + Relu = 3, + Softmax = 4, + FC = 5, + Add = 6, + Concat = 7, + DepthwiseConv2D = 8, + BatchToSpace = 9, + SpaceToBatch = 10, + StridedSlice = 11, + Mul = 12, + AddScalar = 13, + MulScalar = 14, + Dequantize = 15, + LRN = 16, + Tanh = 17, + Floor = 18, + MIN = Conv2D, + MAX = Floor }; -inline const LayerType (&EnumValuesLayerType())[17] { - static const LayerType values[] = { - LayerType::Conv2D, - LayerType::AvePool, - LayerType::MaxPool, - LayerType::Relu, - LayerType::Softmax, - LayerType::FC, - LayerType::Add, - LayerType::Concat, - LayerType::DepthwiseConv2D, - LayerType::BatchToSpace, - LayerType::SpaceToBatch, - LayerType::StridedSlice, - LayerType::Mul, - LayerType::AddScalar, - LayerType::MulScalar, - LayerType::Dequantize, - LayerType::LRN - }; - return values; +inline const LayerType (&EnumValuesLayerType())[19] { + static const LayerType values[] = {LayerType::Conv2D, + LayerType::AvePool, + LayerType::MaxPool, + LayerType::Relu, + LayerType::Softmax, + LayerType::FC, + LayerType::Add, + LayerType::Concat, + LayerType::DepthwiseConv2D, + LayerType::BatchToSpace, + LayerType::SpaceToBatch, + LayerType::StridedSlice, + LayerType::Mul, + LayerType::AddScalar, + LayerType::MulScalar, + LayerType::Dequantize, + LayerType::LRN, + LayerType::Tanh, + LayerType::Floor}; + return values; } inline const char * const *EnumNamesLayerType() { - static const char * const names[] = { - "Conv2D", - "AvePool", - "MaxPool", - "Relu", - "Softmax", - "FC", - "Add", - "Concat", - "DepthwiseConv2D", - "BatchToSpace", - "SpaceToBatch", - "StridedSlice", - "Mul", - "AddScalar", - "MulScalar", - "Dequantize", - "LRN", - nullptr - }; - return names; + static const char *const names[] = { + "Conv2D", "AvePool", "MaxPool", + "Relu", "Softmax", "FC", + "Add", "Concat", "DepthwiseConv2D", + "BatchToSpace", "SpaceToBatch", "StridedSlice", + "Mul", "AddScalar", "MulScalar", + "Dequantize", "LRN", "Tanh", + "Floor", nullptr}; + return names; } inline const char *EnumNameLayerType(LayerType e) { - if (e < LayerType::Conv2D || e > LayerType::LRN) return ""; - const size_t index = static_cast(e); - return EnumNamesLayerType()[index]; + if (e < LayerType::Conv2D || e > LayerType::Floor) return ""; + const size_t index = static_cast(e); + return EnumNamesLayerType()[index]; } struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { @@ -2184,29 +2178,145 @@ inline flatbuffers::Offset CreateLRNDirect( output__); } +struct Tanh FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_INPUT = 4, + VT_OUTPUT = 6 + }; + const flatbuffers::String *input() const { + return GetPointer(VT_INPUT); + } + const flatbuffers::String *output() const { + return GetPointer(VT_OUTPUT); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_INPUT) && + verifier.VerifyString(input()) && + VerifyOffset(verifier, VT_OUTPUT) && + verifier.VerifyString(output()) && verifier.EndTable(); + } +}; + +struct TanhBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_input(flatbuffers::Offset input) { + fbb_.AddOffset(Tanh::VT_INPUT, input); + } + void add_output(flatbuffers::Offset output) { + fbb_.AddOffset(Tanh::VT_OUTPUT, output); + } + explicit TanhBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + TanhBuilder &operator=(const TanhBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTanh( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset input = 0, + flatbuffers::Offset output = 0) { + TanhBuilder builder_(_fbb); + builder_.add_output(output); + builder_.add_input(input); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTanhDirect( + flatbuffers::FlatBufferBuilder &_fbb, const char *input = nullptr, + const char *output = nullptr) { + auto input__ = input ? _fbb.CreateString(input) : 0; + auto output__ = output ? _fbb.CreateString(output) : 0; + return DNN::CreateTanh(_fbb, input__, output__); +} + +struct Floor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_INPUT = 4, + VT_OUTPUT = 6 + }; + const flatbuffers::String *input() const { + return GetPointer(VT_INPUT); + } + const flatbuffers::String *output() const { + return GetPointer(VT_OUTPUT); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_INPUT) && + verifier.VerifyString(input()) && + VerifyOffset(verifier, VT_OUTPUT) && + verifier.VerifyString(output()) && verifier.EndTable(); + } +}; + +struct FloorBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_input(flatbuffers::Offset input) { + fbb_.AddOffset(Floor::VT_INPUT, input); + } + void add_output(flatbuffers::Offset output) { + fbb_.AddOffset(Floor::VT_OUTPUT, output); + } + explicit FloorBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + FloorBuilder &operator=(const FloorBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateFloor( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset input = 0, + flatbuffers::Offset output = 0) { + FloorBuilder builder_(_fbb); + builder_.add_output(output); + builder_.add_input(input); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateFloorDirect( + flatbuffers::FlatBufferBuilder &_fbb, const char *input = nullptr, + const char *output = nullptr) { + auto input__ = input ? _fbb.CreateString(input) : 0; + auto output__ = output ? _fbb.CreateString(output) : 0; + return DNN::CreateFloor(_fbb, input__, output__); +} + struct Layer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_TYPE = 4, - VT_CONV2D_PARAM = 6, - VT_AVEPOOL_PARAM = 8, - VT_MAXPOOL_PARAM = 10, - VT_RELU_PARAM = 12, - VT_SOFTMAX_PARAM = 14, - VT_FC_PARAM = 16, - VT_ADD_PARAM = 18, - VT_CONCAT_PARAM = 20, - VT_DEPTHWISE_CONV2D_PARAM = 22, - VT_BATCH_TO_SPACE_PARAM = 24, - VT_SPACE_TO_BATCH_PARAM = 26, - VT_STRIDED_SLICE_PARAM = 28, - VT_MUL_PARAM = 30, - VT_ADD_SCALAR_PARAM = 32, - VT_MUL_SCALAR_PARAM = 34, - VT_DEQUANTIZE_PARAM = 36, - VT_LRN_PARAM = 38 - }; - LayerType type() const { - return static_cast(GetField(VT_TYPE, 0)); + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_TYPE = 4, + VT_CONV2D_PARAM = 6, + VT_AVEPOOL_PARAM = 8, + VT_MAXPOOL_PARAM = 10, + VT_RELU_PARAM = 12, + VT_SOFTMAX_PARAM = 14, + VT_FC_PARAM = 16, + VT_ADD_PARAM = 18, + VT_CONCAT_PARAM = 20, + VT_DEPTHWISE_CONV2D_PARAM = 22, + VT_BATCH_TO_SPACE_PARAM = 24, + VT_SPACE_TO_BATCH_PARAM = 26, + VT_STRIDED_SLICE_PARAM = 28, + VT_MUL_PARAM = 30, + VT_ADD_SCALAR_PARAM = 32, + VT_MUL_SCALAR_PARAM = 34, + VT_DEQUANTIZE_PARAM = 36, + VT_LRN_PARAM = 38, + VT_TANH_PARAM = 40, + VT_FLOOR_PARAM = 42 + }; + LayerType type() const { + return static_cast(GetField(VT_TYPE, 0)); } const Conv2D *conv2d_param() const { return GetPointer(VT_CONV2D_PARAM); @@ -2259,44 +2369,53 @@ struct Layer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const LRN *lrn_param() const { return GetPointer(VT_LRN_PARAM); } + const Tanh *tanh_param() const { + return GetPointer(VT_TANH_PARAM); + } + const Floor *floor_param() const { + return GetPointer(VT_FLOOR_PARAM); + } bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_TYPE) && - VerifyOffset(verifier, VT_CONV2D_PARAM) && - verifier.VerifyTable(conv2d_param()) && - VerifyOffset(verifier, VT_AVEPOOL_PARAM) && - verifier.VerifyTable(avepool_param()) && - VerifyOffset(verifier, VT_MAXPOOL_PARAM) && - verifier.VerifyTable(maxpool_param()) && - VerifyOffset(verifier, VT_RELU_PARAM) && - verifier.VerifyTable(relu_param()) && - VerifyOffset(verifier, VT_SOFTMAX_PARAM) && - verifier.VerifyTable(softmax_param()) && - VerifyOffset(verifier, VT_FC_PARAM) && - verifier.VerifyTable(fc_param()) && - VerifyOffset(verifier, VT_ADD_PARAM) && - verifier.VerifyTable(add_param()) && - VerifyOffset(verifier, VT_CONCAT_PARAM) && - verifier.VerifyTable(concat_param()) && - VerifyOffset(verifier, VT_DEPTHWISE_CONV2D_PARAM) && - verifier.VerifyTable(depthwise_conv2d_param()) && - VerifyOffset(verifier, VT_BATCH_TO_SPACE_PARAM) && - verifier.VerifyTable(batch_to_space_param()) && - VerifyOffset(verifier, VT_SPACE_TO_BATCH_PARAM) && - verifier.VerifyTable(space_to_batch_param()) && - VerifyOffset(verifier, VT_STRIDED_SLICE_PARAM) && - verifier.VerifyTable(strided_slice_param()) && - VerifyOffset(verifier, VT_MUL_PARAM) && - verifier.VerifyTable(mul_param()) && - VerifyOffset(verifier, VT_ADD_SCALAR_PARAM) && - verifier.VerifyTable(add_scalar_param()) && - VerifyOffset(verifier, VT_MUL_SCALAR_PARAM) && - verifier.VerifyTable(mul_scalar_param()) && - VerifyOffset(verifier, VT_DEQUANTIZE_PARAM) && - verifier.VerifyTable(dequantize_param()) && - VerifyOffset(verifier, VT_LRN_PARAM) && - verifier.VerifyTable(lrn_param()) && - verifier.EndTable(); + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_TYPE) && + VerifyOffset(verifier, VT_CONV2D_PARAM) && + verifier.VerifyTable(conv2d_param()) && + VerifyOffset(verifier, VT_AVEPOOL_PARAM) && + verifier.VerifyTable(avepool_param()) && + VerifyOffset(verifier, VT_MAXPOOL_PARAM) && + verifier.VerifyTable(maxpool_param()) && + VerifyOffset(verifier, VT_RELU_PARAM) && + verifier.VerifyTable(relu_param()) && + VerifyOffset(verifier, VT_SOFTMAX_PARAM) && + verifier.VerifyTable(softmax_param()) && + VerifyOffset(verifier, VT_FC_PARAM) && + verifier.VerifyTable(fc_param()) && + VerifyOffset(verifier, VT_ADD_PARAM) && + verifier.VerifyTable(add_param()) && + VerifyOffset(verifier, VT_CONCAT_PARAM) && + verifier.VerifyTable(concat_param()) && + VerifyOffset(verifier, VT_DEPTHWISE_CONV2D_PARAM) && + verifier.VerifyTable(depthwise_conv2d_param()) && + VerifyOffset(verifier, VT_BATCH_TO_SPACE_PARAM) && + verifier.VerifyTable(batch_to_space_param()) && + VerifyOffset(verifier, VT_SPACE_TO_BATCH_PARAM) && + verifier.VerifyTable(space_to_batch_param()) && + VerifyOffset(verifier, VT_STRIDED_SLICE_PARAM) && + verifier.VerifyTable(strided_slice_param()) && + VerifyOffset(verifier, VT_MUL_PARAM) && + verifier.VerifyTable(mul_param()) && + VerifyOffset(verifier, VT_ADD_SCALAR_PARAM) && + verifier.VerifyTable(add_scalar_param()) && + VerifyOffset(verifier, VT_MUL_SCALAR_PARAM) && + verifier.VerifyTable(mul_scalar_param()) && + VerifyOffset(verifier, VT_DEQUANTIZE_PARAM) && + verifier.VerifyTable(dequantize_param()) && + VerifyOffset(verifier, VT_LRN_PARAM) && + verifier.VerifyTable(lrn_param()) && + VerifyOffset(verifier, VT_TANH_PARAM) && + verifier.VerifyTable(tanh_param()) && + VerifyOffset(verifier, VT_FLOOR_PARAM) && + verifier.VerifyTable(floor_param()) && verifier.EndTable(); } }; @@ -2357,6 +2476,12 @@ struct LayerBuilder { void add_lrn_param(flatbuffers::Offset lrn_param) { fbb_.AddOffset(Layer::VT_LRN_PARAM, lrn_param); } + void add_tanh_param(flatbuffers::Offset tanh_param) { + fbb_.AddOffset(Layer::VT_TANH_PARAM, tanh_param); + } + void add_floor_param(flatbuffers::Offset floor_param) { + fbb_.AddOffset(Layer::VT_FLOOR_PARAM, floor_param); + } explicit LayerBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -2370,8 +2495,7 @@ struct LayerBuilder { }; inline flatbuffers::Offset CreateLayer( - flatbuffers::FlatBufferBuilder &_fbb, - LayerType type = LayerType::Conv2D, + flatbuffers::FlatBufferBuilder &_fbb, LayerType type = LayerType::Conv2D, flatbuffers::Offset conv2d_param = 0, flatbuffers::Offset avepool_param = 0, flatbuffers::Offset maxpool_param = 0, @@ -2388,27 +2512,31 @@ inline flatbuffers::Offset CreateLayer( flatbuffers::Offset add_scalar_param = 0, flatbuffers::Offset mul_scalar_param = 0, flatbuffers::Offset dequantize_param = 0, - flatbuffers::Offset lrn_param = 0) { - LayerBuilder builder_(_fbb); - builder_.add_lrn_param(lrn_param); - builder_.add_dequantize_param(dequantize_param); - builder_.add_mul_scalar_param(mul_scalar_param); - builder_.add_add_scalar_param(add_scalar_param); - builder_.add_mul_param(mul_param); - builder_.add_strided_slice_param(strided_slice_param); - builder_.add_space_to_batch_param(space_to_batch_param); - builder_.add_batch_to_space_param(batch_to_space_param); - builder_.add_depthwise_conv2d_param(depthwise_conv2d_param); - builder_.add_concat_param(concat_param); - builder_.add_add_param(add_param); - builder_.add_fc_param(fc_param); - builder_.add_softmax_param(softmax_param); - builder_.add_relu_param(relu_param); - builder_.add_maxpool_param(maxpool_param); - builder_.add_avepool_param(avepool_param); - builder_.add_conv2d_param(conv2d_param); - builder_.add_type(type); - return builder_.Finish(); + flatbuffers::Offset lrn_param = 0, + flatbuffers::Offset tanh_param = 0, + flatbuffers::Offset floor_param = 0) { + LayerBuilder builder_(_fbb); + builder_.add_floor_param(floor_param); + builder_.add_tanh_param(tanh_param); + builder_.add_lrn_param(lrn_param); + builder_.add_dequantize_param(dequantize_param); + builder_.add_mul_scalar_param(mul_scalar_param); + builder_.add_add_scalar_param(add_scalar_param); + builder_.add_mul_param(mul_param); + builder_.add_strided_slice_param(strided_slice_param); + builder_.add_space_to_batch_param(space_to_batch_param); + builder_.add_batch_to_space_param(batch_to_space_param); + builder_.add_depthwise_conv2d_param(depthwise_conv2d_param); + builder_.add_concat_param(concat_param); + builder_.add_add_param(add_param); + builder_.add_fc_param(fc_param); + builder_.add_softmax_param(softmax_param); + builder_.add_relu_param(relu_param); + builder_.add_maxpool_param(maxpool_param); + builder_.add_avepool_param(avepool_param); + builder_.add_conv2d_param(conv2d_param); + builder_.add_type(type); + return builder_.Finish(); } struct Model FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { diff --git a/include/dnnlibrary/ModelBuilder.h b/include/dnnlibrary/ModelBuilder.h index 7de9642..2993bc0 100644 --- a/include/dnnlibrary/ModelBuilder.h +++ b/include/dnnlibrary/ModelBuilder.h @@ -212,6 +212,14 @@ class ModelBuilder { ModelBuilder::Index AddLRN(const std::string &input, int32_t radius, float bias, float alpha, float beta, const std::string &output); +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 + ModelBuilder::Index AddTanh(const std::string &input, + const std::string &output); +#endif // __ANDROID_API__ >= 27 +#if __ANDROID_API__ >= 27 + ModelBuilder::Index AddFloor(const std::string &input, + const std::string &output); #endif // __ANDROID_API__ >= 27 // ModelBuilder auto generated methods end Index AddDepthWiseConv( diff --git a/include/tools/onnx2daq/OnnxConverter.h b/include/tools/onnx2daq/OnnxConverter.h index d72ea1c..7b3d9cb 100644 --- a/include/tools/onnx2daq/OnnxConverter.h +++ b/include/tools/onnx2daq/OnnxConverter.h @@ -158,6 +158,8 @@ class OnnxConverter { const std::string &output); void AddLayerLRN(const std::string &input, int32_t radius, float bias, float alpha, float beta, const std::string &output); + void AddLayerTanh(const std::string &input, const std::string &output); + void AddLayerFloor(const std::string &input, const std::string &output); // OnnxConverter auto generated methods end /** diff --git a/ops.yml b/ops.yml index 32d7cd4..01af043 100644 --- a/ops.yml +++ b/ops.yml @@ -417,3 +417,11 @@ shaper: Identity pos: 16 api: 27 +- + name: Tanh + shaper: Identity + api: 27 +- + name: Floor + shaper: Identity + api: 27 diff --git a/tools/onnx2daq/OnnxConverter.cpp b/tools/onnx2daq/OnnxConverter.cpp index d17a4df..80be976 100644 --- a/tools/onnx2daq/OnnxConverter.cpp +++ b/tools/onnx2daq/OnnxConverter.cpp @@ -849,6 +849,52 @@ void OnnxConverter::AddLayerLRN(const std::string &input, int32_t radius, layers_.push_back(layer); } +void OnnxConverter::AddLayerTanh(const std::string &input, + const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Identity(m(input), output); + const auto param = + DNN::CreateTanhDirect(builder_, m(input).c_str(), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::Tanh, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerFloor(const std::string &input, + const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Identity(m(input), output); + const auto param = + DNN::CreateFloorDirect(builder_, m(input).c_str(), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::Floor, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + // OnnxConverter auto generated methods end void OnnxConverter::SetIdentity(css &input_name, css &output_name) { @@ -1079,7 +1125,8 @@ std::pair OnnxConverter::IsNodeSupported( "Softmax", "Concat", "Dropout", "BatchNormalization", "Reshape", "LRN", - "Identity"}; + "Identity", "Tanh", + "Floor"}; if (std::find(supported_types.begin(), supported_types.end(), op) == supported_types.end()) { return {false, "Unsupported operator " + op}; @@ -1514,6 +1561,18 @@ void OnnxConverter::Convert(const ONNX_NAMESPACE::ModelProto &model_proto, AddLayerLRN(node.input(0), radius, bias, alpha, beta, node.output(0)); VLOG(5) << "Converting LRN completed"; + } else if (op == "Tanh") { + VLOG(5) << "Start converting Tanh"; + const auto input_name = m(node.input(0)); + const auto output_name = m(node.output(0)); + AddLayerTanh(input_name, output_name); + VLOG(5) << "Converting Tanh completed"; + } else if (op == "Floor") { + VLOG(5) << "Start converting Floor"; + const auto input_name = m(node.input(0)); + const auto output_name = m(node.output(0)); + AddLayerFloor(input_name, output_name); + VLOG(5) << "Converting Floor completed"; } else { throw std::invalid_argument("Unsupported operator " + op); } From 27197343d18c984ae42bb337e021db0702fe0291 Mon Sep 17 00:00:00 2001 From: daquexian Date: Tue, 6 Aug 2019 14:17:43 +0800 Subject: [PATCH 3/6] Move op implementation of OnnxConverterImpl into OnnxConverterImpl.cpp --- tools/onnx2daq/CMakeLists.txt | 1 + tools/onnx2daq/OnnxConverter.cpp | 674 -------------------------- tools/onnx2daq/OnnxConverterImpl.cpp | 686 +++++++++++++++++++++++++++ 3 files changed, 687 insertions(+), 674 deletions(-) create mode 100644 tools/onnx2daq/OnnxConverterImpl.cpp diff --git a/tools/onnx2daq/CMakeLists.txt b/tools/onnx2daq/CMakeLists.txt index 2301d2e..077a531 100644 --- a/tools/onnx2daq/CMakeLists.txt +++ b/tools/onnx2daq/CMakeLists.txt @@ -3,6 +3,7 @@ # message(${CMAKE_CURRENT_BINARY_DIR}) add_library(onnx2daq ${CMAKE_CURRENT_SOURCE_DIR}/OnnxConverter.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/OnnxConverterImpl.cpp ${PROJECT_SOURCE_DIR}/include/tools/onnx2daq/OnnxConverter.h ${CMAKE_CURRENT_SOURCE_DIR}/NodeAttrHelper.cpp ${CMAKE_CURRENT_SOURCE_DIR}/NodeAttrHelper.h diff --git a/tools/onnx2daq/OnnxConverter.cpp b/tools/onnx2daq/OnnxConverter.cpp index 80be976..4d36f8c 100644 --- a/tools/onnx2daq/OnnxConverter.cpp +++ b/tools/onnx2daq/OnnxConverter.cpp @@ -222,680 +222,6 @@ OnnxConverter::Tensor OnnxConverter::OnnxToNnapiIdentity(const Tensor &src) { return src; } -void OnnxConverter::AddConv(const string &input_name, - const std::vector &strides, - const std::vector &pads, - const std::vector &dilations, int group, - const string &ori_weight_name, - const dnn::optional &bias_name, - const string &output_name) { - flatbuffers::Offset layer; - if (dilations != vector{1, 1}) { - if (strides != vector{1, 1}) { - throw std::invalid_argument( - "Both dilations and strides > 1 is not supported for now"); - } - VLOG(5) << "Dilations of conv: " << dilations << ", converting.."; - const auto s2b_name = input_name + "_s2b"; - const auto im_name = input_name + "_conv_imm"; - const auto b2s_name = input_name + "_b2s"; - std::vector new_pads = pads; - const auto input_shape = shaper_[input_name]; - new_pads[1] = (input_shape[1] + pads[1] + (dilations[0] - 1)) / - dilations[0] * dilations[0] - - input_shape[1]; - new_pads[3] = (input_shape[2] + pads[3] + (dilations[1] - 1)) / - dilations[1] * dilations[1] - - input_shape[2]; - VLOG(5) << input_shape << ", " << pads << ", " << dilations << ", " - << new_pads; - // Why "AllowShortBlocksOnASingleLine: false" doesn't work on it? - // clang-format off - { - AddLayerSpaceToBatchND(input_name, dilations, new_pads, s2b_name); - } - // clang-format on - { - // paddings are applied in spacetobatch - AddConv(s2b_name, strides, vector{0, 0, 0, 0}, - vector{1, 1}, group, ori_weight_name, bias_name, - im_name); - } - // clang-format off - { - AddLayerBatchToSpaceND(im_name, dilations, b2s_name); - } - // clang-format on - { - const auto b2s_shape = shaper_[b2s_name]; - const std::vector starts{0, 0, 0, 0}; - const std::vector ends{ - static_cast(b2s_shape[0]), - static_cast(b2s_shape[1]) - (new_pads[1] - pads[0]), - static_cast(b2s_shape[2]) - (new_pads[3] - pads[3]), - static_cast(b2s_shape[3])}; - const std::vector strides_in_ss{1, 1, 1, 1}; - const int32_t begin_mask = 0; - const int32_t end_mask = 0; - const int32_t shrink_axis_mask = 0; - AddLayerStridedSlice(b2s_name, starts, ends, strides_in_ss, - begin_mask, end_mask, shrink_axis_mask, - output_name); - } - return; - } - - if (!onnx_tensors_.has(ori_weight_name)) { - throw std::invalid_argument("The weight of convolution must be known"); - } - const auto &onnx_weight = onnx_tensors_.at(ori_weight_name); - if (group == 1) { - VLOG(5) << "Vanilla conv"; - AddLayerConvImpl(input_name, ori_weight_name, bias_name, pads, strides, - output_name); - } else if (onnx_weight.shape[1] == 1) { // depthwise - VLOG(5) << "Depthwise conv"; - AddLayerDepthwiseConvImpl(input_name, ori_weight_name, bias_name, pads, - strides, onnx_weight.shape[0] / group, - output_name); - } else { - // TODO: Support it - throw std::invalid_argument("group != 1 is not supported"); - } -} - -void OnnxConverter::AddLayerPool(css &op, css &input_name, - const std::vector &kernel_shape, - const std::vector &pads, - const std::vector &strides, - css &output_name) { - if (op == "AveragePool" || op == "GlobalAveragePool") { - AddLayerAvePoolImpl(input_name, kernel_shape, pads, strides, - output_name); - } else { - AddLayerMaxPoolImpl(input_name, kernel_shape, pads, strides, - output_name); - } -} - -// OnnxConverter auto generated methods start -void OnnxConverter::AddLayerConvImpl(const std::string &input, - const std::string &weight, - const dnn::optional &bias, - const std::vector &pads, - const std::vector &strides, - const std::string &output) { - const auto activation = FindActivation(model_proto_, output); - - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - { - const auto name = weight; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - if (bias.has_value()) { - const auto name = bias.value(); - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiIdentity(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Conv(m(input), m(weight), pads, strides, output); - const auto param = DNN::CreateConv2DDirect( - builder_, m(input).c_str(), m(weight).c_str(), - bias.has_value() ? bias.value().c_str() : nullptr, &pads, &strides, - ConvertFuseCodeType(activation.second), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::Conv2D, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerAvePoolImpl( - const std::string &input, const std::vector &kernel_shape, - const std::vector &pads, const std::vector &strides, - const std::string &output) { - const auto activation = FindActivation(model_proto_, output); - - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Pool(m(input), kernel_shape, pads, strides, output); - const auto param = DNN::CreateAvePoolDirect( - builder_, m(input).c_str(), &kernel_shape, &pads, &strides, - ConvertFuseCodeType(activation.second), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::AvePool, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerMaxPoolImpl( - const std::string &input, const std::vector &kernel_shape, - const std::vector &pads, const std::vector &strides, - const std::string &output) { - const auto activation = FindActivation(model_proto_, output); - - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Pool(m(input), kernel_shape, pads, strides, output); - const auto param = DNN::CreateMaxPoolDirect( - builder_, m(input).c_str(), &kernel_shape, &pads, &strides, - ConvertFuseCodeType(activation.second), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::MaxPool, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerReLU(const std::string &input, - const std::string &output) { - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Relu(m(input), output); - const auto param = - DNN::CreateReluDirect(builder_, m(input).c_str(), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::Relu, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerSoftmax(const std::string &input, - const std::string &output) { - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Softmax(m(input), output); - const auto param = - DNN::CreateSoftmaxDirect(builder_, m(input).c_str(), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::Softmax, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerFC(const std::string &input, - const std::string &weight, - const dnn::optional &bias, - const std::string &output) { - const auto activation = FindActivation(model_proto_, output); - - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - { - const auto name = weight; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiIdentity(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - if (bias.has_value()) { - const auto name = bias.value(); - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiIdentity(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.FC(m(input), m(weight), output); - const auto param = DNN::CreateFCDirect( - builder_, m(input).c_str(), m(weight).c_str(), - bias.has_value() ? bias.value().c_str() : nullptr, - ConvertFuseCodeType(activation.second), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::FC, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerAdd(const std::string &input1, - const std::string &input2, - const std::string &output) { - const auto activation = FindActivation(model_proto_, output); - - { - const auto name = input1; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - { - const auto name = input2; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Eltwise(m(input1), m(input2), output); - const auto param = DNN::CreateAddDirect( - builder_, m(input1).c_str(), m(input2).c_str(), - ConvertFuseCodeType(activation.second), output.c_str()); - const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::Add, 0, 0, 0, - 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerConcat(const std::vector &inputs, - int32_t axis, const std::string &output) { - for (const auto &name : inputs) { - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - const auto inputs_fb = FbStrVector(inputs); - shaper_.Concat(inputs, axis, output); - const auto param = - DNN::CreateConcatDirect(builder_, &inputs_fb, axis, output.c_str()); - const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::Concat, 0, 0, - 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerDepthwiseConvImpl( - const std::string &input, const std::string &weight, - const dnn::optional &bias, const std::vector &pads, - const std::vector &strides, int32_t depth_multiplier, - const std::string &output) { - const auto activation = FindActivation(model_proto_, output); - - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - { - const auto name = weight; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes1230(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - if (bias.has_value()) { - const auto name = bias.value(); - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiIdentity(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.DepthwiseConv(m(input), m(weight), pads, strides, output); - const auto param = DNN::CreateDepthwiseConv2DDirect( - builder_, m(input).c_str(), m(weight).c_str(), - bias.has_value() ? bias.value().c_str() : nullptr, &pads, &strides, - depth_multiplier, ConvertFuseCodeType(activation.second), - output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::DepthwiseConv2D, 0, 0, 0, 0, - 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerBatchToSpaceND( - const std::string &input, const std::vector &block_sizes, - const std::string &output) { - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.BatchToSpace(m(input), block_sizes, output); - const auto param = DNN::CreateBatchToSpaceDirect( - builder_, m(input).c_str(), &block_sizes, output.c_str()); - const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::BatchToSpace, - 0, 0, 0, 0, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerSpaceToBatchND( - const std::string &input, const std::vector &block_sizes, - const std::vector &pads, const std::string &output) { - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.SpaceToBatch(m(input), block_sizes, pads, output); - const auto param = DNN::CreateSpaceToBatchDirect( - builder_, m(input).c_str(), &block_sizes, &pads, output.c_str()); - const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::SpaceToBatch, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerStridedSlice(const std::string &input, - const std::vector &starts, - const std::vector &ends, - const std::vector &strides, - int32_t begin_mask, int32_t end_mask, - int32_t shrink_axis_mask, - const std::string &output) { - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.StridedSlice(m(input), starts, ends, strides, begin_mask, end_mask, - shrink_axis_mask, output); - const auto param = DNN::CreateStridedSliceDirect( - builder_, m(input).c_str(), &starts, &ends, &strides, begin_mask, - end_mask, shrink_axis_mask, output.c_str()); - const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::StridedSlice, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerMul(const std::string &input1, - const std::string &input2, - const std::string &output) { - const auto activation = FindActivation(model_proto_, output); - - { - const auto name = input1; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - { - const auto name = input2; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Eltwise(m(input1), m(input2), output); - const auto param = DNN::CreateMulDirect( - builder_, m(input1).c_str(), m(input2).c_str(), - ConvertFuseCodeType(activation.second), output.c_str()); - const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::Mul, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerAdd(const std::string &input, float scalar, - const std::string &output) { - const auto activation = FindActivation(model_proto_, output); - - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Eltwise(m(input), output); - const auto param = DNN::CreateAddScalarDirect( - builder_, m(input).c_str(), scalar, - ConvertFuseCodeType(activation.second), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::AddScalar, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerMul(const std::string &input, float scalar, - const std::string &output) { - const auto activation = FindActivation(model_proto_, output); - - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Eltwise(m(input), output); - const auto param = DNN::CreateMulScalarDirect( - builder_, m(input).c_str(), scalar, - ConvertFuseCodeType(activation.second), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::MulScalar, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerDequantize(const std::string &input, - const std::string &output) { - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Identity(m(input), output); - const auto param = - DNN::CreateDequantizeDirect(builder_, m(input).c_str(), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::Dequantize, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerLRN(const std::string &input, int32_t radius, - float bias, float alpha, float beta, - const std::string &output) { - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Identity(m(input), output); - const auto param = DNN::CreateLRNDirect(builder_, m(input).c_str(), radius, - bias, alpha, beta, output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::LRN, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerTanh(const std::string &input, - const std::string &output) { - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Identity(m(input), output); - const auto param = - DNN::CreateTanhDirect(builder_, m(input).c_str(), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::Tanh, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -void OnnxConverter::AddLayerFloor(const std::string &input, - const std::string &output) { - { - const auto name = input; - - if (onnx_tensors_.has(name)) { - const auto &onnx_tensor = onnx_tensors_.at(name); - const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); - shaper_.AddShape(name, new_tensor.shape); - nnapi_tensors_[name] = new_tensor; - CreateTensorFb(name, new_tensor); - } - } - - shaper_.Identity(m(input), output); - const auto param = - DNN::CreateFloorDirect(builder_, m(input).c_str(), output.c_str()); - const auto layer = - DNN::CreateLayer(builder_, DNN::LayerType::Floor, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, param); - layers_.push_back(layer); -} - -// OnnxConverter auto generated methods end void OnnxConverter::SetIdentity(css &input_name, css &output_name) { // Dropout does nothing, so the output is the same as the input diff --git a/tools/onnx2daq/OnnxConverterImpl.cpp b/tools/onnx2daq/OnnxConverterImpl.cpp new file mode 100644 index 0000000..37dc1a1 --- /dev/null +++ b/tools/onnx2daq/OnnxConverterImpl.cpp @@ -0,0 +1,686 @@ +#include + +#include +#include "NodeAttrHelper.h" + +using std::string; +using std::vector; +using Shape = Shaper::Shape; + +namespace dnn { +void OnnxConverter::AddConv(const string &input_name, + const std::vector &strides, + const std::vector &pads, + const std::vector &dilations, int group, + const string &ori_weight_name, + const dnn::optional &bias_name, + const string &output_name) { + flatbuffers::Offset layer; + if (dilations != vector{1, 1}) { + if (strides != vector{1, 1}) { + throw std::invalid_argument( + "Both dilations and strides > 1 is not supported for now"); + } + VLOG(5) << "Dilations of conv: " << dilations << ", converting.."; + const auto s2b_name = input_name + "_s2b"; + const auto im_name = input_name + "_conv_imm"; + const auto b2s_name = input_name + "_b2s"; + std::vector new_pads = pads; + const auto input_shape = shaper_[input_name]; + new_pads[1] = (input_shape[1] + pads[1] + (dilations[0] - 1)) / + dilations[0] * dilations[0] - + input_shape[1]; + new_pads[3] = (input_shape[2] + pads[3] + (dilations[1] - 1)) / + dilations[1] * dilations[1] - + input_shape[2]; + VLOG(5) << input_shape << ", " << pads << ", " << dilations << ", " + << new_pads; + // Why "AllowShortBlocksOnASingleLine: false" doesn't work on it? + // clang-format off + { + AddLayerSpaceToBatchND(input_name, dilations, new_pads, s2b_name); + } + // clang-format on + { + // paddings are applied in spacetobatch + AddConv(s2b_name, strides, vector{0, 0, 0, 0}, + vector{1, 1}, group, ori_weight_name, bias_name, + im_name); + } + // clang-format off + { + AddLayerBatchToSpaceND(im_name, dilations, b2s_name); + } + // clang-format on + { + const auto b2s_shape = shaper_[b2s_name]; + const std::vector starts{0, 0, 0, 0}; + const std::vector ends{ + static_cast(b2s_shape[0]), + static_cast(b2s_shape[1]) - (new_pads[1] - pads[0]), + static_cast(b2s_shape[2]) - (new_pads[3] - pads[3]), + static_cast(b2s_shape[3])}; + const std::vector strides_in_ss{1, 1, 1, 1}; + const int32_t begin_mask = 0; + const int32_t end_mask = 0; + const int32_t shrink_axis_mask = 0; + AddLayerStridedSlice(b2s_name, starts, ends, strides_in_ss, + begin_mask, end_mask, shrink_axis_mask, + output_name); + } + return; + } + + if (!onnx_tensors_.has(ori_weight_name)) { + throw std::invalid_argument("The weight of convolution must be known"); + } + const auto &onnx_weight = onnx_tensors_.at(ori_weight_name); + if (group == 1) { + VLOG(5) << "Vanilla conv"; + AddLayerConvImpl(input_name, ori_weight_name, bias_name, pads, strides, + output_name); + } else if (onnx_weight.shape[1] == 1) { // depthwise + VLOG(5) << "Depthwise conv"; + AddLayerDepthwiseConvImpl(input_name, ori_weight_name, bias_name, pads, + strides, onnx_weight.shape[0] / group, + output_name); + } else { + // TODO: Support it + throw std::invalid_argument("group != 1 is not supported"); + } +} + +void OnnxConverter::AddLayerPool(css &op, css &input_name, + const std::vector &kernel_shape, + const std::vector &pads, + const std::vector &strides, + css &output_name) { + if (op == "AveragePool" || op == "GlobalAveragePool") { + AddLayerAvePoolImpl(input_name, kernel_shape, pads, strides, + output_name); + } else { + AddLayerMaxPoolImpl(input_name, kernel_shape, pads, strides, + output_name); + } +} + +// OnnxConverter auto generated methods start +void OnnxConverter::AddLayerConvImpl(const std::string &input, + const std::string &weight, + const dnn::optional &bias, + const std::vector &pads, + const std::vector &strides, + const std::string &output) { + const auto activation = FindActivation(model_proto_, output); + + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + { + const auto name = weight; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + if (bias.has_value()) { + const auto name = bias.value(); + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiIdentity(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Conv(m(input), m(weight), pads, strides, output); + const auto param = DNN::CreateConv2DDirect( + builder_, m(input).c_str(), m(weight).c_str(), + bias.has_value() ? bias.value().c_str() : nullptr, &pads, &strides, + ConvertFuseCodeType(activation.second), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::Conv2D, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerAvePoolImpl( + const std::string &input, const std::vector &kernel_shape, + const std::vector &pads, const std::vector &strides, + const std::string &output) { + const auto activation = FindActivation(model_proto_, output); + + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Pool(m(input), kernel_shape, pads, strides, output); + const auto param = DNN::CreateAvePoolDirect( + builder_, m(input).c_str(), &kernel_shape, &pads, &strides, + ConvertFuseCodeType(activation.second), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::AvePool, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerMaxPoolImpl( + const std::string &input, const std::vector &kernel_shape, + const std::vector &pads, const std::vector &strides, + const std::string &output) { + const auto activation = FindActivation(model_proto_, output); + + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Pool(m(input), kernel_shape, pads, strides, output); + const auto param = DNN::CreateMaxPoolDirect( + builder_, m(input).c_str(), &kernel_shape, &pads, &strides, + ConvertFuseCodeType(activation.second), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::MaxPool, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerReLU(const std::string &input, + const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Relu(m(input), output); + const auto param = + DNN::CreateReluDirect(builder_, m(input).c_str(), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::Relu, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerSoftmax(const std::string &input, + const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Softmax(m(input), output); + const auto param = + DNN::CreateSoftmaxDirect(builder_, m(input).c_str(), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::Softmax, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerFC(const std::string &input, + const std::string &weight, + const dnn::optional &bias, + const std::string &output) { + const auto activation = FindActivation(model_proto_, output); + + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + { + const auto name = weight; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiIdentity(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + if (bias.has_value()) { + const auto name = bias.value(); + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiIdentity(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.FC(m(input), m(weight), output); + const auto param = DNN::CreateFCDirect( + builder_, m(input).c_str(), m(weight).c_str(), + bias.has_value() ? bias.value().c_str() : nullptr, + ConvertFuseCodeType(activation.second), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::FC, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerAdd(const std::string &input1, + const std::string &input2, + const std::string &output) { + const auto activation = FindActivation(model_proto_, output); + + { + const auto name = input1; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + { + const auto name = input2; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Eltwise(m(input1), m(input2), output); + const auto param = DNN::CreateAddDirect( + builder_, m(input1).c_str(), m(input2).c_str(), + ConvertFuseCodeType(activation.second), output.c_str()); + const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::Add, 0, 0, 0, + 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerConcat(const std::vector &inputs, + int32_t axis, const std::string &output) { + for (const auto &name : inputs) { + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + const auto inputs_fb = FbStrVector(inputs); + shaper_.Concat(inputs, axis, output); + const auto param = + DNN::CreateConcatDirect(builder_, &inputs_fb, axis, output.c_str()); + const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::Concat, 0, 0, + 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerDepthwiseConvImpl( + const std::string &input, const std::string &weight, + const dnn::optional &bias, const std::vector &pads, + const std::vector &strides, int32_t depth_multiplier, + const std::string &output) { + const auto activation = FindActivation(model_proto_, output); + + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + { + const auto name = weight; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes1230(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + if (bias.has_value()) { + const auto name = bias.value(); + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiIdentity(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.DepthwiseConv(m(input), m(weight), pads, strides, output); + const auto param = DNN::CreateDepthwiseConv2DDirect( + builder_, m(input).c_str(), m(weight).c_str(), + bias.has_value() ? bias.value().c_str() : nullptr, &pads, &strides, + depth_multiplier, ConvertFuseCodeType(activation.second), + output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::DepthwiseConv2D, 0, 0, 0, 0, + 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerBatchToSpaceND( + const std::string &input, const std::vector &block_sizes, + const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.BatchToSpace(m(input), block_sizes, output); + const auto param = DNN::CreateBatchToSpaceDirect( + builder_, m(input).c_str(), &block_sizes, output.c_str()); + const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::BatchToSpace, + 0, 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerSpaceToBatchND( + const std::string &input, const std::vector &block_sizes, + const std::vector &pads, const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.SpaceToBatch(m(input), block_sizes, pads, output); + const auto param = DNN::CreateSpaceToBatchDirect( + builder_, m(input).c_str(), &block_sizes, &pads, output.c_str()); + const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::SpaceToBatch, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerStridedSlice(const std::string &input, + const std::vector &starts, + const std::vector &ends, + const std::vector &strides, + int32_t begin_mask, int32_t end_mask, + int32_t shrink_axis_mask, + const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.StridedSlice(m(input), starts, ends, strides, begin_mask, end_mask, + shrink_axis_mask, output); + const auto param = DNN::CreateStridedSliceDirect( + builder_, m(input).c_str(), &starts, &ends, &strides, begin_mask, + end_mask, shrink_axis_mask, output.c_str()); + const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::StridedSlice, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerMul(const std::string &input1, + const std::string &input2, + const std::string &output) { + const auto activation = FindActivation(model_proto_, output); + + { + const auto name = input1; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + { + const auto name = input2; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Eltwise(m(input1), m(input2), output); + const auto param = DNN::CreateMulDirect( + builder_, m(input1).c_str(), m(input2).c_str(), + ConvertFuseCodeType(activation.second), output.c_str()); + const auto layer = DNN::CreateLayer(builder_, DNN::LayerType::Mul, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerAdd(const std::string &input, float scalar, + const std::string &output) { + const auto activation = FindActivation(model_proto_, output); + + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Eltwise(m(input), output); + const auto param = DNN::CreateAddScalarDirect( + builder_, m(input).c_str(), scalar, + ConvertFuseCodeType(activation.second), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::AddScalar, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerMul(const std::string &input, float scalar, + const std::string &output) { + const auto activation = FindActivation(model_proto_, output); + + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Eltwise(m(input), output); + const auto param = DNN::CreateMulScalarDirect( + builder_, m(input).c_str(), scalar, + ConvertFuseCodeType(activation.second), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::MulScalar, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerDequantize(const std::string &input, + const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Identity(m(input), output); + const auto param = + DNN::CreateDequantizeDirect(builder_, m(input).c_str(), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::Dequantize, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerLRN(const std::string &input, int32_t radius, + float bias, float alpha, float beta, + const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Identity(m(input), output); + const auto param = DNN::CreateLRNDirect(builder_, m(input).c_str(), radius, + bias, alpha, beta, output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::LRN, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerTanh(const std::string &input, + const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Identity(m(input), output); + const auto param = + DNN::CreateTanhDirect(builder_, m(input).c_str(), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::Tanh, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +void OnnxConverter::AddLayerFloor(const std::string &input, + const std::string &output) { + { + const auto name = input; + + if (onnx_tensors_.has(name)) { + const auto &onnx_tensor = onnx_tensors_.at(name); + const auto new_tensor = OnnxToNnapiAxes0231(onnx_tensor); + shaper_.AddShape(name, new_tensor.shape); + nnapi_tensors_[name] = new_tensor; + CreateTensorFb(name, new_tensor); + } + } + + shaper_.Identity(m(input), output); + const auto param = + DNN::CreateFloorDirect(builder_, m(input).c_str(), output.c_str()); + const auto layer = + DNN::CreateLayer(builder_, DNN::LayerType::Floor, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, param); + layers_.push_back(layer); +} + +// OnnxConverter auto generated methods end + +} // namespace dnn From d093f6bc41bf761a537b56fa9116a77e695f01cd Mon Sep 17 00:00:00 2001 From: daquexian Date: Tue, 6 Aug 2019 19:22:01 +0800 Subject: [PATCH 4/6] Add missing code in DaqReader --- dnnlibrary/DaqReader.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/dnnlibrary/DaqReader.cpp b/dnnlibrary/DaqReader.cpp index abbae5f..0c87450 100644 --- a/dnnlibrary/DaqReader.cpp +++ b/dnnlibrary/DaqReader.cpp @@ -53,6 +53,10 @@ std::string layer_type_to_str(DNN::LayerType type) { return "dequantize"; case DNN::LayerType::LRN: return "LRN"; + case DNN::LayerType::Tanh: + return "tanh"; + case DNN::LayerType::Floor: + return "floor"; } } @@ -259,7 +263,7 @@ void AddLayers(const DNN::Model &model, ModelBuilder &builder) { } case DNN::LayerType::Softmax: { UNPACK_LAYER(softmax, input, output); - builder.AddSoftMax(input, 1.f, output); + builder.AddSoftmax(input, 1.f, output); break; } case DNN::LayerType::Concat: { @@ -300,6 +304,14 @@ void AddLayers(const DNN::Model &model, ModelBuilder &builder) { ADD_LAYER(lrn, LRN, input, radius, bias, alpha, beta, output); break; } + case DNN::LayerType::Tanh: { + ADD_LAYER(tanh, Tanh, input, output); + break; + } + case DNN::LayerType::Floor: { + ADD_LAYER(floor, Floor, input, output); + break; + } } } } From 5f76678f22feb51b970b0d66aedff684176b7d60 Mon Sep 17 00:00:00 2001 From: daquexian Date: Tue, 6 Aug 2019 19:22:28 +0800 Subject: [PATCH 5/6] Remove unused function declaration in ModelBuilder.h --- include/dnnlibrary/ModelBuilder.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/dnnlibrary/ModelBuilder.h b/include/dnnlibrary/ModelBuilder.h index 2993bc0..9facca2 100644 --- a/include/dnnlibrary/ModelBuilder.h +++ b/include/dnnlibrary/ModelBuilder.h @@ -256,8 +256,6 @@ class ModelBuilder { int32_t activation, PoolingType poolingType, const std::string &output_name, const dnn::optional &output_quant_info = dnn::nullopt); - Index AddSoftMax(const std::string &input_name, float beta, - const std::string &output_name); Index AddOperationAdd(const std::string &input_name, float scalar, std::string output_name); Index AddOperationAdd( From 589611c50bc903226e40ae2de409cf42c9eb3eaf Mon Sep 17 00:00:00 2001 From: daquexian Date: Tue, 6 Aug 2019 19:22:40 +0800 Subject: [PATCH 6/6] Move template function --- dnnlibrary/ModelBuilder.cpp | 21 --------------------- dnnlibrary/ModelBuilderImpl.cpp | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/dnnlibrary/ModelBuilder.cpp b/dnnlibrary/ModelBuilder.cpp index 2f12c86..52c7cbc 100644 --- a/dnnlibrary/ModelBuilder.cpp +++ b/dnnlibrary/ModelBuilder.cpp @@ -266,27 +266,6 @@ ModelBuilder::Shape ModelBuilder::GetBlobDim(uint32_t index) { throw std::invalid_argument("Wrong index in GetBlobDim"); } -template -ModelBuilder::IndexSeq ModelBuilder::AddOperation( - int op, IndexSeq input_indexes, OperandTypes... operand_types) { - using android::nn::wrapper::OperandType; - vector types; - (types.push_back(operand_types), ...); - IndexSeq output_indexes; - for (const auto &type : types) { - auto index = AddNewOperand(type); - output_indexes.push_back(index); - } - - THROW_ON_ERROR_WITH_NOTE( - nnapi_->ANeuralNetworksModel_addOperation( - dnn_model_->model_, op, input_indexes.size(), &input_indexes[0], - output_indexes.size(), &output_indexes[0]), - "op = " + std::to_string(op)); - - return output_indexes; -} - void ModelBuilder::Prepare() { dnn_model_ = std::unique_ptr(new Model()); const auto ret = nnapi_->ANeuralNetworksModel_create(&dnn_model_->model_); diff --git a/dnnlibrary/ModelBuilderImpl.cpp b/dnnlibrary/ModelBuilderImpl.cpp index febaf81..df9873e 100644 --- a/dnnlibrary/ModelBuilderImpl.cpp +++ b/dnnlibrary/ModelBuilderImpl.cpp @@ -632,4 +632,26 @@ ModelBuilder::Index ModelBuilder::AddMul( return AddMul(input1_name, input2_name, ANEURALNETWORKS_FUSED_NONE, output_name, output_quant_info); } + +template +ModelBuilder::IndexSeq ModelBuilder::AddOperation( + int op, IndexSeq input_indexes, OperandTypes... operand_types) { + using android::nn::wrapper::OperandType; + std::vector types; + (types.push_back(operand_types), ...); + IndexSeq output_indexes; + for (const auto &type : types) { + auto index = AddNewOperand(type); + output_indexes.push_back(index); + } + + THROW_ON_ERROR_WITH_NOTE( + nnapi_->ANeuralNetworksModel_addOperation( + dnn_model_->model_, op, input_indexes.size(), &input_indexes[0], + output_indexes.size(), &output_indexes[0]), + "op = " + std::to_string(op)); + + return output_indexes; +} + } // namespace dnn