| @@ -0,0 +1,60 @@ | |||
| /** | |||
| * 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 "nnacl/base/tile_base.h" | |||
| #include <string.h> | |||
| void DoCopyData(const uint8_t *input_data, uint8_t *output_data, size_t size, size_t data_size, size_t multiple) { | |||
| uint8_t *out_data = output_data; | |||
| for (size_t i = 0; i < multiple; ++i) { | |||
| (void)memcpy(out_data, input_data, size * sizeof(uint8_t) * data_size); | |||
| out_data += size * data_size; | |||
| } | |||
| } | |||
| int DoTileOneDimension(uint8_t *input_data, uint8_t *output_data, size_t dim, TileParameter *parameter) { | |||
| size_t src_dim_size = parameter->in_shape_[dim]; | |||
| if (dim == parameter->in_dim_ - 1) { | |||
| DoCopyData(input_data, output_data, src_dim_size, parameter->data_size_, parameter->multiples_[dim]); | |||
| return 0; | |||
| } | |||
| for (size_t i = 0; i < src_dim_size; ++i) { | |||
| for (size_t j = 0; j < parameter->multiples_[dim]; ++j) { | |||
| size_t in_pos = parameter->in_strides_[dim] * i; | |||
| size_t out_pos = parameter->out_strides_[dim] * (i + j * src_dim_size); | |||
| DoTileOneDimension(input_data + in_pos * parameter->data_size_, output_data + out_pos * parameter->data_size_, | |||
| dim + 1, parameter); | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| void Tile(void *input_data, void *output_data, TileParameter *parameter) { | |||
| DoTileOneDimension((uint8_t *)input_data, (uint8_t *)output_data, 0, parameter); | |||
| } | |||
| void TileSimple(void *input_data, void *output_data, size_t begin, size_t end, TileParameter *parameter) { | |||
| uint8_t *out_data = output_data; | |||
| uint8_t *in_data = input_data; | |||
| for (size_t i = begin; i < end; ++i) { | |||
| uint8_t *src = in_data + i * parameter->fast_stride_ * parameter->data_size_; | |||
| uint8_t *dst = out_data + i * parameter->fast_stride_ * parameter->fast_multiple_ * parameter->data_size_; | |||
| for (size_t m = 0; m < parameter->fast_multiple_; ++m) { | |||
| (void)memcpy(dst, src, parameter->fast_stride_ * parameter->data_size_); | |||
| dst += parameter->fast_stride_ * parameter->data_size_; | |||
| } | |||
| } | |||
| } | |||
| @@ -14,8 +14,8 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_NNACL_TILE_H_ | |||
| #define MINDSPORE_LITE_NNACL_TILE_H_ | |||
| #ifndef MINDSPORE_LITE_NNACL_BASE_TILE_H_ | |||
| #define MINDSPORE_LITE_NNACL_BASE_TILE_H_ | |||
| #include "nnacl/op_base.h" | |||
| @@ -33,14 +33,19 @@ typedef struct TileParameter { | |||
| // other parameter | |||
| int in_dim_; | |||
| size_t data_size_; | |||
| size_t fast_outer_size_; | |||
| size_t fast_stride_; | |||
| size_t fast_multiple_; | |||
| } TileParameter; | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| void Tile(float *input_data, float *output_data, TileParameter *parameter); | |||
| void Tile(void *input_data, void *output_data, TileParameter *parameter); | |||
| void TileSimple(void *input_data, void *output_data, size_t begin, size_t end, TileParameter *parameter); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif // MINDSPORE_LITE_NNACL_TILE_H_ | |||
| #endif // MINDSPORE_LITE_NNACL_BASE_TILE_H_ | |||
| @@ -1,46 +0,0 @@ | |||
| /** | |||
| * 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 "nnacl/fp32/tile_fp32.h" | |||
| #include <string.h> | |||
| void DoCopyData(const float *input_data, float *output_data, size_t size, size_t multiple) { | |||
| float *out_data = output_data; | |||
| for (size_t i = 0; i < multiple; ++i) { | |||
| (void)memcpy(out_data, input_data, size * sizeof(float)); | |||
| out_data += size; | |||
| } | |||
| } | |||
| int DoTileOneDimension(float *input_data, float *output_data, size_t dim, TileParameter *parameter) { | |||
| size_t src_dim_size = parameter->in_shape_[dim]; | |||
| if (dim == parameter->in_dim_ - 1) { | |||
| DoCopyData(input_data, output_data, src_dim_size, parameter->multiples_[dim]); | |||
| return 0; | |||
| } | |||
| for (size_t i = 0; i < src_dim_size; ++i) { | |||
| for (size_t j = 0; j < parameter->multiples_[dim]; ++j) { | |||
| size_t in_pos = parameter->in_strides_[dim] * i; | |||
| size_t out_pos = parameter->out_strides_[dim] * (i + j * src_dim_size); | |||
| DoTileOneDimension(input_data + in_pos, output_data + out_pos, dim + 1, parameter); | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| void Tile(float *input_data, float *output_data, TileParameter *parameter) { | |||
| DoTileOneDimension(input_data, output_data, 0, parameter); | |||
| } | |||
| @@ -17,7 +17,7 @@ | |||
| #include "src/ops/tile.h" | |||
| #include "src/ops/primitive_c.h" | |||
| #include "src/ops/populate/populate_register.h" | |||
| #include "nnacl/fp32/tile_fp32.h" | |||
| #include "nnacl/base/tile_base.h" | |||
| namespace mindspore { | |||
| namespace lite { | |||
| @@ -133,7 +133,7 @@ int Squeeze::InferShape(std::vector<Tensor *> inputs_, std::vector<Tensor *> out | |||
| } | |||
| } | |||
| outputs_.front()->set_shape(out_shape); | |||
| return 0; | |||
| return RET_OK; | |||
| } | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,153 @@ | |||
| /** | |||
| * 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/base/tile_base.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| using mindspore::lite::KernelRegistrar; | |||
| using mindspore::lite::RET_ERROR; | |||
| using mindspore::lite::RET_OK; | |||
| using mindspore::schema::PrimitiveType_Tile; | |||
| namespace mindspore::kernel { | |||
| namespace { | |||
| constexpr size_t kDoubleInputsSize = 2; | |||
| } | |||
| int TileCPUKernel::Init() { | |||
| if (!InferShapeDone()) { | |||
| return RET_OK; | |||
| } | |||
| return ReSize(); | |||
| } | |||
| void TileCPUKernel::ComputeStrides(const int *shape, int *strides, int ndim) { | |||
| int stride = 1; | |||
| for (int i = ndim - 1; i >= 0; i--) { | |||
| strides[i] = stride; | |||
| stride *= shape[i]; | |||
| } | |||
| } | |||
| int TileCPUKernel::ReSize() { | |||
| auto tile_parameter_ = reinterpret_cast<TileParameter *>(op_parameter_); | |||
| MS_ASSERT(tile_parameter_); | |||
| if (in_tensors_.size() == kDoubleInputsSize) { | |||
| if (in_tensors_[1]->ElementsNum() > static_cast<int>(in_tensors_[0]->shape().size())) { | |||
| MS_LOG(ERROR) << "tile's input1 data_num cannot be larger than input0's shape_size."; | |||
| return false; | |||
| } | |||
| auto input1_addr = reinterpret_cast<int *>(in_tensors_[1]->data_c()); | |||
| for (int i = 0; i < in_tensors_[1]->ElementsNum(); ++i) { | |||
| tile_parameter_->dims_[i] = i; | |||
| tile_parameter_->multiples_[i] = input1_addr[i]; | |||
| } | |||
| } | |||
| tile_parameter_->in_dim_ = in_tensors_.at(0)->shape().size(); | |||
| for (int i = 0; i < tile_parameter_->in_dim_; ++i) { | |||
| tile_parameter_->in_shape_[i] = in_tensors_.at(0)->shape().at(i); | |||
| tile_parameter_->out_shape_[i] = out_tensors_.at(0)->shape().at(i); | |||
| } | |||
| ComputeStrides(tile_parameter_->in_shape_, tile_parameter_->in_strides_, tile_parameter_->in_dim_); | |||
| ComputeStrides(tile_parameter_->out_shape_, tile_parameter_->out_strides_, tile_parameter_->in_dim_); | |||
| auto data_type = in_tensors_.at(0)->data_type(); | |||
| if (data_type == kNumberTypeFloat32 || data_type == kNumberTypeInt32) { | |||
| tile_parameter_->data_size_ = sizeof(float); | |||
| } else if (data_type == kNumberTypeFloat16) { | |||
| tile_parameter_->data_size_ = sizeof(float) / 2; | |||
| } else { | |||
| MS_LOG(ERROR) << "tile not support data type: " << data_type; | |||
| return RET_ERROR; | |||
| } | |||
| FillOneDimTileParam(); | |||
| return RET_OK; | |||
| } | |||
| int SimpleTile(void *cdata, int task_id) { | |||
| auto kernel = reinterpret_cast<TileCPUKernel *>(cdata); | |||
| auto ret = kernel->SimpleTileImpl(task_id); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "SimpleTile error task_id[" << task_id << "] error_code[" << ret << "]"; | |||
| return ret; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| void TileCPUKernel::FillOneDimTileParam() { | |||
| // check if tile exact one dim | |||
| auto tile_parameter_ = reinterpret_cast<TileParameter *>(op_parameter_); | |||
| MS_ASSERT(tile_parameter_); | |||
| int large_one_multiple_count = 0; | |||
| int multiple; | |||
| int mul_index; | |||
| for (auto i = 0; i < tile_parameter_->in_dim_; ++i) { | |||
| if (tile_parameter_->multiples_[i] > 1) { | |||
| large_one_multiple_count++; | |||
| multiple = tile_parameter_->multiples_[i]; | |||
| mul_index = i; | |||
| } | |||
| } | |||
| one_dim_tile_ = large_one_multiple_count == 1; | |||
| if (one_dim_tile_) { | |||
| tile_parameter_->fast_multiple_ = static_cast<size_t>(multiple); | |||
| tile_parameter_->fast_stride_ = | |||
| static_cast<size_t>(tile_parameter_->in_shape_[mul_index] * tile_parameter_->in_strides_[mul_index]); | |||
| tile_parameter_->fast_outer_size_ = | |||
| static_cast<size_t>(in_tensors_.at(0)->ElementsNum()) / tile_parameter_->fast_stride_; | |||
| } | |||
| return; | |||
| } | |||
| int TileCPUKernel::SimpleTileImpl(int task_id) { | |||
| auto param = reinterpret_cast<TileParameter *>(op_parameter_); | |||
| MS_ASSERT(param); | |||
| size_t unit = UP_DIV(param->fast_outer_size_, static_cast<size_t>(context_->thread_num_)); | |||
| if (unit == 0 && task_id > 0) { | |||
| return RET_OK; | |||
| } | |||
| size_t begin = unit * static_cast<size_t>(task_id); | |||
| size_t end = MSMIN(begin + unit, param->fast_outer_size_); | |||
| TileSimple(input_addr_, output_addr_, begin, end, param); | |||
| return RET_OK; | |||
| } | |||
| int TileCPUKernel::RunSimpleTile() { | |||
| auto ret = ParallelLaunch(context_->thread_pool_, SimpleTile, this, context_->thread_num_); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "RunSimpleTile error code[" << ret << "]"; | |||
| return ret; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int TileCPUKernel::Run() { | |||
| input_addr_ = reinterpret_cast<uint8_t *>(in_tensors_.at(0)->data_c()); | |||
| output_addr_ = reinterpret_cast<uint8_t *>(out_tensors_.at(0)->data_c()); | |||
| MS_ASSERT(input_addr_ != nullptr); | |||
| MS_ASSERT(output_addr_ != nullptr); | |||
| if (one_dim_tile_) { | |||
| return RunSimpleTile(); | |||
| } | |||
| Tile(input_addr_, output_addr_, reinterpret_cast<TileParameter *>(op_parameter_)); | |||
| return RET_OK; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_Tile, LiteKernelCreator<TileCPUKernel>) | |||
| REG_KERNEL(kCPU, kNumberTypeInt32, PrimitiveType_Tile, LiteKernelCreator<TileCPUKernel>) | |||
| REG_KERNEL(kCPU, kNumberTypeFloat16, PrimitiveType_Tile, LiteKernelCreator<TileCPUKernel>) | |||
| } // namespace mindspore::kernel | |||
| @@ -13,12 +13,12 @@ | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_TILE_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_TILE_H_ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_BASE_TILE_BASE_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_BASE_TILE_BASE_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/fp32/tile_fp32.h" | |||
| #include "nnacl/base/tile_base.h" | |||
| namespace mindspore::kernel { | |||
| class TileCPUKernel : public LiteKernel { | |||
| @@ -32,10 +32,16 @@ class TileCPUKernel : public LiteKernel { | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int SimpleTileImpl(int task_id); | |||
| private: | |||
| int RunSimpleTile(); | |||
| void ComputeStrides(const int *shape, int *strides, int ndim); | |||
| void FillOneDimTileParam(); | |||
| bool one_dim_tile_; | |||
| uint8_t *input_addr_; | |||
| uint8_t *output_addr_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_TILE_H_ | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_BASE_TILE_BASE_H_ | |||
| @@ -38,7 +38,21 @@ int TransposeFp16CPUKernel::Init() { | |||
| } | |||
| int TransposeFp16CPUKernel::Run() { | |||
| MS_ASSERT(in_tensors_.size() == 1); | |||
| MS_ASSERT(in_tensors_.size() == 1 || in_tensors_.size() == 2); | |||
| TransposeParameter *param = reinterpret_cast<TransposeParameter *>(this->op_parameter_); | |||
| if (in_tensors_.size() == 2) { | |||
| auto input_perm = in_tensors_.at(1); | |||
| MS_ASSERT(input_perm != nullptr); | |||
| MS_ASSERT(input_perm->data_c() != nullptr); | |||
| int *perm_data = reinterpret_cast<int *>(input_perm->data_c()); | |||
| for (int i = 0; i < input_perm->ElementsNum(); ++i) { | |||
| param->perm_[i] = perm_data[i]; | |||
| } | |||
| for (int i = input_perm->ElementsNum(); i < 8; ++i) { | |||
| param->perm_[i] = 0; | |||
| } | |||
| param->num_axes_ = input_perm->ElementsNum(); | |||
| } | |||
| MS_ASSERT(out_tensors_.size() == 1); | |||
| auto &in_tensor = in_tensors_.front(); | |||
| auto &out_tensor = out_tensors_.front(); | |||
| @@ -51,7 +65,6 @@ int TransposeFp16CPUKernel::Run() { | |||
| MS_ASSERT(in_data_fp16_); | |||
| MS_ASSERT(out_data_fp16_); | |||
| TransposeParameter *param = reinterpret_cast<TransposeParameter *>(this->op_parameter_); | |||
| if (in_tensor->shape().size() != static_cast<size_t>(param->num_axes_)) { | |||
| memcpy(out_data_fp16_, in_data_fp16_, in_tensor->ElementsNum() * sizeof(float16_t)); | |||
| return RET_OK; | |||
| @@ -68,6 +68,7 @@ int RangeCPUKernel::Run() { | |||
| return RET_OK; | |||
| } | |||
| // fp16 may not be necessary because it involves small amount of data (input 3 number, output depends on input) | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_Range, LiteKernelCreator<RangeCPUKernel>) | |||
| REG_KERNEL(kCPU, kNumberTypeFloat, PrimitiveType_Range, LiteKernelCreator<RangeCPUKernel>) | |||
| REG_KERNEL(kCPU, kNumberTypeInt32, PrimitiveType_Range, LiteKernelCreator<RangeCPUKernel>) | |||
| @@ -1,80 +0,0 @@ | |||
| /** | |||
| * 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/tile_fp32.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| using mindspore::lite::KernelRegistrar; | |||
| using mindspore::lite::RET_ERROR; | |||
| using mindspore::lite::RET_OK; | |||
| using mindspore::schema::PrimitiveType_Tile; | |||
| namespace mindspore::kernel { | |||
| namespace { | |||
| constexpr size_t kDoubleInputsSize = 2; | |||
| } | |||
| int TileCPUKernel::Init() { | |||
| if (!InferShapeDone()) { | |||
| return RET_OK; | |||
| } | |||
| return ReSize(); | |||
| } | |||
| void TileCPUKernel::ComputeStrides(const int *shape, int *strides, int ndim) { | |||
| int stride = 1; | |||
| for (int i = ndim - 1; i >= 0; i--) { | |||
| strides[i] = stride; | |||
| stride *= shape[i]; | |||
| } | |||
| } | |||
| int TileCPUKernel::ReSize() { | |||
| auto tile_parameter_ = reinterpret_cast<TileParameter *>(op_parameter_); | |||
| MS_ASSERT(tile_parameter_); | |||
| if (in_tensors_.size() == kDoubleInputsSize) { | |||
| if (in_tensors_[1]->ElementsNum() > static_cast<int>(in_tensors_[0]->shape().size())) { | |||
| MS_LOG(ERROR) << "tile's input1 data_num cannot be larger than input0's shape_size."; | |||
| return false; | |||
| } | |||
| auto input1_addr = reinterpret_cast<int *>(in_tensors_[1]->data_c()); | |||
| for (int i = 0; i < in_tensors_[1]->ElementsNum(); ++i) { | |||
| tile_parameter_->dims_[i] = i; | |||
| tile_parameter_->multiples_[i] = input1_addr[i]; | |||
| } | |||
| } | |||
| tile_parameter_->in_dim_ = in_tensors_.at(0)->shape().size(); | |||
| for (int i = 0; i < tile_parameter_->in_dim_; ++i) { | |||
| tile_parameter_->in_shape_[i] = in_tensors_.at(0)->shape().at(i); | |||
| tile_parameter_->out_shape_[i] = out_tensors_.at(0)->shape().at(i); | |||
| } | |||
| ComputeStrides(tile_parameter_->in_shape_, tile_parameter_->in_strides_, tile_parameter_->in_dim_); | |||
| ComputeStrides(tile_parameter_->out_shape_, tile_parameter_->out_strides_, tile_parameter_->in_dim_); | |||
| return RET_OK; | |||
| } | |||
| int TileCPUKernel::Run() { | |||
| auto input_addr = reinterpret_cast<float *>(in_tensors_.at(0)->data_c()); | |||
| auto output_addr = reinterpret_cast<float *>(out_tensors_.at(0)->data_c()); | |||
| MS_ASSERT(input_addr); | |||
| MS_ASSERT(output_addr); | |||
| Tile(input_addr, output_addr, reinterpret_cast<TileParameter *>(op_parameter_)); | |||
| return RET_OK; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_Tile, LiteKernelCreator<TileCPUKernel>) | |||
| REG_KERNEL(kCPU, kNumberTypeInt32, PrimitiveType_Tile, LiteKernelCreator<TileCPUKernel>) | |||
| } // namespace mindspore::kernel | |||
| @@ -14,10 +14,9 @@ | |||
| * limitations under the License. | |||
| */ | |||
| #include <iostream> | |||
| #include <memory> | |||
| #include "common/common_test.h" | |||
| #include "mindspore/lite/nnacl/fp32/tile_fp32.h" | |||
| #include "mindspore/lite/nnacl/base/tile_base.h" | |||
| #include "mindspore/lite/src/kernel_registry.h" | |||
| namespace mindspore { | |||
| @@ -68,4 +67,94 @@ TEST_F(TestTileFp32, Tile) { | |||
| in_tensor.set_data(nullptr); | |||
| out_tensor.set_data(nullptr); | |||
| } | |||
| TEST_F(TestTileFp32, SimpleTile1) { | |||
| lite::Tensor in_tensor(kNumberTypeFloat32, {2, 2}); | |||
| lite::Tensor out_tensor(kNumberTypeFloat32, {4, 2}); | |||
| float input_data[] = {1, 2, 3, 4}; | |||
| float output_data[8] = {0}; | |||
| in_tensor.set_data(input_data); | |||
| out_tensor.set_data(output_data); | |||
| std::vector<lite::Tensor *> inputs = {&in_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&out_tensor}; | |||
| TileParameter parameter = {0}; | |||
| parameter.in_dim_ = 2; | |||
| parameter.in_shape_[0] = 2; | |||
| parameter.in_shape_[1] = 2; | |||
| parameter.multiples_[0] = 2; | |||
| parameter.multiples_[1] = 1; | |||
| parameter.in_strides_[0] = 2; | |||
| parameter.in_strides_[1] = 1; | |||
| parameter.out_strides_[0] = 2; | |||
| parameter.out_strides_[1] = 1; | |||
| kernel::KernelKey desc = {kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, schema::PrimitiveType_Tile}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| EXPECT_NE(creator, nullptr); | |||
| auto ctx = std::make_shared<lite::InnerContext>(); | |||
| ASSERT_EQ(lite::RET_OK, ctx->Init()); | |||
| auto context = ctx.get(); | |||
| context->thread_num_ = 2; | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(¶meter), context, desc, nullptr); | |||
| EXPECT_NE(kernel, nullptr); | |||
| auto ret = kernel->Run(); | |||
| EXPECT_EQ(0, ret); | |||
| float expect[] = {1, 2, 3, 4, 1, 2, 3, 4}; | |||
| for (int i = 0; i < 8; ++i) { | |||
| EXPECT_EQ(output_data[i], expect[i]); | |||
| } | |||
| in_tensor.set_data(nullptr); | |||
| out_tensor.set_data(nullptr); | |||
| } | |||
| TEST_F(TestTileFp32, SimpleTile2) { | |||
| lite::Tensor in_tensor(kNumberTypeFloat32, {2, 2}); | |||
| lite::Tensor out_tensor(kNumberTypeFloat32, {2, 4}); | |||
| float input_data[] = {1, 2, 3, 4}; | |||
| float output_data[8] = {0}; | |||
| in_tensor.set_data(input_data); | |||
| out_tensor.set_data(output_data); | |||
| std::vector<lite::Tensor *> inputs = {&in_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&out_tensor}; | |||
| TileParameter parameter = {0}; | |||
| parameter.in_dim_ = 2; | |||
| parameter.in_shape_[0] = 2; | |||
| parameter.in_shape_[1] = 2; | |||
| parameter.multiples_[0] = 1; | |||
| parameter.multiples_[1] = 2; | |||
| parameter.in_strides_[0] = 2; | |||
| parameter.in_strides_[1] = 1; | |||
| parameter.out_strides_[0] = 4; | |||
| parameter.out_strides_[1] = 1; | |||
| kernel::KernelKey desc = {kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, schema::PrimitiveType_Tile}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| EXPECT_NE(creator, nullptr); | |||
| auto ctx = std::make_shared<lite::InnerContext>(); | |||
| ASSERT_EQ(lite::RET_OK, ctx->Init()); | |||
| auto context = ctx.get(); | |||
| context->thread_num_ = 2; | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(¶meter), context, desc, nullptr); | |||
| EXPECT_NE(kernel, nullptr); | |||
| auto ret = kernel->Run(); | |||
| EXPECT_EQ(0, ret); | |||
| float expect[] = {1, 2, 1, 2, 3, 4, 3, 4}; | |||
| for (int i = 0; i < 8; ++i) { | |||
| EXPECT_EQ(output_data[i], expect[i]); | |||
| } | |||
| in_tensor.set_data(nullptr); | |||
| out_tensor.set_data(nullptr); | |||
| } | |||
| } // namespace mindspore | |||