diff --git a/mindspore/lite/src/ops/dequantize.cc b/mindspore/lite/src/ops/dequantize.cc new file mode 100644 index 00000000000..e8496d24b2e --- /dev/null +++ b/mindspore/lite/src/ops/dequantize.cc @@ -0,0 +1,34 @@ +/** + * Copyright 2019-2020 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 "src/ops/ops.h" +#include "include/errorcode.h" +#include "utils/log_adapter.h" +#include "src/ir/tensor.h" + +namespace mindspore::lite { +int Dequantize::InferShape(std::vector inputs_, std::vector outputs_) { + MS_ASSERT(this->primitive != nullptr); + auto input = inputs_.front(); + MS_ASSERT(input != nullptr); + auto output = outputs_.front(); + MS_ASSERT(output != nullptr); + output->set_shape(input->shape()); + output->set_data_type(kNumberTypeFloat32); + return RET_OK; +} +} // namespace mindspore::lite + diff --git a/mindspore/lite/src/ops/ops.cc b/mindspore/lite/src/ops/ops.cc index 2fdc8681d72..f411e2e1b5e 100644 --- a/mindspore/lite/src/ops/ops.cc +++ b/mindspore/lite/src/ops/ops.cc @@ -133,6 +133,14 @@ Primitive *Primitive::CreatePrimitive(schema::Primitive *primitive) { return new lite::OneHot(const_cast(primitive)); case schema::PrimitiveType_PriorBox: return new lite::PriorBox(const_cast(primitive)); + case schema::PrimitiveType_SpaceToDepth: + return new lite::SpaceToDepth(const_cast(primitive)); + case schema::PrimitiveType_SpaceToBatch: + return new lite::SpaceToBatch(const_cast(primitive)); + case schema::PrimitiveType_OnnxInt8Dequantize: + return new lite::Dequantize(const_cast(primitive)); + case schema::PrimitiveType_OnnxInt8Quantize: + return new lite::Quantize(const_cast(primitive)); default: break; } diff --git a/mindspore/lite/src/ops/ops.h b/mindspore/lite/src/ops/ops.h index a67a9753413..5fb261bf8cd 100644 --- a/mindspore/lite/src/ops/ops.h +++ b/mindspore/lite/src/ops/ops.h @@ -596,6 +596,22 @@ class BatchToSpace : public Primitive { int InferShape(std::vector inputs, std::vector outputs) override; }; +class SpaceToBatch : public Primitive { + public: + explicit SpaceToBatch(schema::Primitive *primitive) : Primitive(primitive) {} + const schema::SpaceToBatch *GetAttribute() const { return this->primitive->value_as_SpaceToBatch(); } + int InferShape(std::vector inputs, std::vector outputs) override; + std::vector BlockSizes() {return block_sizes_;} + std::vector Paddings() {return block_sizes_;} + std::vector InShape() {return block_sizes_;} + std::vector PaddedInShape() {return block_sizes_;} + private: + std::vector block_sizes_; + std::vector paddings_; + std::vector in_shape_; + std::vector padded_in_shape_; +}; + class Crop : public Primitive { public: explicit Crop(schema::Primitive *primitive) : Primitive(primitive) {} @@ -668,6 +684,26 @@ class PriorBox : public Primitive { int InferShape(std::vector inputs, std::vector outputs) override; }; +class SpaceToDepth : public Primitive { + public: + explicit SpaceToDepth(schema::Primitive *primitive) : Primitive(primitive) {} + const schema::SpaceToDepth *GetAttribute() const { return this->primitive->value_as_SpaceToDepth(); } + int InferShape(std::vector inputs, std::vector outputs) override; +}; + +class Dequantize : public Primitive { + public: + explicit Dequantize(schema::Primitive *primitive) : Primitive(primitive) {} + const schema::OnnxInt8Dequantize *GetAttribute() const { return this->primitive->value_as_OnnxInt8Dequantize(); } + int InferShape(std::vector inputs, std::vector outputs) override; +}; + +class Quantize : public Primitive { + public: + explicit Quantize(schema::Primitive *primitive) : Primitive(primitive) {} + const schema::OnnxInt8Quantize *GetAttribute() const { return this->primitive->value_as_OnnxInt8Quantize(); } + int InferShape(std::vector inputs, std::vector outputs) override; +}; } // namespace lite } // namespace mindspore #endif // MINDSPORE_LITE_SRC_OPS_OPS_H_ diff --git a/mindspore/lite/src/ops/quantize.cc b/mindspore/lite/src/ops/quantize.cc new file mode 100644 index 00000000000..0db68e1ffad --- /dev/null +++ b/mindspore/lite/src/ops/quantize.cc @@ -0,0 +1,34 @@ +/** + * Copyright 2019-2020 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 "src/ops/ops.h" +#include "include/errorcode.h" +#include "utils/log_adapter.h" +#include "src/ir/tensor.h" + +namespace mindspore::lite { +int Quantize::InferShape(std::vector inputs_, std::vector outputs_) { + MS_ASSERT(this->primitive != nullptr); + auto input = inputs_.front(); + MS_ASSERT(input != nullptr); + auto output = outputs_.front(); + MS_ASSERT(output != nullptr); + output->set_shape(input->shape()); + output->set_data_type(kNumberTypeInt8); + return RET_OK; +} +} // namespace mindspore::lite + diff --git a/mindspore/lite/src/ops/space_to_batch.cc b/mindspore/lite/src/ops/space_to_batch.cc new file mode 100644 index 00000000000..c3cecc75d9c --- /dev/null +++ b/mindspore/lite/src/ops/space_to_batch.cc @@ -0,0 +1,91 @@ +/** + * Copyright 2019-2020 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 +#include "src/ops/ops.h" +#include "include/errorcode.h" +#include "utils/log_adapter.h" +#include "src/ir/tensor.h" + +namespace mindspore::lite { +namespace { +constexpr int kSpaceToBatchNDOutputNum = 1; +constexpr int kSpaceToBatchNDInputNum = 1; +constexpr int kBlockSizesSize = 2; +constexpr int kPaddingsSize = 4; +} // namespace + +int SpaceToBatch::InferShape(std::vector inputs, std::vector outputs) { + MS_ASSERT(this->primitive != nullptr); + if (outputs.size() != kSpaceToBatchNDOutputNum || inputs.size() != kSpaceToBatchNDInputNum) { + 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->GetFormat() != schema::Format_NHWC) { + MS_LOG(ERROR) << "space_to_batch only support NHWC now!"; + return RET_FORMAT_ERR; + } + auto input_shape = input->shape(); + if (input_shape.size() != kDimension_4d) { + MS_LOG(ERROR) << "input shape dimension size should == " << kDimension_4d; + return RET_PARAM_INVALID; + } + + auto prim = this->primitive->value_as_SpaceToBatch(); + if (prim->blockShape()->size() != kBlockSizesSize) { + MS_LOG(ERROR) << "Block shape size should be " << kBlockSizesSize; + return RET_PARAM_INVALID; + } + if (prim->paddings()->size() != kPaddingsSize) { + MS_LOG(ERROR) << "Crops size should be " << kPaddingsSize; + return RET_PARAM_INVALID; + } + + for (auto iter = prim->blockShape()->begin(); iter != prim->blockShape()->end(); ++iter) { + block_sizes_.emplace_back(*iter); + } + + in_shape_.clear(); + padded_in_shape_.clear(); + paddings_.clear(); + in_shape_.emplace_back(input_shape.at(kNHWC_n_index)); + padded_in_shape_.emplace_back(input_shape.at(kNHWC_n_index)); + for (int i = 0; i < kBlockSizesSize; i++) { + in_shape_.emplace_back(input_shape.at(i + 1)); + padded_in_shape_.emplace_back(input_shape.at(i + 1) + (paddings_.at(2 * i) + paddings_.at(2 * i + 1))); + paddings_.emplace_back(paddings_.at(2 * i)); + paddings_.emplace_back(paddings_.at(2 * i + 1)); + if (paddings_.back() % block_sizes_.at(i)) { + MS_LOG(ERROR) << "Padded shape does not divide block size " << block_sizes_.at(i); + return RET_PARAM_INVALID; + } + } + in_shape_.emplace_back(input_shape.at(kNHWC_c_index)); + padded_in_shape_.emplace_back(input_shape.at(kNHWC_c_index)); + + std::vector output_shape(input_shape.size()); + output_shape[kNHWC_n_index] = + input_shape[kNHWC_n_index] * (block_sizes_[kNHWC_n_index] * block_sizes_[kNHWC_h_index]); + output_shape[kNHWC_h_index] = input_shape[kNHWC_h_index] / block_sizes_[kNHWC_n_index]; + output_shape[kNHWC_w_index] = input_shape[kNHWC_w_index] / block_sizes_[kNHWC_h_index]; + output_shape[kNHWC_c_index] = input_shape[kNHWC_c_index]; + outputs[0]->set_shape(output_shape); + outputs[0]->set_data_type(input->data_type()); + return RET_OK; +} +} // namespace mindspore::lite diff --git a/mindspore/lite/src/ops/space_to_depth.cc b/mindspore/lite/src/ops/space_to_depth.cc new file mode 100644 index 00000000000..647c64c9090 --- /dev/null +++ b/mindspore/lite/src/ops/space_to_depth.cc @@ -0,0 +1,62 @@ +/** + * Copyright 2019-2020 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 +#include "src/ops/ops.h" +#include "include/errorcode.h" +#include "utils/log_adapter.h" +#include "src/ir/tensor.h" + +namespace mindspore::lite { +namespace { +constexpr int kSpaceToDepthOutputNum = 1; +constexpr int kSpaceToDepthInputNum = 1; +} + +int SpaceToDepth::InferShape(std::vector inputs, std::vector outputs) { + MS_ASSERT(this->primitive != nullptr); + if (outputs.size() != kSpaceToDepthOutputNum || inputs.size() != kSpaceToDepthInputNum) { + 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->GetFormat() != schema::Format_NHWC) { + MS_LOG(ERROR) << "space_to_depth only support NHWC now!"; + return RET_FORMAT_ERR; + } + auto input_shape = input->shape(); + if (input_shape.size() != kDimension_4d) { + MS_LOG(ERROR) << "input shape dimension size should == " << kDimension_4d; + return RET_PARAM_INVALID; + } + auto prim = this->primitive->value_as_SpaceToDepth(); + int32_t block_size = prim->blockSize(); + if (input_shape[kNHWC_c_index] % (block_size * block_size) != 0 || input_shape[kNHWC_c_index] == 0) { + MS_LOG(ERROR) << "input dimension c size " << input_shape[kNHWC_c_index] << " should be mulitple of block_size(" + << block_size << ") * block_size)!"; + return RET_PARAM_INVALID; + } + std::vector output_shape(input_shape.size()); + output_shape[kNHWC_n_index] = input_shape[kNHWC_n_index]; + output_shape[kNHWC_h_index] = input_shape[kNHWC_h_index] / block_size; + output_shape[kNHWC_w_index] = input_shape[kNHWC_w_index] / block_size; + output_shape[kNHWC_c_index] = input_shape[kNHWC_c_index] * (block_size * block_size); + outputs[0]->set_shape(output_shape); + outputs[0]->set_data_type(input->data_type()); + return RET_OK; +} +} // namespace mindspore::lite diff --git a/mindspore/lite/src/populate_parameter.cc b/mindspore/lite/src/populate_parameter.cc index 1221b994204..1bfbd976670 100644 --- a/mindspore/lite/src/populate_parameter.cc +++ b/mindspore/lite/src/populate_parameter.cc @@ -63,6 +63,10 @@ #include "src/runtime/kernel/arm/opclib/fp32/one_hot.h" #include "src/runtime/kernel/arm/opclib/fp32/strided_slice.h" #include "src/runtime/kernel/arm/base/prior_box.h" +#include "src/runtime/kernel/arm/opclib/fp32/space_to_depth.h" +#include "src/runtime/kernel/arm/opclib/fp32/space_to_batch.h" +#include "src/runtime/kernel/arm/opclib/int8/dequantize.h" +#include "src/runtime/kernel/arm/opclib/fp32/quantize.h" namespace mindspore::kernel { FillParameter *PopulateFillParam(const lite::Primitive *primitive) { @@ -873,6 +877,22 @@ DepthToSpaceParameter *PopulateDepthToSpaceParam(const lite::Primitive *primitiv return parameter; } +SpaceToDepthParameter *PopulateSpaceToDepthParam(const lite::Primitive *primitive) { + SpaceToDepthParameter *parameter = new (std::nothrow) SpaceToDepthParameter(); + if (parameter == nullptr) { + MS_LOG(ERROR) << "new SpaceToDepthParameter failed."; + return nullptr; + } + auto param = primitive->Value()->value_as_DepthToSpace(); + parameter->op_parameter_.type_ = primitive->Type(); + parameter->block_size_ = param->blockSize(); + if (param->format() != schema::Format_NHWC) { + MS_LOG(ERROR) << "Currently only NHWC format is supported."; + return nullptr; + } + return parameter; +} + ResizeParameter *PopulateResizeParameter(const lite::Primitive *primitive) { ResizeParameter *parameter = new (std::nothrow) ResizeParameter(); if (parameter == nullptr) { @@ -961,6 +981,24 @@ FlattenParameter *PopulateFlattenParameter(const lite::Primitive *primitive) { return parameter; } +DequantizeParameter *PopulateDequantizeParameter(const lite::Primitive *primitive) { + DequantizeParameter *parameter = new (std::nothrow) DequantizeParameter(); + if (parameter == nullptr) { + MS_LOG(ERROR) << "new DequantizeParameter fail!"; + return nullptr; + } + return parameter; +} + +QuantizeParameter *PopulateQuantizeParameter(const lite::Primitive *primitive) { + QuantizeParameter *parameter = new (std::nothrow) QuantizeParameter(); + if (parameter == nullptr) { + MS_LOG(ERROR) << "new QuantizeParameter fail!"; + return nullptr; + } + return parameter; +} + StridedSliceParameter *PopulateStridedSliceParam(const lite::Primitive *primitive) { StridedSliceParameter *parameter = new (std::nothrow) StridedSliceParameter(); if (parameter == nullptr) { @@ -1045,6 +1083,24 @@ PriorBoxParameter *PopulatePriorBoxParameter(const lite::Primitive *primitive) { return param; } +SpaceToBatchParameter *PopulateSpaceToBatchParam(const lite::Primitive *primitive) { + SpaceToBatchParameter *parameter = new (std::nothrow) SpaceToBatchParameter(); + if (parameter == nullptr) { + MS_LOG(ERROR) << "new SpaceToBatchParameter failed."; + return nullptr; + } + parameter->op_parameter_.type_ = primitive->Type(); + auto block_sizes = ((lite::SpaceToBatch *)primitive)->BlockSizes(); + (void)memcpy(parameter->block_sizes_, (block_sizes.data()), block_sizes.size() * sizeof(int)); + auto paddings = ((lite::SpaceToBatch *)primitive)->Paddings(); + (void)memcpy(parameter->paddings_, (paddings.data()), paddings.size() * sizeof(int)); + auto in_shape = ((lite::SpaceToBatch *)primitive)->InShape(); + (void)memcpy(parameter->in_shape_, (in_shape.data()), in_shape.size() * sizeof(int)); + auto padded_in_shape = ((lite::SpaceToBatch *)primitive)->PaddedInShape(); + (void)memcpy(parameter->padded_in_shape_, (padded_in_shape.data()), padded_in_shape.size() * sizeof(int)); + return parameter; +} + OpParameter *PopulateParameter(const lite::Primitive *primitive) { MS_EXCEPTION_IF_NULL(primitive); auto op_type = primitive->Type(); @@ -1166,6 +1222,10 @@ OpParameter *PopulateParameter(const lite::Primitive *primitive) { return reinterpret_cast(PopulateAddNParam(primitive)); case schema::PrimitiveType_PriorBox: return reinterpret_cast(PopulatePriorBoxParameter(primitive)); + case schema::PrimitiveType_OnnxInt8Dequantize: + return reinterpret_cast(PopulateDequantizeParameter(primitive)); + case schema::PrimitiveType_OnnxInt8Quantize: + return reinterpret_cast(PopulateQuantizeParameter(primitive)); default: break; } diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/quantize.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/quantize.cc new file mode 100644 index 00000000000..f7057ba14fc --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/quantize.cc @@ -0,0 +1,118 @@ +/** + * Copyright 2020 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 "src/runtime/kernel/arm/fp32/quantize.h" +#include +#include "src/runtime/kernel/arm/opclib/fp32/quantize.h" +#include "src/kernel_registry.h" +#include "src/runtime/runtime_api.h" +#include "schema/model_generated.h" +#include "include/errorcode.h" + +using mindspore::kernel::KERNEL_ARCH::kCPU; +using mindspore::lite::KernelRegistrar; +using mindspore::lite::RET_ERROR; +using mindspore::lite::RET_OK; +using mindspore::schema::PrimitiveType_OnnxInt8Quantize; + +namespace mindspore::kernel { +namespace { +constexpr int kQuantizeInputNum = 1; +constexpr int kQuantizeOutputNum = 1; +} // namespace + +int QuantizeCPUKernel::Init() { + if (inputs_.size() != 1) { + MS_LOG(ERROR) << "inputs number should be 1, but " << inputs_.size() << " is given."; + return RET_ERROR; + } + if (outputs_.size() != 1) { + MS_LOG(ERROR) << "outputs number should be 1, but " << inputs_.size() << " is given."; + return RET_ERROR; + } + auto in_tensor = inputs_.front(); + num_unit_ = static_cast(in_tensor->DataSize()); + thread_n_num_ = MSMIN(thread_num_, num_unit_); + thread_n_stride_ = UP_DIV(num_unit_, thread_n_num_); + + return RET_OK; +} + +int QuantizeCPUKernel::ReSize() { return RET_OK; } + +int QuantizeCPUKernel::Quantize(int task_id) { + int num_unit_thread = MSMIN(thread_n_stride_, num_unit_ - task_id * thread_n_stride_); + if (num_unit_thread <= 0) { + return RET_OK; + } + int thread_offset = task_id * thread_n_stride_; + auto quant_arg = inputs_.front()->GetQuantParams().front(); + int ret = QuantizeToInt8(input_ptr_ + thread_offset, output_ptr_ + thread_offset, quant_arg.scale, + quant_arg.zeroPoint, num_unit_thread); + + if (ret != RET_OK) { + MS_LOG(ERROR) << "Quantize error task_id[" << task_id << "] error_code[" << ret << "]"; + return RET_ERROR; + } + return RET_OK; +} + +int QuantizeRun(int task_id, LiteParallelGroupEnv *penv, void *cdata) { + auto g_kernel = reinterpret_cast(cdata); + auto ret = g_kernel->Quantize(task_id); + if (ret != RET_OK) { + MS_LOG(ERROR) << "QuantizeRun error task_id[" << task_id << "] error_code[" << ret << "]"; + return RET_ERROR; + } + return RET_OK; +} + +int QuantizeCPUKernel::Run() { + input_ptr_ = reinterpret_cast(inputs_[0]->Data()); + output_ptr_ = reinterpret_cast(outputs_[0]->Data()); + int ret = LiteBackendParallelLaunch(QuantizeRun, this, thread_n_num_); + if (ret != RET_OK) { + MS_LOG(ERROR) << "Scale error error_code[" << ret << "]"; + return RET_ERROR; + } + + return RET_OK; +} + +kernel::LiteKernel *CpuQuantizeFp32KernelCreator(const std::vector &inputs, + const std::vector &outputs, + OpParameter *opParameter, const lite::Context *ctx, + const kernel::KernelKey &desc) { + if (opParameter == nullptr) { + MS_LOG(ERROR) << "Input opParameter is nullptr!"; + return nullptr; + } + auto *kernel = new (std::nothrow) QuantizeCPUKernel(opParameter, inputs, outputs, ctx); + if (kernel == nullptr) { + MS_LOG(ERROR) << "new QuantizeCPUKernel fail!"; + return nullptr; + } + auto ret = kernel->Init(); + if (ret != RET_OK) { + MS_LOG(ERROR) << "Init kernel failed! name: " << opParameter->name_ << ", type: " + << schema::EnumNamePrimitiveType(static_cast(opParameter->type_)); + delete kernel; + return nullptr; + } + return kernel; +} + +REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_OnnxInt8Quantize, CpuQuantizeFp32KernelCreator) +} // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/quantize.h b/mindspore/lite/src/runtime/kernel/arm/fp32/quantize.h new file mode 100644 index 00000000000..64540e647b2 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/quantize.h @@ -0,0 +1,46 @@ +/** + * Copyright 2020 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_SRC_RUNTIME_KERNEL_ARM_FP32_QUANTIZE_H_ +#define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_QUANTIZE_H_ + +#include +#include "src/lite_kernel.h" + +namespace mindspore::kernel { +class QuantizeCPUKernel : public LiteKernel { + public: + QuantizeCPUKernel(OpParameter *parameter, const std::vector &inputs, + const std::vector &outputs, const lite::Context *ctx) + : LiteKernel(parameter, inputs, outputs), thread_num_(ctx->threadNum) {} + ~QuantizeCPUKernel() = default; + + int Init() override; + int ReSize() override; + int Run() override; + int Quantize(int task_id); + + private: + int thread_num_; + int thread_n_num_; + int thread_n_stride_; + int num_unit_; + float *input_ptr_; + int8_t *output_ptr_; +}; +} // namespace mindspore::kernel + +#endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_QUANTIZE_H_ diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_batch.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_batch.cc new file mode 100644 index 00000000000..431a445d954 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_batch.cc @@ -0,0 +1,106 @@ +/** + * Copyright 2020 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 "src/runtime/kernel/arm/fp32/space_to_batch.h" +#include +#include "schema/ops_generated.h" +#include "schema/model_generated.h" +#include "src/kernel_registry.h" +#include "src/runtime/kernel/arm/opclib/fp32/space_to_batch.h" +#include "src/runtime/kernel/arm/opclib/errorcode.h" +#include "include/errorcode.h" + +using mindspore::lite::KernelRegistrar; +using mindspore::lite::RET_FORMAT_ERR; +using mindspore::lite::RET_OK; +using mindspore::lite::RET_OP_EXECUTE_FAILURE; +using mindspore::schema::PrimitiveType_SpaceToBatch; + +namespace mindspore::kernel { + +int SpaceToBatchCPUKernel::Init() { + if (inputs_[0]->GetFormat() != schema::Format_NHWC) { + MS_LOG(ERROR) << "space_to_batch only support NHWC now!"; + return RET_FORMAT_ERR; + } + SpaceToBatchParameter *param = reinterpret_cast(this->opParameter); + for (int i = 0; i < SPACE_TO_BATCH_PADDINGS_SIZE; ++i) { + if (param->paddings_[i] != 0) { + param->need_paddings_ = true; + break; + } + } + param->n_dims_ = DIMENSION_4D; + param->n_space_dims_ = SPACE_TO_BATCH_BLOCK_SIZES_SIZE; + param->num_elements_ = EnumElement(param->in_shape_, param->n_dims_); + param->num_elements_padded_ = EnumElement(param->padded_in_shape_, param->n_dims_); + return RET_OK; +} + +int SpaceToBatchCPUKernel::Run() { + auto input = inputs_[0]; + auto output = outputs_[0]; + input_ptr_ = reinterpret_cast(input->Data()); + output_ptr_ = reinterpret_cast(output->Data()); + SpaceToBatchParameter *param = reinterpret_cast(this->opParameter); + + int ret; + float *tmp_space[3] = {nullptr, nullptr, nullptr}; + if (param->need_paddings_) { + tmp_space[0] = reinterpret_cast(malloc(param->num_elements_padded_ * sizeof(float))); + (void)memset(tmp_space[0], 0, param->num_elements_padded_); + tmp_space[1] = reinterpret_cast(malloc(param->num_elements_padded_ * sizeof(float))); + (void)memset(tmp_space[1], 0, param->num_elements_padded_); + tmp_space[2] = reinterpret_cast(malloc(param->num_elements_padded_ * sizeof(float))); + (void)memset(tmp_space[2], 0, param->num_elements_padded_); + + ret = SpaceToBatch(input_ptr_, output_ptr_, *param, tmp_space); + } else { + ret = SpaceToBatch(input_ptr_, output_ptr_, *param, tmp_space); + } + if (ret != OPCLIB_OK) { + MS_LOG(ERROR) << "Do space to batch fails!"; + return RET_OP_EXECUTE_FAILURE; + } + + return RET_OK; +} + +kernel::LiteKernel *CpuSpaceToBatchFp32KernelCreator(const std::vector &inputs, + const std::vector &outputs, + OpParameter *opParameter, const lite::Context *ctx, + const kernel::KernelKey &desc) { + if (opParameter == nullptr) { + MS_LOG(ERROR) << "Input opParameter is nullptr!"; + return nullptr; + } + auto *kernel = new (std::nothrow) SpaceToBatchCPUKernel(opParameter, inputs, outputs); + if (kernel == nullptr) { + MS_LOG(ERROR) << "new SpaceToBatchCPUKernel fail!"; + return nullptr; + } + + auto ret = kernel->Init(); + if (ret != RET_OK) { + delete kernel; + MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " + << schema::EnumNamePrimitiveType(static_cast(opParameter->type_)); + return nullptr; + } + return kernel; +} + +REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_SpaceToBatch, CpuSpaceToBatchFp32KernelCreator) +} // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_batch.h b/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_batch.h new file mode 100644 index 00000000000..510649f2c06 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_batch.h @@ -0,0 +1,41 @@ +/** + * Copyright 2020 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_SRC_RUNTIME_KERNEL_ARM_FP32_SPACE_TO_BATCH_H_ +#define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_SPACE_TO_BATCH_H_ + +#include +#include "src/lite_kernel.h" + +namespace mindspore::kernel { +class SpaceToBatchCPUKernel : public LiteKernel { + public: + SpaceToBatchCPUKernel(OpParameter *parameter, const std::vector &inputs, + const std::vector &outputs) + : LiteKernel(parameter, inputs, outputs) {} + + ~SpaceToBatchCPUKernel() = default; + + int Init() override; + int ReSize() override { return 0; } + int Run() override; + + private: + const float *input_ptr_; + float *output_ptr_; +}; +} // namespace mindspore::kernel + +#endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_SPACE_TO_BATCH_H_ diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_depth.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_depth.cc new file mode 100644 index 00000000000..8f26a731a17 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_depth.cc @@ -0,0 +1,89 @@ +/** + * Copyright 2020 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 "src/runtime/kernel/arm/fp32/space_to_depth.h" +#include +#include "schema/ops_generated.h" +#include "schema/model_generated.h" +#include "src/kernel_registry.h" +#include "src/runtime/kernel/arm/opclib/fp32/space_to_depth.h" +#include "include/errorcode.h" + +using mindspore::lite::KernelRegistrar; +using mindspore::lite::RET_ERROR; +using mindspore::lite::RET_FORMAT_ERR; +using mindspore::lite::RET_OK; +using mindspore::lite::RET_PARAM_INVALID; +using mindspore::schema::PrimitiveType_SpaceToDepth; + +namespace mindspore::kernel { + +int SpaceToDepthCPUKernel::Init() { + if (inputs_[0]->GetFormat() != schema::Format_NHWC) { + MS_LOG(ERROR) << "space_to_depth only support NHWC now!"; + return RET_FORMAT_ERR; + } + SpaceToDepthParameter *param = reinterpret_cast(opParameter); + if (param->block_size_ <= 0) { + MS_LOG(ERROR) << "Input block_size should > 0!"; + return RET_PARAM_INVALID; + } + return RET_OK; +} + +int SpaceToDepthCPUKernel::Run() { + auto input = inputs_[0]; + auto output = outputs_[0]; + const float *input_data = static_cast(input->Data()); + float *output_data = static_cast(output->Data()); + auto in_shape = input->shape(); + auto out_shape = output->shape(); + SpaceToDepthParameter *param = reinterpret_cast(opParameter); + if (input->GetFormat() == schema::Format_NHWC) { + auto ret = SpaceToDepthForNHWC(input_data, output_data, in_shape.data(), out_shape.data(), in_shape.size(), + param->block_size_); + return ret; + } else { + MS_LOG(ERROR) << "Only support NHWC now!"; + return RET_ERROR; + } +} +kernel::LiteKernel *CpuSpaceToDepthFp32KernelCreator(const std::vector &inputs, + const std::vector &outputs, + OpParameter *opParameter, const lite::Context *ctx, + const kernel::KernelKey &desc) { + if (opParameter == nullptr) { + MS_LOG(ERROR) << "Input opParameter is nullptr!"; + return nullptr; + } + auto *kernel = new (std::nothrow) SpaceToDepthCPUKernel(opParameter, inputs, outputs); + if (kernel == nullptr) { + MS_LOG(ERROR) << "new SpaceToDepthCPUKernel fail!"; + return nullptr; + } + + auto ret = kernel->Init(); + if (ret != RET_OK) { + delete kernel; + MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " + << schema::EnumNamePrimitiveType(static_cast(opParameter->type_)); + return nullptr; + } + return kernel; +} + +REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_SpaceToDepth, CpuSpaceToDepthFp32KernelCreator) +} // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_depth.h b/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_depth.h new file mode 100644 index 00000000000..c2a76c87559 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/space_to_depth.h @@ -0,0 +1,37 @@ +/** + * Copyright 2020 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_SRC_BACKEND_ARM_FP32_SPACE_TO_DEPTH_H_ +#define MINDSPORE_LITE_SRC_BACKEND_ARM_FP32_SPACE_TO_DEPTH_H_ + +#include +#include "src/lite_kernel.h" +#include "ir/anf.h" + +namespace mindspore::kernel { +class SpaceToDepthCPUKernel : public LiteKernel { + public: + SpaceToDepthCPUKernel(OpParameter *parameter, const std::vector &inputs, + const std::vector &outputs) + : LiteKernel(parameter, inputs, outputs) {} + ~SpaceToDepthCPUKernel() = default; + + int Init() override; + int ReSize() override { return 0; }; + int Run() override; +}; +} // namespace mindspore::kernel + +#endif // MINDSPORE_LITE_SRC_BACKEND_ARM_FP32_SPACE_TO_DEPTH_H_ diff --git a/mindspore/lite/src/runtime/kernel/arm/int8/dequantize.cc b/mindspore/lite/src/runtime/kernel/arm/int8/dequantize.cc new file mode 100644 index 00000000000..d9f6bfebd95 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/int8/dequantize.cc @@ -0,0 +1,118 @@ +/** + * Copyright 2020 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 "src/runtime/kernel/arm/int8/dequantize.h" +#include +#include "src/runtime/kernel/arm/opclib/int8/dequantize.h" +#include "src/runtime/runtime_api.h" +#include "src/kernel_registry.h" +#include "schema/model_generated.h" +#include "include/errorcode.h" + +using mindspore::kernel::KERNEL_ARCH::kCPU; +using mindspore::lite::KernelRegistrar; +using mindspore::lite::RET_ERROR; +using mindspore::lite::RET_OK; +using mindspore::schema::PrimitiveType_OnnxInt8Dequantize; + +namespace mindspore::kernel { +namespace { +constexpr int kDequantizeInputNum = 1; +constexpr int kDequantizeOutputNum = 1; +} // namespace + +int DequantizeCPUKernel::Init() { + if (inputs_.size() != 1) { + MS_LOG(ERROR) << "inputs number should be 1, but " << inputs_.size() << " is given."; + return RET_ERROR; + } + if (outputs_.size() != 1) { + MS_LOG(ERROR) << "outputs number should be 1, but " << inputs_.size() << " is given."; + return RET_ERROR; + } + auto in_tensor = inputs_.front(); + num_unit_ = static_cast(in_tensor->DataSize()); + thread_n_num_ = MSMIN(thread_num_, num_unit_); + thread_n_stride_ = UP_DIV(num_unit_, thread_n_num_); + + return RET_OK; +} + +int DequantizeCPUKernel::ReSize() { return RET_OK; } + +int DequantizeCPUKernel::Dequantize(int task_id) { + int num_unit_thread = MSMIN(thread_n_stride_, num_unit_ - task_id * thread_n_stride_); + if (num_unit_thread <= 0) { + return RET_OK; + } + int thread_offset = task_id * thread_n_stride_; + auto quant_arg = inputs_.front()->GetQuantParams().front(); + int ret = DequantizeInt8(input_ptr_ + thread_offset, output_ptr_ + thread_offset, quant_arg.scale, + quant_arg.zeroPoint, num_unit_thread); + + if (ret != RET_OK) { + MS_LOG(ERROR) << "Dequantize error task_id[" << task_id << "] error_code[" << ret << "]"; + return RET_ERROR; + } + return RET_OK; +} + +int DequantizeRun(int task_id, LiteParallelGroupEnv *penv, void *cdata) { + auto g_kernel = reinterpret_cast(cdata); + auto ret = g_kernel->Dequantize(task_id); + if (ret != RET_OK) { + MS_LOG(ERROR) << "DequantizeRun error task_id[" << task_id << "] error_code[" << ret << "]"; + return RET_ERROR; + } + return RET_OK; +} + +int DequantizeCPUKernel::Run() { + input_ptr_ = reinterpret_cast(inputs_[0]->Data()); + output_ptr_ = reinterpret_cast(outputs_[0]->Data()); + int ret = LiteBackendParallelLaunch(DequantizeRun, this, thread_n_num_); + if (ret != RET_OK) { + MS_LOG(ERROR) << "Scale error error_code[" << ret << "]"; + return RET_ERROR; + } + + return RET_OK; +} + +kernel::LiteKernel *CpuDequantizeFp32KernelCreator(const std::vector &inputs, + const std::vector &outputs, + OpParameter *opParameter, const lite::Context *ctx, + const kernel::KernelKey &desc) { + if (opParameter == nullptr) { + MS_LOG(ERROR) << "Input opParameter is nullptr!"; + return nullptr; + } + auto *kernel = new (std::nothrow) DequantizeCPUKernel(opParameter, inputs, outputs, ctx); + if (kernel == nullptr) { + MS_LOG(ERROR) << "new DequantizeCPUKernel fail!"; + return nullptr; + } + auto ret = kernel->Init(); + if (ret != RET_OK) { + MS_LOG(ERROR) << "Init kernel failed! name: " << opParameter->name_ << ", type: " + << schema::EnumNamePrimitiveType(static_cast(opParameter->type_)); + delete kernel; + return nullptr; + } + return kernel; +} + +REG_KERNEL(kCPU, kNumberTypeInt8, PrimitiveType_OnnxInt8Dequantize, CpuDequantizeFp32KernelCreator) +} // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/int8/dequantize.h b/mindspore/lite/src/runtime/kernel/arm/int8/dequantize.h new file mode 100644 index 00000000000..0d913b54831 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/int8/dequantize.h @@ -0,0 +1,46 @@ +/** + * Copyright 2020 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_SRC_RUNTIME_KERNEL_ARM_INT8_DEQUANTIZE_H_ +#define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_INT8_DEQUANTIZE_H_ + +#include +#include "src/lite_kernel.h" + +namespace mindspore::kernel { +class DequantizeCPUKernel : public LiteKernel { + public: + DequantizeCPUKernel(OpParameter *parameter, const std::vector &inputs, + const std::vector &outputs, const lite::Context *ctx) + : LiteKernel(parameter, inputs, outputs), thread_num_(ctx->threadNum) {} + ~DequantizeCPUKernel() = default; + + int Init() override; + int ReSize() override; + int Run() override; + int Dequantize(int task_id); + + private: + int thread_num_; + int thread_n_num_; + int thread_n_stride_; + int num_unit_; + int8_t *input_ptr_; + float *output_ptr_; +}; +} // namespace mindspore::kernel + +#endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_INT8_DEQUANTIZE_H_ diff --git a/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/quantize.cc b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/quantize.cc new file mode 100644 index 00000000000..07913eb5798 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/quantize.cc @@ -0,0 +1,29 @@ +/** + * Copyright 2020 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 "src/runtime/kernel/arm/opclib/fp32/quantize.h" +#include "src/runtime/kernel/arm/opclib/errorcode.h" + +int QuantizeToInt8(float *real_values, int8_t *quant_values, float scale, int32_t zp, int size) { + if (quant_values == nullptr || real_values == nullptr) { + return OPCLIB_PARAM_INVALID; + } + + for (int i = 0; i < size; ++i) { + quant_values[i] = (int8_t)round(real_values[i] / scale + zp); + } + return OPCLIB_OK; +} diff --git a/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/quantize.h b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/quantize.h new file mode 100644 index 00000000000..5acf127bd18 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/quantize.h @@ -0,0 +1,28 @@ +/** + * Copyright 2020 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_SRC_RUNTIME_KERNEL_ARM_OPCLIB_FP32_QUANTIZE_H_ +#define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_OPCLIB_FP32_QUANTIZE_H_ + +#include "src/runtime/kernel/arm/opclib/op_base.h" + +struct QuantizeParameter { + OpParameter op_parameter_; +}; + +int QuantizeToInt8(float *real_values, int8_t *quant_values, float scale, int32_t zp, int size); + +#endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_OPCLIB_FP32_QUANTIZE_H_ diff --git a/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_batch.cc b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_batch.cc new file mode 100644 index 00000000000..1861ea4430c --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_batch.cc @@ -0,0 +1,157 @@ +/** + * Copyright 2020 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 "src/runtime/kernel/arm/opclib/fp32/space_to_batch.h" +#include "src/runtime/kernel/arm/opclib/arithmetic_common.h" +#include "src/runtime/kernel/arm/opclib/errorcode.h" +#include "src/runtime/kernel/arm/opclib/fp32/concat.h" +#include "src/runtime/kernel/arm/opclib/op_base.h" + +int EnumElement(int *shape, int n_dims) { + int total = 1; + for (int i = 0; i < n_dims; i++) { + total *= shape[i]; + } + return total; +} + +void TransposeForNHWC(const float *in_data, float *out_data, int *strides, int *out_strides, int *perm, + int *output_shape) { + const int stride0 = strides[perm[0]]; + const int stride1 = strides[perm[1]]; + const int stride2 = strides[perm[2]]; + const int stride3 = strides[perm[3]]; + const int stride4 = strides[perm[4]]; + const int out_stride0 = out_strides[0]; + const int out_stride1 = out_strides[1]; + const int out_stride2 = out_strides[2]; + const int out_stride3 = out_strides[3]; + const int out_stride4 = out_strides[4]; + const int output0 = output_shape[0]; + const int output1 = output_shape[1]; + const int output2 = output_shape[2]; + const int output3 = output_shape[3]; + const int output4 = output_shape[4]; + + for (int i = 0; i < output0; ++i) { + int out_stride0_i = i * out_stride0; + int stride0_i = i * stride0; + for (int j = 0; j < output1; ++j) { + int out_stride1_j = j * out_stride1; + int stride1_j = j * stride1; + for (int k = 0; k < output2; ++k) { + int out_stride2_k = k * out_stride2; + int stride2_k = k * stride2; + for (int m = 0; m < output3; ++m) { + int out_stride3_m = m * out_stride3; + int stride3_m = m * stride3; + for (int n = 0; n < output4; ++n) { + int out_stride4_n = n * out_stride4; + int stride4_n = n * stride4; + memcpy(out_data + out_stride0_i + out_stride1_j + out_stride2_k + out_stride3_m + out_stride4_n, + in_data + stride0_i + stride1_j + stride2_k + stride3_m + stride4_n, stride4 * sizeof(float)); + } + } + } + } + } +} + +int SpaceToBatchForNHWC(const float *input, float *output, int *in_shape, int shape_size, int *block_sizes) { + int trans_in_shape[6] = {in_shape[0], in_shape[1] / block_sizes[0], + block_sizes[0], in_shape[2] / block_sizes[1], + block_sizes[1], in_shape[3]}; + int trans_out_shape[6] = { + in_shape[0], block_sizes[0], block_sizes[1], in_shape[1] / block_sizes[0], in_shape[2] / block_sizes[1], + in_shape[3]}; + int in_strides[C4NUM + 2]; + ComputeStrides(trans_in_shape, in_strides, shape_size + 2); + int out_strides[C4NUM + 2]; + ComputeStrides(trans_out_shape, out_strides, shape_size + 2); + + int perm[6] = {0, 2, 4, 1, 3, 5}; + TransposeForNHWC(input, output, in_strides, out_strides, perm, trans_out_shape); + return OPCLIB_OK; +} + +void DoPadding(const float *input, float *padded_input, SpaceToBatchParameter param, float *tmp_space[]) { + float *tmp = padded_input; + (void)memcpy(tmp, input, param.num_elements_ * sizeof(float)); + float *target = tmp_space[0]; + float *tmp_zeros = tmp_space[1]; + float *tmp2 = nullptr; + int cur_shape[param.n_dims_], cur_start_shape[param.n_dims_], cur_end_shape[param.n_dims_], + cur_target_shape[param.n_dims_]; + float *concat_inputs[3]; + int *concat_shapes[4]; + + for (int i = 0; i < param.n_dims_; i++) { + cur_shape[i] = param.in_shape_[i]; + cur_start_shape[i] = param.in_shape_[i]; + cur_end_shape[i] = param.in_shape_[i]; + cur_target_shape[i] = param.in_shape_[i]; + } + for (int i = 0; i < param.n_space_dims_; ++i) { + if (param.padded_in_shape_[i + 1] > param.in_shape_[i + 1]) { + int concat_idx = 0; + cur_target_shape[i + 1] = 0; + if (param.paddings_[2 * i] != 0) { + cur_start_shape[i + 1] = param.paddings_[2 * i]; + concat_inputs[concat_idx] = tmp_zeros; + concat_shapes[concat_idx++] = cur_start_shape; + cur_target_shape[i + 1] += cur_start_shape[i + 1]; + } + + concat_inputs[concat_idx] = tmp; + concat_shapes[concat_idx++] = cur_shape; + cur_target_shape[i + 1] += cur_shape[i + 1]; + if (param.paddings_[2 * i + 1] != 0) { + cur_end_shape[i + 1] = param.paddings_[2 * i + 1]; + concat_inputs[concat_idx] = tmp_zeros; + concat_shapes[concat_idx++] = cur_end_shape; + cur_target_shape[i + 1] += cur_end_shape[i + 1]; + } + concat_shapes[concat_idx] = cur_target_shape; + Concat((void **)concat_inputs, concat_idx, i + 1, concat_shapes, param.n_dims_, target); + + tmp2 = tmp; + tmp = target; + target = tmp2; + cur_start_shape[i + 1] = cur_end_shape[i + 1] = cur_shape[i + 1] = concat_shapes[concat_idx][i + 1]; + } + } + if (padded_input != tmp) { + memcpy(padded_input, tmp, param.num_elements_padded_ * sizeof(float)); + } +} + +int SpaceToBatch(const float *input, float *output, SpaceToBatchParameter param, float *tmp_space[3]) { + float *padded_input; + int ret; + if (param.need_paddings_) { + if (tmp_space[0] == nullptr || tmp_space[1] == nullptr || tmp_space[2] == nullptr) { + return OPCLIB_NULL_PTR; + } + padded_input = tmp_space[0]; + DoPadding(input, padded_input, param, tmp_space + 1); + } + + if (param.need_paddings_) { + ret = SpaceToBatchForNHWC(padded_input, output, param.padded_in_shape_, param.n_dims_, param.block_sizes_); + } else { + ret = SpaceToBatchForNHWC(input, output, param.padded_in_shape_, param.n_dims_, param.block_sizes_); + } + return ret; +} diff --git a/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_batch.h b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_batch.h new file mode 100644 index 00000000000..cf04b9f9a4e --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_batch.h @@ -0,0 +1,42 @@ +/** + * Copyright 2020 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_SRC_BACKEND_ARM_OPCLIB_FP32_SPACE_TO_BATCH_H_ +#define MINDSPORE_LITE_SRC_BACKEND_ARM_OPCLIB_FP32_SPACE_TO_BATCH_H_ +#include "src/runtime/kernel/arm/opclib/op_base.h" + +#define SPACE_TO_BATCH_BLOCK_SIZES_SIZE 2 +#define SPACE_TO_BATCH_PADDINGS_SIZE 4 + +struct SpaceToBatchParameter { + OpParameter op_parameter_; + int block_sizes_[8]; + int paddings_[8]; + int n_dims_; + int num_elements_; + int num_elements_padded_; + int n_space_dims_; + int in_shape_[8]; + int padded_in_shape_[8]; + bool need_paddings_ = false; +}; + +int SpaceToBatch(const float *input, float *output, SpaceToBatchParameter param, float *tmp_space[3]); +int SpaceToBatchForNHWC(const float *input, float *output, int *in_shape, int shape_size, int *block_size); +void TransposeForNHWC(const float *in_data, float *out_data, int *strides, int *out_strides, int *perm, + int *output_shape); +void DoPadding(const float *input, float *padded_input, SpaceToBatchParameter param); +int EnumElement(int *shape, int n_dims); +#endif // MINDSPORE_LITE_SRC_BACKEND_ARM_OPCLIB_FP32_SPACE_TO_BATCH_H_ diff --git a/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_depth.cc b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_depth.cc new file mode 100644 index 00000000000..38313ac7a5f --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_depth.cc @@ -0,0 +1,50 @@ +/** + * Copyright 2020 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 "src/runtime/kernel/arm/opclib/fp32/space_to_depth.h" +#include "src/runtime/kernel/arm/opclib/arithmetic_common.h" +#include "src/runtime/kernel/arm/opclib/errorcode.h" +#include "src/runtime/kernel/arm/opclib/op_base.h" + +int SpaceToDepthForNHWC(const float *input, float *output, int *in_shape, int *out_shape, int shape_size, + int block_size) { + if (input == nullptr || output == nullptr) { + return OPCLIB_NULL_PTR; + } + if (shape_size != C4NUM) { + return OPCLIB_PARAM_INVALID; + } + int in_strides[C4NUM]; + ComputeStrides(in_shape, in_strides, shape_size); + int out_strides[C4NUM]; + ComputeStrides(out_shape, out_strides, shape_size); + for (int i = 0; i < out_shape[0]; ++i) { + size_t in_offset_n = i * in_strides[0]; + size_t out_offset_n = i * out_strides[0]; + for (int j = 0; j < out_shape[1]; ++j) { + size_t in_offset_h = in_offset_n + j * block_size * in_strides[1]; + size_t out_offset_h = out_offset_n + j * out_strides[1]; + for (int k = 0; k < out_shape[2]; ++k) { + size_t in_offset_w = in_offset_h + k * block_size * in_strides[2]; + size_t out_offset_w = out_offset_h + k * out_strides[2]; + for (int l = 0; l < block_size; ++l) { + memcpy(output + out_offset_w + l * block_size * in_strides[2], input + in_offset_w + l * in_strides[1], + block_size * in_strides[2] * sizeof(float)); + } + } + } + } + return OPCLIB_OK; +} diff --git a/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_depth.h b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_depth.h new file mode 100644 index 00000000000..752c9cc4d10 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_depth.h @@ -0,0 +1,27 @@ +/** + * Copyright 2020 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_SRC_BACKEND_ARM_OPCLIB_FP32_SPACE_TO_DEPTH_H_ +#define MINDSPORE_LITE_SRC_BACKEND_ARM_OPCLIB_FP32_SPACE_TO_DEPTH_H_ +#include "src/runtime/kernel/arm/opclib/op_base.h" + +struct SpaceToDepthParameter { + OpParameter op_parameter_; + int32_t block_size_; +}; + +int SpaceToDepthForNHWC(const float *input, float *output, int *in_shape, int *out_shape, int shape_size, + int block_size); +#endif // MINDSPORE_LITE_SRC_BACKEND_ARM_OPCLIB_FP32_SPACE_TO_DEPTH_H_ diff --git a/mindspore/lite/src/runtime/kernel/arm/opclib/int8/dequantize.cc b/mindspore/lite/src/runtime/kernel/arm/opclib/int8/dequantize.cc new file mode 100644 index 00000000000..5365f907291 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/opclib/int8/dequantize.cc @@ -0,0 +1,29 @@ +/** + * Copyright 2020 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 "src/runtime/kernel/arm/opclib/int8/dequantize.h" +#include "src/runtime/kernel/arm/opclib/errorcode.h" + +int DequantizeInt8(int8_t *quant_values, float *real_values, float scale, int32_t zp, int size) { + if (quant_values == nullptr || real_values == nullptr) { + return OPCLIB_PARAM_INVALID; + } + + for (int i = 0; i < size; ++i) { + real_values[i] = (quant_values[i] + zp) * scale; + } + return OPCLIB_OK; +} diff --git a/mindspore/lite/src/runtime/kernel/arm/opclib/int8/dequantize.h b/mindspore/lite/src/runtime/kernel/arm/opclib/int8/dequantize.h new file mode 100644 index 00000000000..c3588360163 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/opclib/int8/dequantize.h @@ -0,0 +1,28 @@ +/** + * Copyright 2020 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_SRC_RUNTIME_KERNEL_ARM_OPCLIB_INT8_DEQUANTIZE_H_ +#define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_OPCLIB_INT8_DEQUANTIZE_H_ + +#include "src/runtime/kernel/arm/opclib/op_base.h" + +struct DequantizeParameter { + OpParameter op_parameter_; +}; + +int DequantizeInt8(int8_t *quant_values, float *real_values, float scale, int32_t zp, int size); + +#endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_OPCLIB_INT8_DEQUANTIZE_H_ diff --git a/mindspore/lite/test/ut/src/runtime/kernel/arm/fp32/quantize_fp32_tests.cc b/mindspore/lite/test/ut/src/runtime/kernel/arm/fp32/quantize_fp32_tests.cc new file mode 100644 index 00000000000..74f1687699a --- /dev/null +++ b/mindspore/lite/test/ut/src/runtime/kernel/arm/fp32/quantize_fp32_tests.cc @@ -0,0 +1,77 @@ +/** + * Copyright 2020 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 +#include +#include "utils/log_adapter.h" +#include "common/common_test.h" +#include "mindspore/lite/src/runtime/kernel/arm/fp32/quantize.h" +#include "mindspore/lite/src/runtime/kernel/arm/opclib/fp32/quantize.h" +#include "mindspore/lite/src/kernel_registry.h" +#include "mindspore/lite/src/lite_kernel.h" + +namespace mindspore { + +class QuantizeTestFp32 : public mindspore::Common { + public: + QuantizeTestFp32() {} +}; + +TEST_F(QuantizeTestFp32, QuantizeTest1) { + const lite::tensor::QuantArg quant_arg = {0.3515625, -57}; + QuantizeParameter param; + param.op_parameter_.type_ = schema::PrimitiveType_OnnxInt8Quantize; + + std::vector input = {1, 2, 5, 6, 10, -20, 3, 8, 18, 10, 3, 4, 11, 16, 15, 25}; + std::vector in_shape = {1, 4, 4, 1}; + lite::tensor::Tensor input_tensor; + input_tensor.SetData(input.data()); + input_tensor.set_shape(in_shape); + input_tensor.SetFormat(schema::Format_NHWC); + input_tensor.set_data_type(kNumberTypeFloat32); + input_tensor.AddQuantParam(quant_arg); + std::vector inputs_tensor; + inputs_tensor.emplace_back(&input_tensor); + + const int out_size = 16; + int8_t expect_out[16] = {-54, -51, -43, -40, -29, -114, -48, -34, -6, -29, -48, -46, -26, -11, -14, 14}; + std::vector output(16); + std::vector out_shape = {1, 4, 4, 1}; + lite::tensor::Tensor output_tensor; + output_tensor.SetData(output.data()); + output_tensor.set_shape(out_shape); + output_tensor.SetFormat(schema::Format_NHWC); + output_tensor.set_data_type(kNumberTypeInt8); + std::vector outputs_tensor; + outputs_tensor.emplace_back(&output_tensor); + + lite::Context ctx; + ctx.threadNum = 3; + kernel::KernelKey desc = {kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, schema::PrimitiveType_OnnxInt8Quantize}; + auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); + ASSERT_NE(creator, nullptr); + kernel::LiteKernel *kernel = + creator(inputs_tensor, outputs_tensor, reinterpret_cast(¶m), &ctx, desc); + ASSERT_NE(kernel, nullptr); + kernel->Run(); + + for (int i = 0; i < out_size; ++i) { + std::cout << output[i] << " "; + } + std::cout << "\n"; + CompareOutputData(output.data(), expect_out, out_size, 0.000001); +} + +} // namespace mindspore diff --git a/mindspore/lite/test/ut/src/runtime/kernel/arm/fp32/space_to_batch_fp32_tests.cc b/mindspore/lite/test/ut/src/runtime/kernel/arm/fp32/space_to_batch_fp32_tests.cc new file mode 100644 index 00000000000..eafafe80119 --- /dev/null +++ b/mindspore/lite/test/ut/src/runtime/kernel/arm/fp32/space_to_batch_fp32_tests.cc @@ -0,0 +1,163 @@ +/** + * Copyright 2020 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 +#include +#include "utils/log_adapter.h" +#include "common/common_test.h" +#include "mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_batch.h" +#include "mindspore/lite/src/kernel_registry.h" +#include "mindspore/lite/src/lite_kernel.h" + +namespace mindspore { + +class SpaceToBatchTestFp32 : public mindspore::Common { + public: + SpaceToBatchTestFp32() {} +}; + +int InitSpaceToBatchParameter(SpaceToBatchParameter *param) { + param->n_dims_ = 4; + param->n_space_dims_ = 2; + + param->block_sizes_[0] = 2; + param->block_sizes_[1] = 2; + + param->paddings_[0] = 2; + param->paddings_[1] = 0; + param->paddings_[2] = 2; + param->paddings_[3] = 2; + + param->in_shape_[0] = 1; + param->in_shape_[1] = 4; + param->in_shape_[2] = 4; + param->in_shape_[3] = 1; + + param->padded_in_shape_[0] = 1; + param->padded_in_shape_[1] = 6; + param->padded_in_shape_[2] = 8; + param->padded_in_shape_[3] = 1; + + param->num_elements_ = 16; + param->num_elements_padded_ = 48; + + param->need_paddings_ = true; +} + +int InitSpaceToBatchParameter2(SpaceToBatchParameter *param) { + param->block_sizes_[0] = 2; + param->block_sizes_[1] = 2; + + param->paddings_[0] = 2; + param->paddings_[1] = 0; + param->paddings_[2] = 2; + param->paddings_[3] = 2; + + param->in_shape_[0] = 1; + param->in_shape_[1] = 4; + param->in_shape_[2] = 4; + param->in_shape_[3] = 1; + + param->padded_in_shape_[0] = 1; + param->padded_in_shape_[1] = 6; + param->padded_in_shape_[2] = 8; + param->padded_in_shape_[3] = 1; +} + +TEST_F(SpaceToBatchTestFp32, SpaceToBatchTest1) { + float input[16] = {1, 2, 5, 6, 10, 20, 3, 8, 18, 10, 3, 4, 11, 55, 15, 25}; + const int out_size = 16; + float expect_out[16] = {1, 5, 18, 3, 2, 6, 10, 4, 10, 3, 11, 15, 20, 8, 55, 25}; + + float output[16]; + int in_shape[4] = {1, 4, 4, 1}; + int out_shape[4] = {4, 2, 2, 1}; + int block_sizes[2] = {2, 2}; + SpaceToBatchForNHWC((const float *)input, output, in_shape, 4, block_sizes); + for (int i = 0; i < out_size; ++i) { + std::cout << output[i] << " "; + } + std::cout << "\n"; + CompareOutputData(output, expect_out, out_size, 0.000001); +} + +TEST_F(SpaceToBatchTestFp32, SpaceToBatchTest2) { + SpaceToBatchParameter param; + InitSpaceToBatchParameter(¶m); + float input[16] = {1, 2, 5, 6, 10, 20, 3, 8, 18, 10, 3, 4, 11, 55, 15, 25}; + const int out_size = 48; + float expect_out[48] = {0, 0, 0, 0, 0, 1, 5, 0, 0, 18, 3, 0, 0, 0, 0, 0, 0, 2, 6, 0, 0, 10, 4, 0, + 0, 0, 0, 0, 0, 10, 3, 0, 0, 11, 15, 0, 0, 0, 0, 0, 0, 20, 8, 0, 0, 55, 25, 0}; + float output[48]; + int in_shape[4] = {1, 4, 4, 1}; + int out_shape[4] = {4, 3, 4, 1}; + int block_sizes[2] = {2, 2}; + + float padded_input[48]{}, tmp[48]{}, tmp_zero[48]{}; + float *tmp_space[3] = {padded_input, tmp, tmp_zero}; + auto ret = SpaceToBatch((const float *)input, output, param, tmp_space); + std::cout << "return " << ret << std::endl; + for (int i = 0; i < out_size; ++i) { + std::cout << output[i] << " "; + } + std::cout << "\n"; + CompareOutputData(output, expect_out, out_size, 0.000001); +} + +TEST_F(SpaceToBatchTestFp32, SpaceToBatchTest3) { + SpaceToBatchParameter param; + InitSpaceToBatchParameter2(¶m); + param.op_parameter_.type_ = schema::PrimitiveType_SpaceToBatch; + + std::vector input = {1, 2, 5, 6, 10, 20, 3, 8, 18, 10, 3, 4, 11, 55, 15, 25}; + std::vector in_shape = {1, 4, 4, 1}; + lite::tensor::Tensor input_tensor; + input_tensor.SetData(input.data()); + input_tensor.set_shape(in_shape); + input_tensor.SetFormat(schema::Format_NHWC); + input_tensor.set_data_type(kNumberTypeFloat32); + std::vector inputs_tensor; + inputs_tensor.emplace_back(&input_tensor); + + const int out_size = 48; + float expect_out[48] = {0, 0, 0, 0, 0, 1, 5, 0, 0, 18, 3, 0, 0, 0, 0, 0, 0, 2, 6, 0, 0, 10, 4, 0, + 0, 0, 0, 0, 0, 10, 3, 0, 0, 11, 15, 0, 0, 0, 0, 0, 0, 20, 8, 0, 0, 55, 25, 0}; + std::vector output(48); + std::vector out_shape = {4, 3, 4, 1}; + lite::tensor::Tensor output_tensor; + output_tensor.SetData(output.data()); + output_tensor.set_shape(out_shape); + output_tensor.SetFormat(schema::Format_NHWC); + output_tensor.set_data_type(kNumberTypeFloat32); + std::vector outputs_tensor; + outputs_tensor.emplace_back(&output_tensor); + + lite::Context ctx; + kernel::KernelKey desc = {kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, schema::PrimitiveType_SpaceToBatch}; + auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); + ASSERT_NE(creator, nullptr); + kernel::LiteKernel *kernel = + creator(inputs_tensor, outputs_tensor, reinterpret_cast(¶m), &ctx, desc); + ASSERT_NE(kernel, nullptr); + kernel->Run(); + + for (int i = 0; i < out_size; ++i) { + std::cout << output[i] << " "; + } + std::cout << "\n"; + CompareOutputData(output.data(), expect_out, out_size, 0.000001); +} + +} // namespace mindspore diff --git a/mindspore/lite/test/ut/src/runtime/kernel/arm/fp32/space_to_depth_fp32_tests.cc b/mindspore/lite/test/ut/src/runtime/kernel/arm/fp32/space_to_depth_fp32_tests.cc new file mode 100644 index 00000000000..e9822c59815 --- /dev/null +++ b/mindspore/lite/test/ut/src/runtime/kernel/arm/fp32/space_to_depth_fp32_tests.cc @@ -0,0 +1,91 @@ +/** + * Copyright 2020 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 +#include +#include +#include "utils/log_adapter.h" +#include "common/common_test.h" +#include "mindspore/lite/src/runtime/kernel/arm/opclib/fp32/space_to_depth.h" +#include "mindspore/lite/src/kernel_registry.h" +#include "mindspore/lite/src/lite_kernel.h" + +namespace mindspore { + +class SpaceToDepthTestFp32 : public mindspore::Common { + public: + SpaceToDepthTestFp32() {} +}; + +TEST_F(SpaceToDepthTestFp32, SpaceToDepthTest1) { + float input[16] = {1, 2, 5, 6, 10, 20, 3, 8, 18, 10, 3, 4, 11, 55, 15, 25}; + const int out_size = 16; + float expect_out[16] = {1, 2, 10, 20, 5, 6, 3, 8, 18, 10, 11, 55, 3, 4, 15, 25}; + + float output[16]; + int in_shape[4] = {1, 4, 4, 1}; + int out_shape[4] = {1, 2, 2, 4}; + SpaceToDepthForNHWC((const float *)input, output, in_shape, out_shape, 4, 2); + for (int i = 0; i < out_size; ++i) { + std::cout << output[i] << " "; + } + std::cout << "\n"; + CompareOutputData(output, expect_out, out_size, 0.000001); +} + +TEST_F(SpaceToDepthTestFp32, SpaceToDepthTest2) { + std::vector input = {1, 2, 5, 6, 10, 20, 3, 8, 18, 10, 3, 4, 11, 55, 15, 25}; + std::vector in_shape = {1, 4, 4, 1}; + lite::tensor::Tensor input_tensor; + input_tensor.SetData(input.data()); + input_tensor.set_shape(in_shape); + input_tensor.SetFormat(schema::Format_NHWC); + input_tensor.set_data_type(kNumberTypeFloat32); + std::vector inputs_tensor; + inputs_tensor.emplace_back(&input_tensor); + + const int out_size = 16; + float expect_out[16] = {1, 2, 10, 20, 5, 6, 3, 8, 18, 10, 11, 55, 3, 4, 15, 25}; + std::vector output(16); + std::vector out_shape = {1, 2, 2, 4}; + lite::tensor::Tensor output_tensor; + output_tensor.SetData(output.data()); + output_tensor.set_shape(out_shape); + output_tensor.SetFormat(schema::Format_NHWC); + output_tensor.set_data_type(kNumberTypeFloat32); + std::vector outputs_tensor; + outputs_tensor.emplace_back(&output_tensor); + + SpaceToDepthParameter op_param; + op_param.op_parameter_.type_ = schema::PrimitiveType_SpaceToBatch; + op_param.block_size_ = 2; + + lite::Context ctx; + kernel::KernelKey desc = {kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, schema::PrimitiveType_SpaceToDepth}; + auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); + ASSERT_NE(creator, nullptr); + kernel::LiteKernel *kernel = + creator(inputs_tensor, outputs_tensor, reinterpret_cast(&op_param), &ctx, desc); + ASSERT_NE(kernel, nullptr); + kernel->Run(); + + for (int i = 0; i < out_size; ++i) { + std::cout << output[i] << " "; + } + std::cout << "\n"; + CompareOutputData(output.data(), expect_out, out_size, 0.000001); +} + +} // namespace mindspore diff --git a/mindspore/lite/test/ut/src/runtime/kernel/arm/int8/dequantize_int8_tests.cc b/mindspore/lite/test/ut/src/runtime/kernel/arm/int8/dequantize_int8_tests.cc new file mode 100644 index 00000000000..480ae296987 --- /dev/null +++ b/mindspore/lite/test/ut/src/runtime/kernel/arm/int8/dequantize_int8_tests.cc @@ -0,0 +1,83 @@ +/** + * Copyright 2020 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 +#include +#include "utils/log_adapter.h" +#include "common/common_test.h" +#include "mindspore/lite/src/runtime/kernel/arm/int8/dequantize.h" +#include "mindspore/lite/src/runtime/kernel/arm/opclib/int8/dequantize.h" +#include "mindspore/lite/src/kernel_registry.h" +#include "mindspore/lite/src/lite_kernel.h" + +namespace mindspore { + +class DequantizeTestFp32 : public mindspore::Common { + public: + DequantizeTestFp32() {} +}; + +TEST_F(DequantizeTestFp32, DequantizeTest1) { + const lite::tensor::QuantArg quant_arg{0.21176, 5}; + // quant_arg.scale = 100.0; + // quant_arg.zeroPoint = 20; + DequantizeParameter param; + param.op_parameter_.type_ = schema::PrimitiveType_OnnxInt8Dequantize; + + std::vector input = {10, 14, 29, 33, 52, 99, 19, 43, 90, 52, 19, 24, 57, 127, 76, 123}; + // int8_t input0[] = {1, 2, 10}; + // int32_t a = input0[0] + 2; + std::vector in_shape = {1, 4, 4, 1}; + lite::tensor::Tensor input_tensor; + input_tensor.SetData(input.data()); + input_tensor.set_shape(in_shape); + input_tensor.set_data_type(kNumberTypeInt8); + input_tensor.SetFormat(schema::Format_NHWC); + + input_tensor.AddQuantParam(quant_arg); + std::vector inputs_tensor; + inputs_tensor.emplace_back(&input_tensor); + + const int out_size = 16; + float expect_out[16] = {3.1764, 4.02344, 7.19984, 8.04688, 12.07032, 22.02304, 5.08224, 10.16448, + 20.1172, 12.07032, 5.082240, 6.14104, 13.12912, 27.95232, 17.15256, 27.10528}; + std::vector output(16); + std::vector out_shape = {1, 4, 4, 1}; + lite::tensor::Tensor output_tensor; + output_tensor.SetData(output.data()); + output_tensor.set_shape(out_shape); + output_tensor.set_data_type(kNumberTypeFloat32); + output_tensor.SetFormat(schema::Format_NHWC); + std::vector outputs_tensor; + outputs_tensor.emplace_back(&output_tensor); + + lite::Context ctx; + ctx.threadNum = 3; + kernel::KernelKey desc = {kernel::KERNEL_ARCH::kCPU, kNumberTypeInt8, schema::PrimitiveType_OnnxInt8Dequantize}; + auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); + ASSERT_NE(creator, nullptr); + kernel::LiteKernel *kernel = + creator(inputs_tensor, outputs_tensor, reinterpret_cast(¶m), &ctx, desc); + ASSERT_NE(kernel, nullptr); + kernel->Run(); + + for (int i = 0; i < out_size; ++i) { + std::cout << output[i] << " "; + } + std::cout << "\n"; + CompareOutputData(output.data(), expect_out, out_size, 0.000001); +} + +} // namespace mindspore