From: @YeFeng_24 Reviewed-by: Signed-off-by:tags/v1.2.0-rc1
| @@ -78,34 +78,19 @@ Registry BatchToSpaceRegistry(schema::PrimitiveType_BatchToSpace, BatchToSpaceCr | |||||
| namespace { | namespace { | ||||
| constexpr int kBatchToSpaceOutputNum = 1; | constexpr int kBatchToSpaceOutputNum = 1; | ||||
| constexpr int kBatchToSpaceInputNum = 1; | |||||
| constexpr int kBatchToSpaceOneInput = 1; | |||||
| constexpr int kBatchToSpaceThreeInput = 3; | |||||
| constexpr int kBlockShapeSize = 2; | constexpr int kBlockShapeSize = 2; | ||||
| constexpr int kCropsSize = 4; | constexpr int kCropsSize = 4; | ||||
| } // namespace | } // namespace | ||||
| int BatchToSpace::InferShape(std::vector<lite::Tensor *> inputs, std::vector<lite::Tensor *> outputs) { | |||||
| MS_ASSERT(this->primitive_ != nullptr); | |||||
| if (outputs.size() != kBatchToSpaceOutputNum || inputs.size() != kBatchToSpaceInputNum) { | |||||
| MS_LOG(ERROR) << "Invalid output/input size! output size: " << outputs.size() << ",input size: " << inputs.size(); | |||||
| return RET_PARAM_INVALID; | |||||
| } | |||||
| auto input = inputs.at(0); | |||||
| if (input->format() != schema::Format::Format_NHWC) { | |||||
| MS_LOG(ERROR) << "batch_to_space only support NHWC now!"; | |||||
| return RET_FORMAT_ERR; | |||||
| } | |||||
| outputs[0]->set_format(input->format()); | |||||
| outputs[0]->set_data_type(input->data_type()); | |||||
| if (!infer_flag()) { | |||||
| return RET_INFER_INVALID; | |||||
| } | |||||
| auto input_shape = input->shape(); | |||||
| int BatchToSpace::SetOutputShapeFromParam(const std::vector<lite::Tensor *> inputs, | |||||
| std::vector<lite::Tensor *> outputs) { | |||||
| auto input_shape = inputs[0]->shape(); | |||||
| if (input_shape.size() != kQuadrupleNum) { | if (input_shape.size() != kQuadrupleNum) { | ||||
| MS_LOG(ERROR) << "input shape dimension size should == " << kQuadrupleNum; | MS_LOG(ERROR) << "input shape dimension size should == " << kQuadrupleNum; | ||||
| return RET_PARAM_INVALID; | return RET_PARAM_INVALID; | ||||
| } | } | ||||
| auto block_shape = GetBlockShape(); | auto block_shape = GetBlockShape(); | ||||
| if (block_shape.size() != kBlockShapeSize) { | if (block_shape.size() != kBlockShapeSize) { | ||||
| MS_LOG(ERROR) << "Block shape size should be " << kBlockShapeSize; | MS_LOG(ERROR) << "Block shape size should be " << kBlockShapeSize; | ||||
| @@ -116,7 +101,7 @@ int BatchToSpace::InferShape(std::vector<lite::Tensor *> inputs, std::vector<lit | |||||
| MS_LOG(ERROR) << "Crops size should be " << kCropsSize; | MS_LOG(ERROR) << "Crops size should be " << kCropsSize; | ||||
| return RET_PARAM_INVALID; | return RET_PARAM_INVALID; | ||||
| } | } | ||||
| int mul_block_shape = 1; | |||||
| mul_block_shape_ = 1; | |||||
| for (size_t i = 0; i < kBlockShapeSize; ++i) { | for (size_t i = 0; i < kBlockShapeSize; ++i) { | ||||
| if (block_shape[i] <= 0) { | if (block_shape[i] <= 0) { | ||||
| @@ -128,10 +113,10 @@ int BatchToSpace::InferShape(std::vector<lite::Tensor *> inputs, std::vector<lit | |||||
| << block_shape[i]; | << block_shape[i]; | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| mul_block_shape *= block_shape[i]; | |||||
| mul_block_shape_ *= block_shape[i]; | |||||
| } | } | ||||
| if (input_shape[NHWC_N] < mul_block_shape) { | |||||
| if (input_shape[NHWC_N] < mul_block_shape_) { | |||||
| MS_LOG(ERROR) << "Dimension n " << input_shape[NHWC_N] << " < product of block shape!"; | MS_LOG(ERROR) << "Dimension n " << input_shape[NHWC_N] << " < product of block shape!"; | ||||
| return RET_PARAM_INVALID; | return RET_PARAM_INVALID; | ||||
| } | } | ||||
| @@ -142,13 +127,105 @@ int BatchToSpace::InferShape(std::vector<lite::Tensor *> inputs, std::vector<lit | |||||
| } | } | ||||
| } | } | ||||
| std::vector<int32_t> output_shape(input_shape.size()); | std::vector<int32_t> output_shape(input_shape.size()); | ||||
| output_shape[NHWC_N] = input_shape[NHWC_N] / mul_block_shape; | |||||
| output_shape[NHWC_N] = input_shape[NHWC_N] / mul_block_shape_; | |||||
| output_shape[NHWC_H] = input_shape[NHWC_H] * block_shape[0] - crops[0] - crops[1]; | output_shape[NHWC_H] = input_shape[NHWC_H] * block_shape[0] - crops[0] - crops[1]; | ||||
| output_shape[NHWC_W] = input_shape[NHWC_W] * block_shape[1] - crops[2] - crops[3]; | output_shape[NHWC_W] = input_shape[NHWC_W] * block_shape[1] - crops[2] - crops[3]; | ||||
| output_shape[NHWC_C] = input_shape[NHWC_C]; | |||||
| if (input_shape.size() > 3) { | |||||
| output_shape[NHWC_C] = input_shape[NHWC_C]; | |||||
| } | |||||
| outputs[0]->set_shape(output_shape); | |||||
| return RET_OK; | |||||
| } | |||||
| int BatchToSpace::SetOutputShapeFromInput(const std::vector<lite::Tensor *> inputs, | |||||
| std::vector<lite::Tensor *> outputs) { | |||||
| auto input_shape = inputs[0]->shape(); | |||||
| if (input_shape.size() != kQuadrupleNum) { | |||||
| MS_LOG(ERROR) << "input shape dimension size should == " << kQuadrupleNum; | |||||
| return RET_PARAM_INVALID; | |||||
| } | |||||
| auto block_shape_data = inputs[1]->data_c(); | |||||
| auto crops_data = inputs[2]->data_c(); | |||||
| auto block_shape = static_cast<int *>(block_shape_data); | |||||
| auto crops = static_cast<int *>(crops_data); | |||||
| if (inputs[1]->ElementsNum() != kBlockShapeSize) { | |||||
| MS_LOG(ERROR) << "Block shape size should be " << kBlockShapeSize; | |||||
| return RET_PARAM_INVALID; | |||||
| } | |||||
| if (inputs[2]->ElementsNum() != kCropsSize) { | |||||
| MS_LOG(ERROR) << "Crops size should be " << kCropsSize; | |||||
| return RET_PARAM_INVALID; | |||||
| } | |||||
| mul_block_shape_ = 1; | |||||
| for (size_t i = 0; i < kBlockShapeSize; ++i) { | |||||
| if (block_shape[i] <= 0) { | |||||
| MS_LOG(ERROR) << "Input block_shape should > 0!"; | |||||
| return RET_PARAM_INVALID; | |||||
| } | |||||
| if (input_shape[NHWC_N] % block_shape[i]) { | |||||
| MS_LOG(ERROR) << "Dimension n " << input_shape[NHWC_N] << " can not divide block_shape[" << i << "] " | |||||
| << block_shape[i]; | |||||
| return 1; | |||||
| } | |||||
| mul_block_shape_ *= block_shape[i]; | |||||
| } | |||||
| if (input_shape[NHWC_N] < mul_block_shape_) { | |||||
| MS_LOG(ERROR) << "Dimension n " << input_shape[NHWC_N] << " < product of block shape!"; | |||||
| return RET_PARAM_INVALID; | |||||
| } | |||||
| for (size_t i = 0; i < kCropsSize; ++i) { | |||||
| if (crops[i] < 0) { | |||||
| MS_LOG(ERROR) << "Input crops should >= 0"; | |||||
| return RET_PARAM_INVALID; | |||||
| } | |||||
| } | |||||
| std::vector<int32_t> output_shape(input_shape.size()); | |||||
| output_shape[NHWC_N] = input_shape[NHWC_N] / mul_block_shape_; | |||||
| output_shape[NHWC_H] = input_shape[NHWC_H] * block_shape[0] - crops[0] - crops[1]; | |||||
| output_shape[NHWC_W] = input_shape[NHWC_W] * block_shape[1] - crops[2] - crops[3]; | |||||
| if (input_shape.size() > 3) { | |||||
| output_shape[NHWC_C] = input_shape[NHWC_C]; | |||||
| } | |||||
| outputs[0]->set_shape(output_shape); | outputs[0]->set_shape(output_shape); | ||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int BatchToSpace::InferShape(std::vector<lite::Tensor *> inputs, std::vector<lite::Tensor *> outputs) { | |||||
| MS_ASSERT(this->primitive_ != nullptr); | |||||
| if (outputs.size() != kBatchToSpaceOutputNum || | |||||
| (inputs.size() != kBatchToSpaceOneInput && inputs.size() != kBatchToSpaceThreeInput)) { | |||||
| MS_LOG(ERROR) << "Invalid output/input size! output size: " << outputs.size() << ",input size: " << inputs.size(); | |||||
| return RET_PARAM_INVALID; | |||||
| } | |||||
| auto input = inputs.at(0); | |||||
| if (input->format() != schema::Format::Format_NHWC) { | |||||
| MS_LOG(ERROR) << "batch_to_space only support NHWC now!"; | |||||
| return RET_FORMAT_ERR; | |||||
| } | |||||
| outputs[0]->set_format(input->format()); | |||||
| outputs[0]->set_data_type(input->data_type()); | |||||
| if (!infer_flag()) { | |||||
| return RET_INFER_INVALID; | |||||
| } | |||||
| if (inputs.size() == kBatchToSpaceOneInput) { | |||||
| auto ret = SetOutputShapeFromParam(inputs, outputs); | |||||
| return ret; | |||||
| } | |||||
| if (inputs.size() == kBatchToSpaceThreeInput) { | |||||
| if (inputs[0]->data_c() == nullptr) { | |||||
| return RET_INFER_INVALID; | |||||
| } | |||||
| MS_ASSERT(inputs[1]->data_c() != nullptr); | |||||
| MS_ASSERT(inputs[2]->data_c() != nullptr); | |||||
| auto ret = SetOutputShapeFromInput(inputs, outputs); | |||||
| return ret; | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| @@ -40,6 +40,11 @@ class BatchToSpace : public PrimitiveC { | |||||
| int InferShape(std::vector<lite::Tensor *> inputs_, std::vector<lite::Tensor *> outputs_) override; | int InferShape(std::vector<lite::Tensor *> inputs_, std::vector<lite::Tensor *> outputs_) override; | ||||
| std::vector<int> GetBlockShape() const; | std::vector<int> GetBlockShape() const; | ||||
| std::vector<int> GetCrops() const; | std::vector<int> GetCrops() const; | ||||
| private: | |||||
| int SetOutputShapeFromParam(const std::vector<lite::Tensor *> inputs, std::vector<lite::Tensor *> outputs); | |||||
| int SetOutputShapeFromInput(const std::vector<lite::Tensor *> inputs, std::vector<lite::Tensor *> outputs); | |||||
| int mul_block_shape_; | |||||
| }; | }; | ||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| @@ -396,6 +396,9 @@ int Conv2D::InferShape(std::vector<Tensor *> inputs_, std::vector<Tensor *> outp | |||||
| return RET_INFER_INVALID; | return RET_INFER_INVALID; | ||||
| } | } | ||||
| auto in_shape = input_tensor->shape(); | auto in_shape = input_tensor->shape(); | ||||
| if (in_shape.size() == 0) { | |||||
| return RET_INFER_INVALID; | |||||
| } | |||||
| int input_h = in_shape.at(1); | int input_h = in_shape.at(1); | ||||
| int input_w = in_shape.at(2); | int input_w = in_shape.at(2); | ||||
| int output_w = 0, output_h = 0; | int output_w = 0, output_h = 0; | ||||
| @@ -34,6 +34,9 @@ OpParameter *PopulateBatchToSpaceParameter(const mindspore::lite::PrimitiveC *pr | |||||
| batch_space_param->op_parameter_.type_ = primitive->Type(); | batch_space_param->op_parameter_.type_ = primitive->Type(); | ||||
| auto param = reinterpret_cast<mindspore::lite::BatchToSpace *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | auto param = reinterpret_cast<mindspore::lite::BatchToSpace *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | ||||
| auto block_shape = param->GetBlockShape(); | auto block_shape = param->GetBlockShape(); | ||||
| if (block_shape.empty()) { | |||||
| return reinterpret_cast<OpParameter *>(batch_space_param); | |||||
| } | |||||
| if (block_shape.size() != BATCH_TO_SPACE_BLOCK_SHAPE_SIZE) { | if (block_shape.size() != BATCH_TO_SPACE_BLOCK_SHAPE_SIZE) { | ||||
| MS_LOG(ERROR) << "batch_to_space blockShape size should be " << BATCH_TO_SPACE_BLOCK_SHAPE_SIZE; | MS_LOG(ERROR) << "batch_to_space blockShape size should be " << BATCH_TO_SPACE_BLOCK_SHAPE_SIZE; | ||||
| free(batch_space_param); | free(batch_space_param); | ||||
| @@ -41,6 +44,9 @@ OpParameter *PopulateBatchToSpaceParameter(const mindspore::lite::PrimitiveC *pr | |||||
| } | } | ||||
| auto crops = param->GetCrops(); | auto crops = param->GetCrops(); | ||||
| if (crops.empty()) { | |||||
| return reinterpret_cast<OpParameter *>(batch_space_param); | |||||
| } | |||||
| if (crops.size() != COMM_SHAPE_SIZE) { | if (crops.size() != COMM_SHAPE_SIZE) { | ||||
| MS_LOG(ERROR) << "batch_to_space crops size should be " << COMM_SHAPE_SIZE; | MS_LOG(ERROR) << "batch_to_space crops size should be " << COMM_SHAPE_SIZE; | ||||
| free(batch_space_param); | free(batch_space_param); | ||||
| @@ -31,6 +31,9 @@ OpParameter *PopulateSpaceToBatchNDParameter(const mindspore::lite::PrimitiveC * | |||||
| space_batch_param_nd->op_parameter_.type_ = primitive->Type(); | space_batch_param_nd->op_parameter_.type_ = primitive->Type(); | ||||
| auto block_sizes = ((mindspore::lite::SpaceToBatchND *)primitive)->GetBlockShape(); | auto block_sizes = ((mindspore::lite::SpaceToBatchND *)primitive)->GetBlockShape(); | ||||
| if (block_sizes.empty()) { | |||||
| return reinterpret_cast<OpParameter *>(space_batch_param_nd); | |||||
| } | |||||
| space_batch_param_nd->m_ = block_sizes.size(); | space_batch_param_nd->m_ = block_sizes.size(); | ||||
| if (block_sizes.size() > std::numeric_limits<size_t>::max() / sizeof(int)) { | if (block_sizes.size() > std::numeric_limits<size_t>::max() / sizeof(int)) { | ||||
| MS_LOG(ERROR) << "The value of block_sizes.size() is too big"; | MS_LOG(ERROR) << "The value of block_sizes.size() is too big"; | ||||
| @@ -39,6 +42,9 @@ OpParameter *PopulateSpaceToBatchNDParameter(const mindspore::lite::PrimitiveC * | |||||
| } | } | ||||
| memcpy(space_batch_param_nd->block_sizes_, (block_sizes.data()), block_sizes.size() * sizeof(int)); | memcpy(space_batch_param_nd->block_sizes_, (block_sizes.data()), block_sizes.size() * sizeof(int)); | ||||
| auto paddings = ((mindspore::lite::SpaceToBatchND *)primitive)->GetPaddings(); | auto paddings = ((mindspore::lite::SpaceToBatchND *)primitive)->GetPaddings(); | ||||
| if (paddings.empty()) { | |||||
| return reinterpret_cast<OpParameter *>(space_batch_param_nd); | |||||
| } | |||||
| if (paddings.size() > std::numeric_limits<size_t>::max() / sizeof(int)) { | if (paddings.size() > std::numeric_limits<size_t>::max() / sizeof(int)) { | ||||
| MS_LOG(ERROR) << "The value of paddings.size() is too big"; | MS_LOG(ERROR) << "The value of paddings.size() is too big"; | ||||
| free(space_batch_param_nd); | free(space_batch_param_nd); | ||||
| @@ -26,7 +26,8 @@ namespace mindspore { | |||||
| namespace lite { | namespace lite { | ||||
| namespace { | namespace { | ||||
| constexpr int kSpaceToBatchNDOutputNum = 1; | constexpr int kSpaceToBatchNDOutputNum = 1; | ||||
| constexpr int kSpaceToBatchNDInputNum = 1; | |||||
| constexpr int kSpaceToBatchNDOneInput = 1; | |||||
| constexpr int kSpaceToBatchNDThreeInput = 3; | |||||
| } // namespace | } // namespace | ||||
| #ifdef PRIMITIVE_WRITEABLE | #ifdef PRIMITIVE_WRITEABLE | ||||
| @@ -86,23 +87,9 @@ Registry SpaceToBatchNDRegistry(schema::PrimitiveType_SpaceToBatchND, SpaceToBat | |||||
| #endif // PRIMITIVE_WRITEABLE | #endif // PRIMITIVE_WRITEABLE | ||||
| int SpaceToBatchND::InferShape(std::vector<lite::Tensor *> inputs, std::vector<lite::Tensor *> outputs) { | |||||
| if (outputs.size() != kSpaceToBatchNDOutputNum || inputs.size() != kSpaceToBatchNDInputNum) { | |||||
| MS_LOG(ERROR) << "Invalid output/input size! output size: " << outputs.size() << ",input size: " << inputs.size(); | |||||
| return 1; | |||||
| } | |||||
| auto input = inputs.at(0); | |||||
| if (input->format() != schema::Format::Format_NHWC) { | |||||
| MS_LOG(ERROR) << "space_to_batch_nd only support NHWC now!"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| outputs.at(0)->set_data_type(input->data_type()); | |||||
| outputs.at(0)->set_format(input->format()); | |||||
| if (!infer_flag()) { | |||||
| return RET_INFER_INVALID; | |||||
| } | |||||
| auto input_shape = input->shape(); | |||||
| int SpaceToBatchND::SetOutputShapeFromParam(const std::vector<lite::Tensor *> inputs, | |||||
| std::vector<lite::Tensor *> outputs) { | |||||
| auto input_shape = inputs[0]->shape(); | |||||
| if (input_shape.size() != kQuadrupleNum) { | if (input_shape.size() != kQuadrupleNum) { | ||||
| MS_LOG(ERROR) << "input shape dimension size only support " << kQuadrupleNum << " now!"; | MS_LOG(ERROR) << "input shape dimension size only support " << kQuadrupleNum << " now!"; | ||||
| return RET_ERROR; | return RET_ERROR; | ||||
| @@ -133,9 +120,94 @@ int SpaceToBatchND::InferShape(std::vector<lite::Tensor *> inputs, std::vector<l | |||||
| return RET_ERROR; | return RET_ERROR; | ||||
| } | } | ||||
| output_shape.at(NHWC_W) = (input_shape.at(NHWC_W) + padding_left + padding_right) / block_w; | output_shape.at(NHWC_W) = (input_shape.at(NHWC_W) + padding_left + padding_right) / block_w; | ||||
| output_shape.at(NHWC_C) = input_shape.at(NHWC_C); | |||||
| if (input_shape.size() > 3) { | |||||
| output_shape.at(NHWC_C) = input_shape.at(NHWC_C); | |||||
| } | |||||
| outputs.at(0)->set_shape(output_shape); | outputs.at(0)->set_shape(output_shape); | ||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int SpaceToBatchND::SetOutputShapeFromInput(const std::vector<lite::Tensor *> inputs, | |||||
| std::vector<lite::Tensor *> outputs) { | |||||
| auto input_shape = inputs[0]->shape(); | |||||
| if (input_shape.size() != kQuadrupleNum) { | |||||
| MS_LOG(ERROR) << "input shape dimension size only support " << kQuadrupleNum << " now!"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| MS_ASSERT(inputs[2]->ElementsNum() == 4); | |||||
| auto block_shape_data = inputs[1]->data_c(); | |||||
| auto block_shape = static_cast<int *>(block_shape_data); | |||||
| auto padding_data = inputs[2]->data_c(); | |||||
| auto padding = static_cast<int *>(padding_data); | |||||
| int padding_left = 0; | |||||
| int padding_right = 0; | |||||
| int block_w = 1; | |||||
| if (inputs[1]->ElementsNum() == 2) { | |||||
| padding_left = padding[2]; | |||||
| padding_right = padding[3]; | |||||
| block_w = block_shape[1]; | |||||
| } | |||||
| std::vector<int32_t> output_shape(input_shape.size()); | |||||
| if (block_shape[0] * block_w > std::numeric_limits<int>::max() / input_shape.at(NHWC_N)) { | |||||
| MS_LOG(ERROR) << "The value of block_shape.at(0) * block_w is too big"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| output_shape.at(NHWC_N) = input_shape.at(NHWC_N) * block_shape[0] * block_w; | |||||
| if (padding[0] + padding[1] > std::numeric_limits<int>::max() - input_shape.at(NHWC_H)) { | |||||
| MS_LOG(ERROR) << "The value of padding.at(0) + padding.at(1) is too big"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| output_shape.at(NHWC_H) = (input_shape.at(NHWC_H) + padding[0] + padding[1]) / block_shape[0]; | |||||
| if (padding_left + padding_right > std::numeric_limits<int>::max() - input_shape.at(NHWC_W)) { | |||||
| MS_LOG(ERROR) << "The value of padding_left + padding_right is too big"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| output_shape.at(NHWC_W) = (input_shape.at(NHWC_W) + padding_left + padding_right) / block_w; | |||||
| if (input_shape.size() > 3) { | |||||
| output_shape.at(NHWC_C) = input_shape.at(NHWC_C); | |||||
| } | |||||
| outputs.at(0)->set_shape(output_shape); | |||||
| return RET_OK; | |||||
| } | |||||
| int SpaceToBatchND::InferShape(std::vector<lite::Tensor *> inputs, std::vector<lite::Tensor *> outputs) { | |||||
| if (outputs.size() != kSpaceToBatchNDOutputNum || | |||||
| (inputs.size() != kSpaceToBatchNDOneInput && inputs.size() != kSpaceToBatchNDThreeInput)) { | |||||
| MS_LOG(ERROR) << "Invalid output/input size! output size: " << outputs.size() << ",input size: " << inputs.size(); | |||||
| return 1; | |||||
| } | |||||
| auto input = inputs.at(0); | |||||
| if (input->format() != schema::Format::Format_NHWC) { | |||||
| MS_LOG(ERROR) << "space_to_batch_nd only support NHWC now!"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| outputs.at(0)->set_data_type(input->data_type()); | |||||
| outputs.at(0)->set_format(input->format()); | |||||
| if (!infer_flag()) { | |||||
| return RET_INFER_INVALID; | |||||
| } | |||||
| if (inputs.size() == kSpaceToBatchNDOneInput) { | |||||
| auto ret = SetOutputShapeFromParam(inputs, outputs); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "SetOutputShapeFromParam failed"; | |||||
| return ret; | |||||
| } | |||||
| } | |||||
| if (inputs.size() == kSpaceToBatchNDThreeInput) { | |||||
| if (inputs[0]->data_c() == nullptr) { | |||||
| return RET_INFER_INVALID; | |||||
| } | |||||
| MS_ASSERT(inputs[1]->data_c() != nullptr); | |||||
| MS_ASSERT(inputs[2]->data_c() != nullptr); | |||||
| auto ret = SetOutputShapeFromInput(inputs, outputs); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "SetOutputShapeFromInput failed"; | |||||
| return ret; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| @@ -39,6 +39,8 @@ class SpaceToBatchND : public PrimitiveC { | |||||
| std::vector<int> GetBlockShape() const; | std::vector<int> GetBlockShape() const; | ||||
| std::vector<int> GetPaddings() const; | std::vector<int> GetPaddings() const; | ||||
| int InferShape(std::vector<lite::Tensor *> inputs, std::vector<lite::Tensor *> outputs) override; | int InferShape(std::vector<lite::Tensor *> inputs, std::vector<lite::Tensor *> outputs) override; | ||||
| int SetOutputShapeFromParam(const std::vector<lite::Tensor *> inputs, std::vector<lite::Tensor *> outputs); | |||||
| int SetOutputShapeFromInput(const std::vector<lite::Tensor *> inputs, std::vector<lite::Tensor *> outputs); | |||||
| }; | }; | ||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| @@ -16,23 +16,46 @@ | |||||
| #include "src/runtime/kernel/arm/fp32/batch_to_space_fp32.h" | #include "src/runtime/kernel/arm/fp32/batch_to_space_fp32.h" | ||||
| #include "schema/model_generated.h" | #include "schema/model_generated.h" | ||||
| #include "src/kernel_registry.h" | #include "src/kernel_registry.h" | ||||
| #include "src/ops/batch_to_space.h" | |||||
| using mindspore::lite::KernelRegistrar; | using mindspore::lite::KernelRegistrar; | ||||
| using mindspore::lite::RET_ERROR; | |||||
| using mindspore::lite::RET_OK; | |||||
| using mindspore::schema::PrimitiveType_BatchToSpace; | using mindspore::schema::PrimitiveType_BatchToSpace; | ||||
| using mindspore::schema::PrimitiveType_BatchToSpaceND; | using mindspore::schema::PrimitiveType_BatchToSpaceND; | ||||
| namespace mindspore::kernel { | namespace mindspore::kernel { | ||||
| int BatchToSpaceCPUKernel::Processinput() { | |||||
| MS_ASSERT(in_tensors_[1]->data_c() != nullptr); | |||||
| MS_ASSERT(in_tensors_[2]->data_c() != nullptr); | |||||
| auto block_shape_data = in_tensors_[1]->data_c(); | |||||
| auto crops_data = in_tensors_[2]->data_c(); | |||||
| auto block_shape = static_cast<int *>(block_shape_data); | |||||
| auto crops = static_cast<int *>(crops_data); | |||||
| for (int i = 0; i < BATCH_TO_SPACE_BLOCK_SHAPE_SIZE; ++i) { | |||||
| block_shape_[i] = block_shape[i]; | |||||
| } | |||||
| no_crop_ = true; | |||||
| for (int i = 0; i < COMM_SHAPE_SIZE; ++i) { | |||||
| crops_[i] = crops[i]; | |||||
| if (crops_[i] != 0) { | |||||
| no_crop_ = false; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| int BatchToSpaceCPUKernel::Init() { | int BatchToSpaceCPUKernel::Init() { | ||||
| MS_ASSERT(in_tensors_.at(0)->format() == schema::Format::Format_NHWC); | MS_ASSERT(in_tensors_.at(0)->format() == schema::Format::Format_NHWC); | ||||
| if (!InferShapeDone()) { | if (!InferShapeDone()) { | ||||
| return lite::RET_OK; | |||||
| return RET_OK; | |||||
| } | } | ||||
| return ReSize(); | return ReSize(); | ||||
| } | } | ||||
| int BatchToSpaceCPUKernel::ReSize() { | int BatchToSpaceCPUKernel::ReSize() { | ||||
| MS_ASSERT(in_tensors_.at(0)->shape().size() == 4); | MS_ASSERT(in_tensors_.at(0)->shape().size() == 4); | ||||
| return lite::RET_OK; | |||||
| return RET_OK; | |||||
| } | } | ||||
| int BatchToSpaceCPUKernel::Run() { | int BatchToSpaceCPUKernel::Run() { | ||||
| @@ -42,17 +65,29 @@ int BatchToSpaceCPUKernel::Run() { | |||||
| float *output_data = reinterpret_cast<float *>(output->MutableData()); | float *output_data = reinterpret_cast<float *>(output->MutableData()); | ||||
| auto in_shape = input->shape(); | auto in_shape = input->shape(); | ||||
| auto out_shape = output->shape(); | auto out_shape = output->shape(); | ||||
| BatchToSpaceParameter *param = reinterpret_cast<BatchToSpaceParameter *>(this->op_parameter_); | |||||
| if (param->no_crop_) { | |||||
| BatchToSpaceNoCropForNHWC(input_data, output_data, in_shape.data(), out_shape[0], param->block_shape_, | |||||
| sizeof(float)); | |||||
| } else { | |||||
| BatchToSpaceForNHWC(input_data, output_data, in_shape.data(), out_shape[0], param->block_shape_, param->crops_, | |||||
| sizeof(float)); | |||||
| if (in_tensors_.size() == 1) { | |||||
| BatchToSpaceParameter *param = reinterpret_cast<BatchToSpaceParameter *>(this->op_parameter_); | |||||
| if (param->no_crop_) { | |||||
| BatchToSpaceNoCropForNHWC(input_data, output_data, in_shape.data(), out_shape[0], param->block_shape_, | |||||
| sizeof(float)); | |||||
| } else { | |||||
| BatchToSpaceForNHWC(input_data, output_data, in_shape.data(), out_shape[0], param->block_shape_, param->crops_, | |||||
| sizeof(float)); | |||||
| } | |||||
| } | } | ||||
| return lite::RET_OK; | |||||
| if (in_tensors_.size() == 3) { | |||||
| auto ret = Processinput(); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "Processinput failed in BatchToSpace."; | |||||
| return ret; | |||||
| } | |||||
| if (no_crop_) { | |||||
| BatchToSpaceNoCropForNHWC(input_data, output_data, in_shape.data(), out_shape[0], block_shape_, sizeof(float)); | |||||
| } else { | |||||
| BatchToSpaceForNHWC(input_data, output_data, in_shape.data(), out_shape[0], block_shape_, crops_, sizeof(float)); | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | } | ||||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_BatchToSpace, LiteKernelCreator<BatchToSpaceCPUKernel>) | REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_BatchToSpace, LiteKernelCreator<BatchToSpaceCPUKernel>) | ||||
| @@ -34,6 +34,12 @@ class BatchToSpaceCPUKernel : public LiteKernel { | |||||
| int Init() override; | int Init() override; | ||||
| int ReSize() override; | int ReSize() override; | ||||
| int Run() override; | int Run() override; | ||||
| int Processinput(); | |||||
| private: | |||||
| int32_t block_shape_[BATCH_TO_SPACE_BLOCK_SHAPE_SIZE]; | |||||
| int32_t crops_[COMM_SHAPE_SIZE]; | |||||
| bool no_crop_; | |||||
| }; | }; | ||||
| } // namespace mindspore::kernel | } // namespace mindspore::kernel | ||||
| @@ -25,6 +25,32 @@ using mindspore::schema::PrimitiveType_SpaceToBatch; | |||||
| using mindspore::schema::PrimitiveType_SpaceToBatchND; | using mindspore::schema::PrimitiveType_SpaceToBatchND; | ||||
| namespace mindspore::kernel { | namespace mindspore::kernel { | ||||
| void SpaceToBatchCPUKernel::ProcessInput() { | |||||
| MS_ASSERT(in_tensors_[1] != nullptr); | |||||
| MS_ASSERT(in_tensors_[2] != nullptr); | |||||
| auto input_tensor = in_tensors_.at(0); | |||||
| MS_ASSERT(input_tensor); | |||||
| auto output_tensor = out_tensors_.at(0); | |||||
| MS_ASSERT(output_tensor); | |||||
| MS_ASSERT(param_); | |||||
| for (size_t i = 0; i < DIMENSION_4D; i++) { | |||||
| param_->input_shape_[i] = input_tensor->shape().at(i); | |||||
| param_->output_shape_[i] = output_tensor->shape().at(i); | |||||
| } | |||||
| ComputeStrides(param_->input_shape_, param_->in_stride_, DIMENSION_4D); | |||||
| ComputeStrides(param_->output_shape_, param_->out_stride_, DIMENSION_4D); | |||||
| auto block_shape_data = in_tensors_[1]->data_c(); | |||||
| auto block_shape = static_cast<int *>(block_shape_data); | |||||
| for (int i = 0; i < in_tensors_[1]->ElementsNum(); i++) { | |||||
| param_->block_sizes_[i] = block_shape[i]; | |||||
| } | |||||
| auto padding_data = in_tensors_[2]->data_c(); | |||||
| auto padding = static_cast<int *>(padding_data); | |||||
| for (int i = 0; i < in_tensors_[2]->ElementsNum(); i++) { | |||||
| param_->paddings_[i] = padding[i]; | |||||
| } | |||||
| } | |||||
| int SpaceToBatchCPUKernel::Init() { | int SpaceToBatchCPUKernel::Init() { | ||||
| if (!InferShapeDone()) { | if (!InferShapeDone()) { | ||||
| return RET_OK; | return RET_OK; | ||||
| @@ -39,6 +65,12 @@ int SpaceToBatchFp32Run(void *cdata, int task_id) { | |||||
| } | } | ||||
| int SpaceToBatchCPUKernel::ReSize() { | int SpaceToBatchCPUKernel::ReSize() { | ||||
| if (in_tensors_.size() == 3) { | |||||
| if (in_tensors_[1] != nullptr && in_tensors_[1]->IsConst() && in_tensors_[2] != nullptr && | |||||
| in_tensors_[2]->IsConst()) { | |||||
| ProcessInput(); | |||||
| } | |||||
| } | |||||
| auto input_tensor = in_tensors_.at(0); | auto input_tensor = in_tensors_.at(0); | ||||
| MS_ASSERT(input_tensor); | MS_ASSERT(input_tensor); | ||||
| auto output_tensor = out_tensors_.at(0); | auto output_tensor = out_tensors_.at(0); | ||||
| @@ -61,8 +93,14 @@ void SpaceToBatchCPUKernel::DoRun(int task_id) { | |||||
| } | } | ||||
| int SpaceToBatchCPUKernel::Run() { | int SpaceToBatchCPUKernel::Run() { | ||||
| MS_ASSERT(in_tensors_[0] != nullptr); | |||||
| input_ptr_ = reinterpret_cast<float *>(in_tensors_.at(0)->data_c()); | input_ptr_ = reinterpret_cast<float *>(in_tensors_.at(0)->data_c()); | ||||
| output_ptr_ = reinterpret_cast<float *>(out_tensors_.at(0)->data_c()); | output_ptr_ = reinterpret_cast<float *>(out_tensors_.at(0)->data_c()); | ||||
| if (in_tensors_.size() == 3) { | |||||
| if (!in_tensors_[1]->IsConst() || !in_tensors_[2]->IsConst()) { | |||||
| ProcessInput(); | |||||
| } | |||||
| } | |||||
| ParallelLaunch(this->context_->thread_pool_, SpaceToBatchFp32Run, this, op_parameter_->thread_num_); | ParallelLaunch(this->context_->thread_pool_, SpaceToBatchFp32Run, this, op_parameter_->thread_num_); | ||||
| @@ -35,6 +35,7 @@ class SpaceToBatchCPUKernel : public LiteKernel { | |||||
| int Init() override; | int Init() override; | ||||
| int ReSize() override; | int ReSize() override; | ||||
| int Run() override; | int Run() override; | ||||
| void ProcessInput(); | |||||
| public: | public: | ||||
| void DoRun(int task_id); | void DoRun(int task_id); | ||||
| @@ -0,0 +1,65 @@ | |||||
| /** | |||||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| #include "tools/converter/parser/tf/tf_batch_to_space_nd_parser.h" | |||||
| #include <string> | |||||
| #include <memory> | |||||
| #include <map> | |||||
| #include <vector> | |||||
| #include "tools/converter/parser/tf/tf_node_parser_registry.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| STATUS TFBatchToSpaceNDParser::Parse(const tensorflow::NodeDef &tf_op, | |||||
| const std::map<string, const tensorflow::NodeDef *> &tf_node_map, | |||||
| PrimitiveC **primitiveC, std::vector<std::string> *inputs, int *output_size) { | |||||
| MS_LOG(WARNING) << "TF BatchToSpaceNDParser"; | |||||
| if (primitiveC == nullptr || output_size == nullptr) { | |||||
| MS_LOG(ERROR) << "primitiveC is nullptr"; | |||||
| return RET_NULL_PTR; | |||||
| } | |||||
| auto primitive = std::make_unique<schema::PrimitiveT>(); | |||||
| if (primitive == nullptr) { | |||||
| MS_LOG(ERROR) << "New PrimitiveT failed"; | |||||
| return RET_NULL_PTR; | |||||
| } | |||||
| auto attr = std::make_unique<schema::BatchToSpaceT>(); | |||||
| if (attr == nullptr) { | |||||
| MS_LOG(ERROR) << "new attr failed"; | |||||
| return RET_NULL_PTR; | |||||
| } | |||||
| primitive->value.type = schema::PrimitiveType_BatchToSpace; | |||||
| primitive->value.value = attr.release(); | |||||
| *primitiveC = PrimitiveC::Create(primitive.release()); | |||||
| if (*primitiveC == nullptr) { | |||||
| MS_LOG(ERROR) << "primitiveC is nullptr"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| *output_size = 1; | |||||
| for (int i = 0; i < tf_op.input_size(); ++i) { | |||||
| auto status = AddOpInput(tf_op, i, inputs); | |||||
| if (status != RET_OK) { | |||||
| return status; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| TFNodeRegistrar g_tfBatchToSpaceNDParser("BatchToSpaceND", new TFBatchToSpaceNDParser()); | |||||
| TFNodeRegistrar g_tfBatchToSpaceParser("BatchToSpace", new TFBatchToSpaceNDParser()); | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| @@ -0,0 +1,36 @@ | |||||
| /** | |||||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| #ifndef MINDSPORE_LITE_TOOLS_CONVERTER_PARSER_TF_TF_BATCH_TO_SPACE_ND_PARSER_H_ | |||||
| #define MINDSPORE_LITE_TOOLS_CONVERTER_PARSER_TF_TF_BATCH_TO_SPACE_ND_PARSER_H_ | |||||
| #include <string> | |||||
| #include <memory> | |||||
| #include <map> | |||||
| #include <vector> | |||||
| #include "tools/converter/parser/tf/tf_node_parser.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| class TFBatchToSpaceNDParser : public TFNodeParser { | |||||
| public: | |||||
| TFBatchToSpaceNDParser() = default; | |||||
| ~TFBatchToSpaceNDParser() override = default; | |||||
| STATUS Parse(const tensorflow::NodeDef &tf_op, const std::map<string, const tensorflow::NodeDef *> &tf_node_map, | |||||
| PrimitiveC **primitiveC, std::vector<std::string> *inputs, int *output_size) override; | |||||
| }; | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| #endif // MINDSPORE_LITE_TOOLS_CONVERTER_PARSER_TF_TF_BATCH_TO_SPACE_ND_PARSER_H_ | |||||
| @@ -0,0 +1,64 @@ | |||||
| /** | |||||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| #include "tools/converter/parser/tf/tf_space_to_batch_nd_parser.h" | |||||
| #include <string> | |||||
| #include <memory> | |||||
| #include <map> | |||||
| #include <vector> | |||||
| #include "tools/converter/parser/tf/tf_node_parser_registry.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| STATUS TFSpaceToBatchNDParser::Parse(const tensorflow::NodeDef &tf_op, | |||||
| const std::map<string, const tensorflow::NodeDef *> &tf_node_map, | |||||
| PrimitiveC **primitiveC, std::vector<std::string> *inputs, int *output_size) { | |||||
| MS_LOG(WARNING) << "TF SpaceToBatchNDParser"; | |||||
| if (primitiveC == nullptr || output_size == nullptr) { | |||||
| MS_LOG(ERROR) << "primitiveC is nullptr"; | |||||
| return RET_NULL_PTR; | |||||
| } | |||||
| auto primitive = std::make_unique<schema::PrimitiveT>(); | |||||
| if (primitive == nullptr) { | |||||
| MS_LOG(ERROR) << "New PrimitiveT failed"; | |||||
| return RET_NULL_PTR; | |||||
| } | |||||
| auto attr = std::make_unique<schema::SpaceToBatchNDT>(); | |||||
| if (attr == nullptr) { | |||||
| MS_LOG(ERROR) << "new attr failed"; | |||||
| return RET_NULL_PTR; | |||||
| } | |||||
| primitive->value.type = schema::PrimitiveType_SpaceToBatchND; | |||||
| primitive->value.value = attr.release(); | |||||
| *primitiveC = PrimitiveC::Create(primitive.release()); | |||||
| if (*primitiveC == nullptr) { | |||||
| MS_LOG(ERROR) << "primitiveC is nullptr"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| *output_size = 1; | |||||
| for (int i = 0; i < tf_op.input_size(); ++i) { | |||||
| auto status = AddOpInput(tf_op, i, inputs); | |||||
| if (status != RET_OK) { | |||||
| return status; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| TFNodeRegistrar g_tfSpaceToBatchNDParser("SpaceToBatchND", new TFSpaceToBatchNDParser()); | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| @@ -0,0 +1,36 @@ | |||||
| /** | |||||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| #ifndef MINDSPORE_LITE_TOOLS_CONVERTER_PARSER_TF_TF_SPACE_TO_BATCH_ND_PARSER_H_ | |||||
| #define MINDSPORE_LITE_TOOLS_CONVERTER_PARSER_TF_TF_SPACE_TO_BATCH_ND_PARSER_H_ | |||||
| #include <string> | |||||
| #include <memory> | |||||
| #include <map> | |||||
| #include <vector> | |||||
| #include "tools/converter/parser/tf/tf_node_parser.h" | |||||
| namespace mindspore { | |||||
| namespace lite { | |||||
| class TFSpaceToBatchNDParser : public TFNodeParser { | |||||
| public: | |||||
| TFSpaceToBatchNDParser() = default; | |||||
| ~TFSpaceToBatchNDParser() override = default; | |||||
| STATUS Parse(const tensorflow::NodeDef &tf_op, const std::map<string, const tensorflow::NodeDef *> &tf_node_map, | |||||
| PrimitiveC **primitiveC, std::vector<std::string> *inputs, int *output_size) override; | |||||
| }; | |||||
| } // namespace lite | |||||
| } // namespace mindspore | |||||
| #endif // MINDSPORE_LITE_TOOLS_CONVERTER_PARSER_TF_TF_SPACE_TO_BATCH_ND_PARSER_H_ | |||||