Merge pull request !4040 from sunsuodong/strided_slice_int8tags/v0.7.0-beta
| @@ -86,7 +86,7 @@ void StridedSlice::ApplyBeginMask() { | |||
| void StridedSlice::ApplyEndMask() { | |||
| for (int i = 0; i < ndim_; i++) { | |||
| if (ends_.at(i)) { | |||
| if (ends_mask_.at(i)) { | |||
| ends_.at(i) = in_shape_.at(i); | |||
| } | |||
| } | |||
| @@ -62,7 +62,7 @@ | |||
| #include "src/runtime/kernel/arm/fp32/flatten.h" | |||
| #include "src/runtime/kernel/arm/opclib/fp32/unsqueeze.h" | |||
| #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/opclib/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" | |||
| @@ -14,9 +14,9 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "src/runtime/kernel/arm/fp32/strided_slice.h" | |||
| #include "src/runtime/kernel/arm/base/strided_slice.h" | |||
| #include <vector> | |||
| #include "src/runtime/kernel/arm/opclib/fp32/strided_slice.h" | |||
| #include "src/runtime/kernel/arm/opclib/strided_slice.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| @@ -30,26 +30,24 @@ using mindspore::schema::PrimitiveType_StridedSlice; | |||
| namespace mindspore::kernel { | |||
| int StridedSliceCPUKernel::Init() { return RET_OK; } | |||
| int StridedSliceCPUKernel::ReSize() { return 0; } | |||
| int StridedSliceCPUKernel::StridedSlice() { | |||
| StridedSliceParameter *param = reinterpret_cast<StridedSliceParameter *>(opParameter); | |||
| auto ret = DoStridedSlice(input_ptr_, output_ptr_, param); | |||
| if (ret != RET_OK) { | |||
| return RET_ERROR; | |||
| } | |||
| int StridedSliceCPUKernel::Init() { | |||
| auto input = inputs_.at(0); | |||
| auto parameter = reinterpret_cast<StridedSliceParameter *>(opParameter); | |||
| MS_ASSERT(input); | |||
| MS_ASSERT(parameter); | |||
| parameter->data_type = input->data_type() == kNumberTypeInt8 ? kDataTypeInt8 : kDataTypeFloat; | |||
| return RET_OK; | |||
| } | |||
| int StridedSliceCPUKernel::ReSize() { return 0; } | |||
| int StridedSliceCPUKernel::Run() { | |||
| auto input_tensor = inputs_.at(0); | |||
| auto output_tensor = outputs_.at(0); | |||
| input_ptr_ = reinterpret_cast<float *>(input_tensor->Data()); | |||
| output_ptr_ = reinterpret_cast<float *>(output_tensor->Data()); | |||
| auto input = inputs_.at(0); | |||
| auto output = outputs_.at(0); | |||
| MS_ASSERT(input); | |||
| MS_ASSERT(output); | |||
| auto ret = StridedSlice(); | |||
| auto ret = DoStridedSlice(input->Data(), output->Data(), reinterpret_cast<StridedSliceParameter *>(opParameter)); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "StridedSlice error error_code[" << ret << "]"; | |||
| return RET_ERROR; | |||
| @@ -57,10 +55,10 @@ int StridedSliceCPUKernel::Run() { | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuStridedSliceFp32KernelCreator(const std::vector<lite::tensor::Tensor *> &inputs, | |||
| const std::vector<lite::tensor::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::Context *ctx, | |||
| const kernel::KernelKey &desc) { | |||
| kernel::LiteKernel *CpuStridedSliceKernelCreator(const std::vector<lite::tensor::Tensor *> &inputs, | |||
| const std::vector<lite::tensor::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::Context *ctx, | |||
| const kernel::KernelKey &desc) { | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_StridedSlice); | |||
| if (opParameter == nullptr) { | |||
| MS_LOG(ERROR) << "opParameter null pointer dereferencing."; | |||
| @@ -82,5 +80,6 @@ kernel::LiteKernel *CpuStridedSliceFp32KernelCreator(const std::vector<lite::ten | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_StridedSlice, CpuStridedSliceFp32KernelCreator) | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_StridedSlice, CpuStridedSliceKernelCreator) | |||
| REG_KERNEL(kCPU, kNumberTypeInt8, PrimitiveType_StridedSlice, CpuStridedSliceKernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -14,8 +14,8 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_BACKEND_ARM_FP32_STRIDED_SLICE_H_ | |||
| #define MINDSPORE_LITE_SRC_BACKEND_ARM_FP32_STRIDED_SLICE_H_ | |||
| #ifndef MINDSPORE_LITE_SRC_BACKEND_ARM_BASE_STRIDED_SLICE_H_ | |||
| #define MINDSPORE_LITE_SRC_BACKEND_ARM_BASE_STRIDED_SLICE_H_ | |||
| #include <vector> | |||
| #include "ir/anf.h" | |||
| @@ -32,13 +32,10 @@ class StridedSliceCPUKernel : public LiteKernel { | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int StridedSlice(); | |||
| private: | |||
| int thread_num_; | |||
| float *input_ptr_; | |||
| float *output_ptr_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_BACKEND_ARM_FP32_STRIDED_SLICE_H_ | |||
| #endif // MINDSPORE_LITE_SRC_BACKEND_ARM_BASE_STRIDED_SLICE_H_ | |||
| @@ -48,6 +48,11 @@ | |||
| #define kInputSize1 2 | |||
| #define kInputSize2 3 | |||
| enum LiteDataType { | |||
| kDataTypeFloat, | |||
| kDataTypeInt8, | |||
| }; | |||
| struct OpParameter { | |||
| char name_[100]; | |||
| int type_; | |||
| @@ -55,4 +60,3 @@ struct OpParameter { | |||
| }; | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_OPCLIB_OP_BASE_H_ | |||
| @@ -14,7 +14,7 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include "src/runtime/kernel/arm/opclib/fp32/strided_slice.h" | |||
| #include "src/runtime/kernel/arm/opclib/strided_slice.h" | |||
| #include "src/runtime/kernel/arm/opclib/errorcode.h" | |||
| void PadStridedSliceParameterTo4D(StridedSliceParameter *param) { | |||
| @@ -45,7 +45,7 @@ void PadStridedSliceParameterTo4D(StridedSliceParameter *param) { | |||
| param->num_axes_ = DIMENSION_4D; | |||
| } | |||
| int DoStridedSlice(const float *in_data, float *out_data, StridedSliceParameter *param) { | |||
| int DoStridedSlice(const void *in_data, void *out_data, StridedSliceParameter *param) { | |||
| if (in_data == nullptr || out_data == nullptr || param == nullptr) { | |||
| return OPCLIB_NULL_PTR; | |||
| } | |||
| @@ -66,17 +66,21 @@ int DoStridedSlice(const float *in_data, float *out_data, StridedSliceParameter | |||
| dim_offset[2] = in_shape[3]; | |||
| dim_offset[1] = dim_offset[2] * in_shape[2]; | |||
| dim_offset[0] = dim_offset[1] * in_shape[1]; | |||
| size_t output_index = 0; | |||
| size_t out_offset = 0; | |||
| for (int32_t dim0 = begins[0]; dim0 < ends[0]; dim0 += strides[0]) { | |||
| for (int32_t dim1 = begins[1]; dim1 < ends[1]; dim1 += strides[1]) { | |||
| for (int32_t dim2 = begins[2]; dim2 < ends[2]; dim2 += strides[2]) { | |||
| for (int32_t dim3 = begins[3]; dim3 < ends[3]; dim3 += strides[3]) { | |||
| out_data[output_index++] = | |||
| *(in_data + dim0 * dim_offset[0] + dim1 * dim_offset[1] + dim2 * dim_offset[2] + dim3); | |||
| int32_t in_offset = dim0 * dim_offset[0] + dim1 * dim_offset[1] + dim2 * dim_offset[2] + dim3; | |||
| if (param->data_type == kDataTypeFloat) { | |||
| *((float *)out_data + out_offset) = *((float *)in_data + in_offset); | |||
| } else { | |||
| *((int8_t *)out_data + out_offset) = *((int8_t *)in_data + in_offset); | |||
| } | |||
| out_offset++; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| return OPCLIB_OK; | |||
| } | |||
| @@ -13,20 +13,21 @@ | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_BACKEND_ARM_OPCLIB_FP32_STRIDED_SLICE_H_ | |||
| #define MINDSPORE_LITE_SRC_BACKEND_ARM_OPCLIB_FP32_STRIDED_SLICE_H_ | |||
| #ifndef MINDSPORE_LITE_SRC_BACKEND_ARM_OPCLIB_STRIDED_SLICE_H_ | |||
| #define MINDSPORE_LITE_SRC_BACKEND_ARM_OPCLIB_STRIDED_SLICE_H_ | |||
| #include "src/runtime/kernel/arm/opclib/op_base.h" | |||
| struct StridedSliceParameter { | |||
| OpParameter op_parameter_; | |||
| int begins_[8] = {0}; | |||
| int ends_[8] = {0}; | |||
| int strides_[8] = {1}; | |||
| int isScale; | |||
| int num_axes_; | |||
| int in_shape_[8]; | |||
| OpParameter op_parameter_; | |||
| int begins_[8] = {0}; | |||
| int ends_[8] = {0}; | |||
| int strides_[8] = {1}; | |||
| int isScale; | |||
| int num_axes_; | |||
| int in_shape_[8]; | |||
| LiteDataType data_type; | |||
| }; | |||
| int DoStridedSlice(const float *inputs, float *output, StridedSliceParameter * param); | |||
| #endif // MINDSPORE_LITE_SRC_BACKEND_ARM_OPCLIB_FP32_STRIDED_SLICE_H_ | |||
| int DoStridedSlice(const void *inputs, void *output, StridedSliceParameter *param); | |||
| #endif // MINDSPORE_LITE_SRC_BACKEND_ARM_OPCLIB_STRIDED_SLICE_H_ | |||
| @@ -252,6 +252,7 @@ else() | |||
| endif() | |||
| ### test src | |||
| file(GLOB_RECURSE TEST_CASE_KERNEL_SRC | |||
| ${TEST_DIR}/ut/src/runtime/kernel/arm/common/*.cc | |||
| ${TEST_DIR}/ut/src/runtime/kernel/arm/fp32/*.cc | |||
| ${TEST_DIR}/ut/src/runtime/kernel/arm/int8/*.cc | |||
| ) | |||
| @@ -0,0 +1,126 @@ | |||
| /** | |||
| * 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 <memory> | |||
| #include "common/common_test.h" | |||
| #include "mindspore/lite/src/runtime/kernel/arm/opclib/strided_slice.h" | |||
| #include "mindspore/lite/src/kernel_registry.h" | |||
| namespace mindspore { | |||
| class TestStridedSlice : public mindspore::Common { | |||
| public: | |||
| TestStridedSlice() {} | |||
| }; | |||
| void InitStridedSliceParam(StridedSliceParameter *strided_slice_param) { | |||
| strided_slice_param->begins_[0] = 0; | |||
| strided_slice_param->begins_[1] = 0; | |||
| strided_slice_param->begins_[2] = 0; | |||
| strided_slice_param->ends_[0] = 1; | |||
| strided_slice_param->ends_[1] = 2; | |||
| strided_slice_param->ends_[2] = 4; | |||
| strided_slice_param->strides_[0] = 1; | |||
| strided_slice_param->strides_[1] = 2; | |||
| strided_slice_param->strides_[2] = 2; | |||
| strided_slice_param->in_shape_[0] = 1; | |||
| strided_slice_param->in_shape_[1] = 2; | |||
| strided_slice_param->in_shape_[2] = 4; | |||
| strided_slice_param->num_axes_ = 3; | |||
| } | |||
| TEST_F(TestStridedSlice, StridedSlice) { | |||
| lite::tensor::Tensor in_tensor(kNumberTypeFloat32, {1, 2, 4}); | |||
| lite::tensor::Tensor out_tensor(kNumberTypeFloat32, {1, 1, 2}); | |||
| float input_data[] = {0.2390374, 0.92039955, 0.05051243, 0.49574447, 0.8355223, 0.02647042, 0.08811307, 0.4566604}; | |||
| float output_data[2] = {0}; | |||
| in_tensor.SetData(input_data); | |||
| out_tensor.SetData(output_data); | |||
| std::vector<lite::tensor::Tensor *> inputs = {&in_tensor}; | |||
| std::vector<lite::tensor::Tensor *> outputs = {&out_tensor}; | |||
| StridedSliceParameter parameter = {0}; | |||
| InitStridedSliceParam(¶meter); | |||
| parameter.op_parameter_.type_ = schema::PrimitiveType_StridedSlice; | |||
| kernel::KernelKey desc = {kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, schema::PrimitiveType_StridedSlice}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| ASSERT_NE(creator, nullptr); | |||
| auto ctx = std::make_shared<lite::Context>(); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(¶meter), ctx.get(), desc); | |||
| ASSERT_NE(kernel, nullptr); | |||
| auto ret = kernel->Run(); | |||
| EXPECT_EQ(0, ret); | |||
| float expect[2] = {0.2390374, 0.05051243}; | |||
| CompareOutputData(output_data, expect, 2, 0.000001); | |||
| in_tensor.SetData(nullptr); | |||
| out_tensor.SetData(nullptr); | |||
| } | |||
| TEST_F(TestStridedSlice, StridedSliceInt8) { | |||
| lite::tensor::Tensor in_tensor(kNumberTypeInt8, {2, 3, 4}); | |||
| lite::tensor::Tensor out_tensor(kNumberTypeInt8, {2, 3, 4}); | |||
| int8_t input_data[] = {-12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, | |||
| 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; | |||
| int8_t output_data[4] = {0}; | |||
| in_tensor.SetData(input_data); | |||
| out_tensor.SetData(output_data); | |||
| std::vector<lite::tensor::Tensor *> inputs = {&in_tensor}; | |||
| std::vector<lite::tensor::Tensor *> outputs = {&out_tensor}; | |||
| StridedSliceParameter parameter = {0}; | |||
| parameter.begins_[0] = 0; | |||
| parameter.begins_[1] = 1; | |||
| parameter.begins_[2] = 2; | |||
| parameter.ends_[0] = 2; | |||
| parameter.ends_[1] = 3; | |||
| parameter.ends_[2] = 4; | |||
| parameter.strides_[0] = 1; | |||
| parameter.strides_[1] = 2; | |||
| parameter.strides_[2] = 1; | |||
| parameter.in_shape_[0] = 2; | |||
| parameter.in_shape_[1] = 3; | |||
| parameter.in_shape_[2] = 4; | |||
| parameter.num_axes_ = 3; | |||
| parameter.op_parameter_.type_ = schema::PrimitiveType_StridedSlice; | |||
| kernel::KernelKey desc = {kernel::KERNEL_ARCH::kCPU, kNumberTypeInt8, schema::PrimitiveType_StridedSlice}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| ASSERT_NE(creator, nullptr); | |||
| auto ctx = std::make_shared<lite::Context>(); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(¶meter), ctx.get(), desc); | |||
| ASSERT_NE(kernel, nullptr); | |||
| auto ret = kernel->Run(); | |||
| EXPECT_EQ(0, ret); | |||
| int8_t expect[4] = {-6, -5, 7, 8}; | |||
| for (int i = 0; i < sizeof(expect); ++i) { | |||
| EXPECT_EQ(output_data[i], expect[i]); | |||
| } | |||
| in_tensor.SetData(nullptr); | |||
| out_tensor.SetData(nullptr); | |||
| } | |||
| } // namespace mindspore | |||