| @@ -58,9 +58,6 @@ if (SUPPORT_TRAIN) | |||
| set(LITE_SRC | |||
| ${LITE_SRC} | |||
| ${ANF_SRC} | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/train_populate_parameter.cc | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/train_session.cc | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/train/train_model.cc | |||
| ${CMAKE_CURRENT_SOURCE_DIR}/lite_session.cc | |||
| ) | |||
| endif () | |||
| @@ -1,131 +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_grad/activation_grad.h" | |||
| #include "nnacl/fp32_grad/activation_grad.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "src/runtime/runtime_api.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::ActivationType_HSWISH; | |||
| using mindspore::schema::ActivationType_LEAKY_RELU; | |||
| using mindspore::schema::ActivationType_RELU; | |||
| using mindspore::schema::ActivationType_RELU6; | |||
| using mindspore::schema::PrimitiveType_ActivationGrad; | |||
| namespace mindspore::kernel { | |||
| int ActivationGradCPUKernel::Init() { | |||
| if (2 != in_tensors_.size()) { | |||
| MS_LOG(ERROR) << "ActivationGrad should have 2 input tensors"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ActivationGradCPUKernel::ReSize() { return RET_OK; } | |||
| int ActivationGradCPUKernel::DoActivation(int task_id) { | |||
| auto yt_addr = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||
| auto input_addr = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | |||
| auto output_addr = reinterpret_cast<float *>(out_tensors_.at(0)->MutableData()); | |||
| int length = in_tensors_.at(0)->ElementsNum(); | |||
| int stride = UP_DIV(length, 1); | |||
| int count = MSMIN(stride, length - stride * task_id); | |||
| auto error_code = RET_OK; | |||
| if (param_act_grad_->type_ == schema::ActivationType_RELU) { | |||
| error_code = | |||
| ReluGrad(yt_addr + stride * task_id, input_addr + stride * task_id, count, output_addr + stride * task_id); | |||
| } else if (param_act_grad_->type_ == schema::ActivationType_RELU6) { | |||
| error_code = | |||
| Relu6Grad(yt_addr + stride * task_id, input_addr + stride * task_id, count, output_addr + stride * task_id); | |||
| } else if (param_act_grad_->type_ == schema::ActivationType_LEAKY_RELU) { | |||
| error_code = LReluGrad(yt_addr + stride * task_id, input_addr + stride * task_id, count, | |||
| output_addr + stride * task_id, param_act_grad_->alpha_); | |||
| } else if (param_act_grad_->type_ == schema::ActivationType_SIGMOID) { | |||
| // Sigmoid gets the input tensors in reverse order! | |||
| error_code = | |||
| SigmoidGrad(input_addr + stride * task_id, yt_addr + stride * task_id, count, output_addr + stride * task_id); | |||
| } else if (param_act_grad_->type_ == schema::ActivationType_TANH) { | |||
| error_code = | |||
| TanhGrad(yt_addr + stride * task_id, input_addr + stride * task_id, count, output_addr + stride * task_id); | |||
| } else if (param_act_grad_->type_ == schema::ActivationType_HSWISH) { | |||
| error_code = | |||
| HSwishGrad(yt_addr + stride * task_id, input_addr + stride * task_id, count, output_addr + stride * task_id); | |||
| } else if (param_act_grad_->type_ == schema::ActivationType_HSIGMOID) { | |||
| error_code = | |||
| HSigmoidGrad(yt_addr + stride * task_id, input_addr + stride * task_id, count, output_addr + stride * task_id); | |||
| } else { | |||
| MS_LOG(ERROR) << "Activation type error"; | |||
| return RET_ERROR; | |||
| } | |||
| if (error_code != RET_OK) { | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ActivationGradRun(void *cdata, int task_id) { | |||
| auto activationGrad_kernel = reinterpret_cast<ActivationGradCPUKernel *>(cdata); | |||
| auto error_code = activationGrad_kernel->DoActivation(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "ActivationGradRun error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ActivationGradCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, ActivationGradRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "Activation Grad function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuActivationGradFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_ActivationGrad); | |||
| auto *kernel = new (std::nothrow) ActivationGradCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new ActivationGradCPUKernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_ActivationGrad, CpuActivationGradFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ACTIVATION_GRAD_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ACTIVATION_GRAD_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/fp32/activation.h" | |||
| namespace mindspore::kernel { | |||
| class ActivationGradCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit ActivationGradCPUKernel(OpParameter *param, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(param, inputs, outputs, ctx, primitive) { | |||
| param_act_grad_ = reinterpret_cast<ActivationParameter *>(param); | |||
| } | |||
| ~ActivationGradCPUKernel() override = default; | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int DoActivation(int task_id); | |||
| private: | |||
| ActivationParameter *param_act_grad_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ACTIVATION_GRAD_H_ | |||
| @@ -1,112 +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_grad/adam.h" | |||
| #include <cmath> | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| #include "src/runtime/kernel/arm/fp32/nchw2nhwc_fp32.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_Adam; | |||
| namespace mindspore::kernel { | |||
| int AdamCPUKernel::ReSize() { return RET_OK; } | |||
| int AdamCPUKernel::Execute(int task_id) { | |||
| auto weight = reinterpret_cast<float *>(in_tensors_[0]->MutableData()); | |||
| auto m = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| auto v = reinterpret_cast<float *>(in_tensors_[2]->MutableData()); | |||
| auto beta1_power = reinterpret_cast<float *>(in_tensors_[3]->MutableData())[0]; | |||
| auto beta2_power = reinterpret_cast<float *>(in_tensors_[4]->MutableData())[0]; | |||
| auto learning_rate = reinterpret_cast<float *>(in_tensors_[5]->MutableData())[0]; | |||
| auto beta1 = reinterpret_cast<float *>(in_tensors_[6]->MutableData())[0]; | |||
| auto beta2 = reinterpret_cast<float *>(in_tensors_[7]->MutableData())[0]; | |||
| auto eps = reinterpret_cast<float *>(in_tensors_[8]->MutableData())[0]; | |||
| auto gradient = reinterpret_cast<float *>(in_tensors_[9]->MutableData()); | |||
| size_t elem_num = in_tensors_[0]->ElementsNum(); | |||
| if (adam_param_->use_nesterov_) { // Nadam | |||
| for (size_t i = 0; i < elem_num; ++i) { | |||
| m[i] = (m[i] * beta1) + (gradient[i] * (1.f - beta1)); | |||
| v[i] = (v[i] * beta2) + (gradient[i] * gradient[i] * (1.f - beta2)); | |||
| auto g_hat = gradient[i] / (1 - beta1_power); | |||
| auto m_hat = m[i] / (1 - beta1_power); | |||
| auto v_hat = v[i] / (1 - beta2_power); | |||
| auto m_tag = (1.f - beta1) * g_hat + beta1 * m_hat; | |||
| weight[i] -= learning_rate * m_tag / (sqrtf(v_hat) + eps); | |||
| } | |||
| } else { | |||
| for (size_t i = 0; i < elem_num; ++i) { | |||
| m[i] = (m[i] * beta1) + (gradient[i] * (1.f - beta1)); | |||
| v[i] = (v[i] * beta2) + (gradient[i] * gradient[i] * (1.f - beta2)); | |||
| auto m_hat = m[i] / (1 - beta1_power); | |||
| auto v_hat = v[i] / (1 - beta2_power); | |||
| weight[i] -= learning_rate * m_hat / (sqrtf(v_hat) + eps); | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int AdamRun(void *cdata, int task_id) { | |||
| auto Adam_kernel = reinterpret_cast<AdamCPUKernel *>(cdata); | |||
| auto error_code = Adam_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "Adam run error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int AdamCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, AdamRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "Adam function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int AdamCPUKernel::Init() { return RET_OK; } | |||
| kernel::LiteKernel *CpuAdamFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | |||
| const lite::InnerContext *ctx, const kernel::KernelKey &desc, | |||
| const lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_Adam); | |||
| auto *kernel = new (std::nothrow) AdamCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| MS_ASSERT(kernel != nullptr); | |||
| auto ret = kernel->Init(); | |||
| if (0 != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_Adam, CpuAdamFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,44 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ADAM_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ADAM_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/fp32_grad/optimizer.h" | |||
| namespace mindspore::kernel { | |||
| class AdamCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit AdamCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) { | |||
| adam_param_ = reinterpret_cast<AdamParameter *>(parameter); | |||
| } | |||
| ~AdamCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| AdamParameter *adam_param_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ADAM_H_ | |||
| @@ -1,103 +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_grad/apply_momentum.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| #include "src/runtime/kernel/arm/fp32/nchw2nhwc_fp32.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_ApplyMomentum; | |||
| namespace mindspore::kernel { | |||
| int ApplyMomentumCPUKernel::ReSize() { return RET_OK; } | |||
| int ApplyMomentumCPUKernel::Execute(int task_id) { | |||
| auto weight = reinterpret_cast<float *>(in_tensors_[0]->MutableData()); | |||
| auto accumulate = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| float learning_rate = reinterpret_cast<float *>(in_tensors_[2]->MutableData())[0]; | |||
| auto gradient = reinterpret_cast<float *>(in_tensors_[3]->MutableData()); | |||
| float moment = reinterpret_cast<float *>(in_tensors_[4]->MutableData())[0]; | |||
| size_t elem_num = in_tensors_[0]->ElementsNum(); | |||
| if (apply_momentum_param_->use_nesterov_) { | |||
| for (size_t i = 0; i < elem_num; ++i) { | |||
| accumulate[i] = accumulate[i] * moment + gradient[i]; | |||
| weight[i] -= (accumulate[i] * moment + gradient[i]) * learning_rate; | |||
| } | |||
| } else { | |||
| for (size_t i = 0; i < elem_num; ++i) { | |||
| accumulate[i] = accumulate[i] * moment + gradient[i]; | |||
| weight[i] -= accumulate[i] * learning_rate; | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ApplyMomentumRun(void *cdata, int task_id) { | |||
| auto applyMomentum_kernel = reinterpret_cast<ApplyMomentumCPUKernel *>(cdata); | |||
| auto error_code = applyMomentum_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "apply Momentum run error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ApplyMomentumCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, ApplyMomentumRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "Apply Momentum function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ApplyMomentumCPUKernel::Init() { return RET_OK; } | |||
| kernel::LiteKernel *CpuApplyMomentumFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, | |||
| const lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_ApplyMomentum); | |||
| auto *kernel = new (std::nothrow) ApplyMomentumCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new ApplyMomentumCPUKernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (0 != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_ApplyMomentum, CpuApplyMomentumFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,44 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_APPLY_MOMENTUM_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_APPLY_MOMENTUM_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/fp32_grad/optimizer.h" | |||
| namespace mindspore::kernel { | |||
| class ApplyMomentumCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit ApplyMomentumCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive), apply_momentum_param_(nullptr) { | |||
| apply_momentum_param_ = reinterpret_cast<ApplyMomentumParameter *>(parameter); | |||
| } | |||
| ~ApplyMomentumCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| ApplyMomentumParameter *apply_momentum_param_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_APPLY_MOMENTUM_H_ | |||
| @@ -1,243 +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_grad/arithmetic_grad.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "nnacl/fp32_grad/reduce_grad.h" | |||
| #include "nnacl/fp32_grad/arithmetic_grad.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| using mindspore::kernel::KERNEL_ARCH::kCPU; | |||
| using mindspore::lite::KernelRegistrar; | |||
| using mindspore::lite::RET_ERROR; | |||
| using mindspore::lite::RET_OK; | |||
| namespace mindspore::kernel { | |||
| int ArithmeticGradCPUKernel::Init() { | |||
| auto dx1 = out_tensors_[0]; | |||
| auto dx2 = out_tensors_[1]; | |||
| MS_ASSERT(dx1 != nullptr); | |||
| MS_ASSERT(dx2 != nullptr); | |||
| if ((Type() == PrimitiveType_MulGrad) || (Type() == PrimitiveType_DivGrad)) { | |||
| if (dx1->ElementsNum() < dx2->ElementsNum()) { | |||
| if (Type() == PrimitiveType_MulGrad) | |||
| arithmetic_grad_ = &ArithmeticGradCPUKernel::ArithmeticGradMul2L; | |||
| else if (Type() == PrimitiveType_DivGrad) | |||
| arithmetic_grad_ = &ArithmeticGradCPUKernel::ArithmeticGradDiv2L; | |||
| } else if (dx2->ElementsNum() < dx1->ElementsNum()) { | |||
| if (Type() == PrimitiveType_MulGrad) | |||
| arithmetic_grad_ = &ArithmeticGradCPUKernel::ArithmeticGradMul1L; | |||
| else if (Type() == PrimitiveType_DivGrad) | |||
| arithmetic_grad_ = &ArithmeticGradCPUKernel::ArithmeticGradDiv1L; | |||
| } | |||
| tile_data0 = new (std::nothrow) float[in_tensors_.at(0)->ElementsNum()]; | |||
| if (tile_data0 == nullptr) { | |||
| MS_LOG(ERROR) << "new data0 fail!"; | |||
| return RET_ERROR; | |||
| } | |||
| tile_data1 = new (std::nothrow) float[in_tensors_.at(0)->ElementsNum()]; | |||
| if (tile_data1 == nullptr) { | |||
| MS_LOG(ERROR) << "new data1 fail!"; | |||
| return RET_ERROR; | |||
| } | |||
| if (Type() == PrimitiveType_DivGrad) { | |||
| tile_data2 = new (std::nothrow) float[in_tensors_.at(0)->ElementsNum()]; | |||
| if (tile_data2 == nullptr) { | |||
| MS_LOG(ERROR) << "new data2 fail!"; | |||
| return RET_ERROR; | |||
| } | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| void ArithmeticGradCPUKernel::ArithmeticGradAdd(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, | |||
| int dx2_size) { | |||
| if (dx1_size == dy_size) | |||
| memcpy(dx1, dy, dy_size * sizeof(float)); | |||
| else | |||
| ReduceSumByAxes(dy, arithmeticParameter_->out_shape_, dx1, arithmeticParameter_->in_shape0_, | |||
| arithmeticParameter_->ndim_); | |||
| if (dx2_size == dy_size) | |||
| memcpy(dx2, dy, dy_size * sizeof(float)); | |||
| else | |||
| ReduceSumByAxes(dy, arithmeticParameter_->out_shape_, dx2, arithmeticParameter_->in_shape1_, | |||
| arithmeticParameter_->ndim_); | |||
| } | |||
| void ArithmeticGradCPUKernel::ArithmeticGradSub(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, | |||
| int dx2_size) { | |||
| if (dx1_size == dy_size) | |||
| memcpy(dx1, dy, dy_size * sizeof(float)); | |||
| else | |||
| ReduceSumByAxes(dy, arithmeticParameter_->out_shape_, dx1, arithmeticParameter_->in_shape0_, | |||
| arithmeticParameter_->ndim_); | |||
| if (dx2_size == dy_size) { | |||
| for (int i = 0; i < dx2_size; i++) { | |||
| dx2[i] = -dy[i]; | |||
| } | |||
| } else { | |||
| ReduceSumByAxes(dy, arithmeticParameter_->out_shape_, dx2, arithmeticParameter_->in_shape1_, | |||
| arithmeticParameter_->ndim_); | |||
| for (int i = 0; i < dx2_size; i++) { | |||
| dx2[i] = -dx2[i]; | |||
| } | |||
| } | |||
| } | |||
| void ArithmeticGradCPUKernel::ArithmeticGradMul(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, | |||
| int dx2_size) { | |||
| auto x1_data = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| auto x2_data = reinterpret_cast<float *>(in_tensors_[2]->MutableData()); | |||
| ElementMul(dy, x1_data, dx2, dy_size); | |||
| ElementMul(dy, x2_data, dx1, dy_size); | |||
| } | |||
| void ArithmeticGradCPUKernel::ArithmeticGradMul1L(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, | |||
| int dx2_size) { | |||
| auto x1_data = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| auto x2_data = reinterpret_cast<float *>(in_tensors_[2]->MutableData()); | |||
| ElementMul(dy, x1_data, tile_data0, dy_size); | |||
| ReduceSumByAxes(tile_data0, arithmeticParameter_->in_shape0_, dx2, arithmeticParameter_->in_shape1_, | |||
| arithmeticParameter_->ndim_); | |||
| BroadcastMul(dy, x2_data, tile_data0, tile_data1, dx1, dy_size, arithmeticParameter_); // broadcast directly to dx1 | |||
| } | |||
| void ArithmeticGradCPUKernel::ArithmeticGradMul2L(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, | |||
| int dx2_size) { | |||
| auto x1_data = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| auto x2_data = reinterpret_cast<float *>(in_tensors_[2]->MutableData()); | |||
| ElementMul(dy, x2_data, tile_data0, dy_size); | |||
| ReduceSumByAxes(tile_data0, arithmeticParameter_->in_shape0_, dx1, arithmeticParameter_->in_shape1_, | |||
| arithmeticParameter_->ndim_); | |||
| BroadcastMul(dy, x1_data, tile_data0, tile_data1, dx2, dy_size, arithmeticParameter_); // broadcast directly to dx2 | |||
| } | |||
| void ArithmeticGradCPUKernel::ArithmeticGradDiv(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, | |||
| int dx2_size) { | |||
| auto x1 = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| auto x2 = reinterpret_cast<float *>(in_tensors_[2]->MutableData()); | |||
| ElementDiv(dy, x2, dx1, dy_size); | |||
| ElementMulAndDivNegSquare(dy, x1, x2, dx2, dy_size); | |||
| } | |||
| void ArithmeticGradCPUKernel::ArithmeticGradDiv1L(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, | |||
| int dx2_size) { | |||
| auto x1_data = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| auto x2_data = reinterpret_cast<float *>(in_tensors_[2]->MutableData()); | |||
| ElementMul(x2_data, x2_data, dx2, dx2_size); | |||
| ElementMul(x1_data, dy, dx1, dy_size); // use dx1 buffer | |||
| BroadcastDiv(dx1, dx2, tile_data0, tile_data1, tile_data2, dy_size, | |||
| arithmeticParameter_); // broadcast directly to dx1 | |||
| ReduceSumByAxes(tile_data2, arithmeticParameter_->in_shape0_, dx2, arithmeticParameter_->in_shape1_, | |||
| arithmeticParameter_->ndim_); | |||
| for (int i = 0; i < dx2_size; i++) dx2[i] = -dx2[i]; | |||
| // broadcasting x2 | |||
| BroadcastDiv(dy, x2_data, tile_data0, tile_data1, dx1, dy_size, arithmeticParameter_); // broadcast directly to dx1 | |||
| } | |||
| void ArithmeticGradCPUKernel::ArithmeticGradDiv2L(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, | |||
| int dx2_size) { | |||
| auto x1_data = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| auto x2_data = reinterpret_cast<float *>(in_tensors_[2]->MutableData()); | |||
| // dx1 = dy/x2 | |||
| ElementDiv(dy, x2_data, tile_data0, dy_size); // first multiply into temp | |||
| ReduceSumByAxes(tile_data0, arithmeticParameter_->in_shape0_, dx1, arithmeticParameter_->in_shape1_, | |||
| arithmeticParameter_->ndim_); | |||
| // dx2 = -dy*x1/(x2*x2) | |||
| BroadcastMul(dy, x1_data, tile_data0, tile_data1, tile_data2, dy_size, arithmeticParameter_); // broadcast numerator | |||
| ElementDivNegSquare(tile_data2, x2_data, dx2, dy_size); | |||
| } | |||
| int ArithmeticGradCPUKernel::ReSize() { return RET_OK; } | |||
| int ArithmeticGradCPUKernel::Execute(int task_id) { | |||
| auto dy = reinterpret_cast<float *>(in_tensors_[0]->MutableData()); | |||
| auto dx1 = reinterpret_cast<float *>(out_tensors_[0]->MutableData()); | |||
| auto dx2 = reinterpret_cast<float *>(out_tensors_[1]->MutableData()); | |||
| size_t dy_size = in_tensors_.at(0)->ElementsNum(); | |||
| size_t dx1_size = out_tensors_.at(0)->ElementsNum(); | |||
| size_t dx2_size = out_tensors_[1]->ElementsNum(); | |||
| (this->*arithmetic_grad_)(dy, dy_size, dx1, dx1_size, dx2, dx2_size); | |||
| return RET_OK; | |||
| } | |||
| int ArithmeticGradRun(void *cdata, int task_id) { | |||
| auto Arithmetic_kernel = reinterpret_cast<ArithmeticGradCPUKernel *>(cdata); | |||
| auto error_code = Arithmetic_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "ArithmeticGradRun error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ArithmeticGradCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, ArithmeticGradRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "Arithmetic Grad function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuArithmeticGradFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(nullptr != opParameter); | |||
| if (opParameter == nullptr) { | |||
| return nullptr; | |||
| } | |||
| auto *kernel = new (std::nothrow) ArithmeticGradCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new ArithmeticGradCPUKernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_MulGrad, CpuArithmeticGradFp32KernelCreator) | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_AddGrad, CpuArithmeticGradFp32KernelCreator) | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_SubGrad, CpuArithmeticGradFp32KernelCreator) | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_DivGrad, CpuArithmeticGradFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,90 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ARITHMETIC_GRAD_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ARITHMETIC_GRAD_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/fp32/arithmetic.h" | |||
| #include "schema/model_generated.h" | |||
| using mindspore::schema::PrimitiveType_AddGrad; | |||
| using mindspore::schema::PrimitiveType_DivGrad; | |||
| using mindspore::schema::PrimitiveType_MulGrad; | |||
| using mindspore::schema::PrimitiveType_SubGrad; | |||
| namespace mindspore::kernel { | |||
| class ArithmeticGradCPUKernel; | |||
| class ArithmeticGradCPUKernel : public LiteKernel { | |||
| typedef void (ArithmeticGradCPUKernel::*ArithmeticGradOperation)(float *, int, float *, int, float *, int); | |||
| public: | |||
| explicit ArithmeticGradCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive), tile_data0(NULL), tile_data1(NULL), tile_data2(NULL) { | |||
| switch (Type()) { | |||
| case PrimitiveType_MulGrad: | |||
| arithmetic_grad_ = &ArithmeticGradCPUKernel::ArithmeticGradMul; // this will be adjusted in InferShape | |||
| break; | |||
| case PrimitiveType_AddGrad: | |||
| arithmetic_grad_ = &ArithmeticGradCPUKernel::ArithmeticGradAdd; | |||
| break; | |||
| case PrimitiveType_SubGrad: | |||
| arithmetic_grad_ = &ArithmeticGradCPUKernel::ArithmeticGradSub; | |||
| break; | |||
| case PrimitiveType_DivGrad: | |||
| arithmetic_grad_ = &ArithmeticGradCPUKernel::ArithmeticGradDiv; // this will be adjusted in InferShape | |||
| break; | |||
| default: | |||
| MS_LOG(ERROR) << "Error Operator type " << parameter->type_; | |||
| break; | |||
| } | |||
| arithmeticParameter_ = reinterpret_cast<ArithmeticParameter *>(parameter); | |||
| } | |||
| ~ArithmeticGradCPUKernel() override { | |||
| if (tile_data0) delete[] tile_data0; | |||
| if (tile_data1) delete[] tile_data1; | |||
| if (tile_data2) delete[] tile_data2; | |||
| } | |||
| int Init() override; | |||
| int InferShape(); | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| void ArithmeticGradAdd(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, int dx2_size); | |||
| void ArithmeticGradSub(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, int dx2_size); | |||
| void ArithmeticGradMul(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, int dx2_size); | |||
| void ArithmeticGradMul1L(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, int dx2_size); | |||
| void ArithmeticGradMul2L(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, int dx2_size); | |||
| void ArithmeticGradDiv(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, int dx2_size); | |||
| void ArithmeticGradDiv1L(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, int dx2_size); | |||
| void ArithmeticGradDiv2L(float *dy, int dy_size, float *dx1, int dx1_size, float *dx2, int dx2_size); | |||
| ArithmeticParameter *arithmeticParameter_; | |||
| ArithmeticGradOperation arithmetic_grad_; | |||
| float *tile_data0; | |||
| float *tile_data1; | |||
| float *tile_data2; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ARITHMETIC_GRAD_H_ | |||
| @@ -1,108 +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_grad/arithmetic_self_grad.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| #include "nnacl/fp32/arithmetic.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_LogGrad; | |||
| namespace mindspore::kernel { | |||
| namespace { | |||
| int ArithmeticSelfGradRun(void *cdata, int thread_id) { | |||
| MS_ASSERT(cdata != nullptr); | |||
| auto kernel = reinterpret_cast<ArithmeticSelfGradCPUKernel *>(cdata); | |||
| return kernel->DoArithmeticSelfGrad(thread_id); | |||
| } | |||
| } // namespace | |||
| int ArithmeticSelfGradCPUKernel::Init() { | |||
| auto type = Type(); | |||
| switch (type) { | |||
| case PrimitiveType_LogGrad: | |||
| self_grad_operation_ = ElementDiv; | |||
| break; | |||
| default: | |||
| MS_LOG(ERROR) << "Unsupport type: " << type; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ArithmeticSelfGradCPUKernel::DoArithmeticSelfGrad(int thread_id) { | |||
| auto dy = reinterpret_cast<float *>(in_tensors_[0]->MutableData()); | |||
| auto in_x = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| auto dx = reinterpret_cast<float *>(out_tensors_[0]->MutableData()); | |||
| int dy_size = in_tensors_.at(0)->ElementsNum(); | |||
| int size = MSMIN(thread_stride_, static_cast<int>(dy_size - thread_id * thread_stride_)); | |||
| if (size <= 0) { | |||
| return RET_OK; | |||
| } | |||
| int offset = thread_id * thread_stride_; | |||
| (*self_grad_operation_)(dy + offset, in_x + offset, dx + offset, size); | |||
| return RET_OK; | |||
| } | |||
| int ArithmeticSelfGradCPUKernel::ReSize() { return RET_OK; } | |||
| int ArithmeticSelfGradCPUKernel::Run() { | |||
| int dy_size = in_tensors_.at(0)->ElementsNum(); | |||
| op_parameter_->thread_num_ = MSMIN(op_parameter_->thread_num_, static_cast<int>(dy_size)); | |||
| thread_stride_ = UP_DIV(dy_size, op_parameter_->thread_num_); | |||
| auto ret = ParallelLaunch(this->context_->thread_pool_, ArithmeticSelfGradRun, this, op_parameter_->thread_num_); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "parallel launch fail!ret: " << ret; | |||
| return ret; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuArithmeticSelfGradFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *param, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| if (param == nullptr) { | |||
| MS_LOG(ERROR) << "input parameter is nullptr!"; | |||
| return nullptr; | |||
| } | |||
| auto *kernel = new (std::nothrow) ArithmeticSelfGradCPUKernel(param, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new ArithmeticSelfGradCPUKernel fail!"; | |||
| free(param); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << param->name_ | |||
| << ", type: " << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(param->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_LogGrad, CpuArithmeticSelfGradFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ARITHMETIC_SELF_GRAD_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ARITHMETIC_SELF_GRAD_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "schema/model_generated.h" | |||
| namespace mindspore::kernel { | |||
| class ArithmeticSelfGradCPUKernel : public LiteKernel { | |||
| typedef int (*ArithmeticSelfGradOperation)(const float *, const float *, float *, const int); | |||
| public: | |||
| ArithmeticSelfGradCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||
| ~ArithmeticSelfGradCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int DoArithmeticSelfGrad(int thread_id); | |||
| private: | |||
| int thread_stride_; | |||
| ArithmeticSelfGradOperation self_grad_operation_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ARITHMETIC_SELF_GRAD_H_ | |||
| @@ -1,85 +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_grad/assign.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| #include "src/runtime/kernel/arm/fp32/nchw2nhwc_fp32.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_Assign; | |||
| namespace mindspore::kernel { | |||
| int AssignCPUKernel::ReSize() { return RET_OK; } | |||
| int AssignCPUKernel::Execute(int task_id) { | |||
| auto x = reinterpret_cast<float *>(in_tensors_[0]->MutableData()); | |||
| auto y = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| size_t size = in_tensors_[0]->Size(); | |||
| memcpy(x, y, size); | |||
| return RET_OK; | |||
| } | |||
| int AssignRun(void *cdata, int task_id) { | |||
| auto Assign_kernel = reinterpret_cast<AssignCPUKernel *>(cdata); | |||
| auto error_code = Assign_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "assign run error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int AssignCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, AssignRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "Assign function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int AssignCPUKernel::Init() { return RET_OK; } | |||
| kernel::LiteKernel *CpuAssignFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | |||
| const lite::InnerContext *ctx, const kernel::KernelKey &desc, | |||
| const lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_Assign); | |||
| auto *kernel = new (std::nothrow) AssignCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| MS_ASSERT(kernel != nullptr); | |||
| auto ret = kernel->Init(); | |||
| if (0 != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_Assign, CpuAssignFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,39 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ASSIGN_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ASSIGN_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/fp32_grad/optimizer.h" | |||
| namespace mindspore::kernel { | |||
| class AssignCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit AssignCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||
| ~AssignCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_ASSIGN_H_ | |||
| @@ -1,111 +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 <vector> | |||
| #include "src/runtime/kernel/arm/fp32_grad/bias_grad.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.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_BiasGrad; | |||
| namespace mindspore::kernel { | |||
| int BiasGradCPUKernel::Init() { | |||
| auto dims = in_tensors_[0]->shape(); | |||
| bias_param->ndim_ = dims.size(); | |||
| for (unsigned int i = 0; i < bias_param->ndim_; i++) { | |||
| bias_param->in_shape0_[i] = dims[i]; | |||
| bias_param->out_shape_[i] = 1; // 1 dimension for N,H,W, | |||
| } | |||
| bias_param->out_shape_[bias_param->ndim_ - 1] = dims[bias_param->ndim_ - 1]; | |||
| for (int i = bias_param->ndim_; i < 4; i++) { | |||
| bias_param->in_shape0_[i] = 0; | |||
| bias_param->out_shape_[i] = 0; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int BiasGradCPUKernel::ReSize() { return RET_OK; } | |||
| int BiasGradCPUKernel::Execute(int task_id) { | |||
| auto in = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||
| auto out = reinterpret_cast<float *>(out_tensors_.at(0)->MutableData()); | |||
| size_t nhw_size = 1; | |||
| size_t channels = bias_param->in_shape0_[bias_param->ndim_ - 1]; // C in NHWC | |||
| for (unsigned int i = 0; i < bias_param->ndim_ - 1; i++) nhw_size *= bias_param->in_shape0_[i]; | |||
| size_t total_size = channels * nhw_size; | |||
| for (size_t c = 0; c < channels; ++c) { | |||
| out[c] = 0; | |||
| for (size_t offset = 0; offset < total_size; offset += channels) { | |||
| out[c] += in[offset + c]; | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int BiasGradRun(void *cdata, int task_id) { | |||
| auto bias_kernel = reinterpret_cast<BiasGradCPUKernel *>(cdata); | |||
| auto error_code = bias_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "bias error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int BiasGradCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, BiasGradRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "bias function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuBiasGradFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | |||
| const lite::InnerContext *ctx, const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_BiasGrad); | |||
| auto *kernel = new (std::nothrow) BiasGradCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new BiasGradCPUKernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (RET_OK != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_BiasGrad, CpuBiasGradFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,45 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_BIAS_GRAD_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_BIAS_GRAD_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/fp32/arithmetic.h" | |||
| namespace mindspore::kernel { | |||
| class BiasGradCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit BiasGradCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) { | |||
| bias_param = reinterpret_cast<ArithmeticParameter *>(parameter); | |||
| } | |||
| ~BiasGradCPUKernel() override = default; | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| ArithmeticParameter *bias_param; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_BIAS_GRAD_H_ | |||
| @@ -1,122 +0,0 @@ | |||
| /** | |||
| * Copyright 2019 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_grad/bn_grad.h" | |||
| #include <algorithm> | |||
| #include <vector> | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "nnacl/fp32_grad/batch_norm.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| using mindspore::kernel::KERNEL_ARCH::kCPU; | |||
| using mindspore::lite::KernelRegistrar; | |||
| using mindspore::lite::RET_ERROR; | |||
| using mindspore::lite::RET_OK; | |||
| // using mindspore::lite::REG_OP; | |||
| using mindspore::schema::PrimitiveType_BNGrad; | |||
| namespace mindspore::kernel { | |||
| int BNGradCPUKernel::Init() { | |||
| auto *input_x = in_tensors_.at(1); | |||
| int channels = input_x->shape().at(kNHWC_C); | |||
| SetWorkspaceSize(4 * channels * sizeof(float)); | |||
| return RET_OK; | |||
| } | |||
| int BNGradCPUKernel::ReSize() { return RET_OK; } | |||
| int BNGradCPUKernel::Execute(int task_id) { | |||
| auto bn_param = reinterpret_cast<BNGradParameter *>(op_parameter_); | |||
| auto *input_yt = in_tensors_.at(0); | |||
| auto *input_x = in_tensors_.at(1); | |||
| auto *input_scale = in_tensors_.at(2); | |||
| auto *output_dx = out_tensors_.at(0); | |||
| auto *output_scale = out_tensors_.at(1); | |||
| auto *output_bias = out_tensors_.at(2); | |||
| int batch = input_x->Batch(); | |||
| int channels = input_x->Channel(); | |||
| int spatial = input_x->Height() * input_x->Width(); | |||
| float eps = bn_param->epsilon_; | |||
| float *workspace = static_cast<float *>(GetWorkspace()); | |||
| std::fill(workspace, workspace + GetWorkspaceSize() / sizeof(*workspace), 0.f); | |||
| float *mean = workspace; | |||
| float *invar = mean + channels; | |||
| float *dxhat_sum = invar + channels; | |||
| float *dxhathat_sum = dxhat_sum + channels; | |||
| float *x = reinterpret_cast<float *>(input_x->MutableData()); | |||
| float *yt = reinterpret_cast<float *>(input_yt->MutableData()); | |||
| float *scale = reinterpret_cast<float *>(input_scale->MutableData()); | |||
| float *dx = reinterpret_cast<float *>(output_dx->MutableData()); | |||
| float *dscale = reinterpret_cast<float *>(output_scale->MutableData()); | |||
| float *dbias = reinterpret_cast<float *>(output_bias->MutableData()); | |||
| backwardX(x, yt, scale, batch * spatial, channels, eps, mean, invar, dxhat_sum, dxhathat_sum, dx); | |||
| // dbias | |||
| sumSpatialBatch(yt, batch * spatial, channels, dbias); | |||
| // dscale | |||
| backwardScale(x, mean, invar, yt, batch, channels, spatial, dscale); | |||
| return RET_OK; | |||
| } | |||
| int BNGradRun(void *cdata, int task_id) { | |||
| auto bn_kernel = reinterpret_cast<BNGradCPUKernel *>(cdata); | |||
| if (task_id == 0) { | |||
| auto error_code = bn_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "BNGradRun error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int BNGradCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, BNGradRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "BN function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuBNGradFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | |||
| const lite::InnerContext *ctx, const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_BNGrad); | |||
| auto *kernel = new (std::nothrow) BNGradCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new BNGradCPUKernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (RET_OK != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_BNGrad, CpuBNGradFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,38 +0,0 @@ | |||
| /** | |||
| * Copyright 2019 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_GRAD_BN_GRAD_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_BN_GRAD_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| namespace mindspore::kernel { | |||
| class BNGradCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit BNGradCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||
| ~BNGradCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_BN_GRAD_H_ | |||
| @@ -1,150 +0,0 @@ | |||
| /** | |||
| * Copyright 2019 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_grad/convolution.h" | |||
| #include "nnacl/fp32_grad/pack_ext.h" | |||
| #include "nnacl/fp32_grad/gemm.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| using mindspore::kernel::KERNEL_ARCH::kCPU; | |||
| using mindspore::lite::RET_ERROR; | |||
| using mindspore::lite::RET_OK; | |||
| namespace mindspore::kernel { | |||
| int ConvolutionTrainCPUKernel::Init() { | |||
| if (2 != in_tensors_.size()) { | |||
| MS_LOG(ERROR) << "Convolution should have two inputs"; | |||
| return RET_ERROR; | |||
| } | |||
| if (1 != out_tensors_.size()) { | |||
| MS_LOG(ERROR) << "Convolution should have one output"; | |||
| return RET_ERROR; | |||
| } | |||
| auto conv_param_ = reinterpret_cast<ConvParameter *>(op_parameter_); | |||
| auto *input_x = in_tensors_.at(kInputIndex); | |||
| auto *input_weight = in_tensors_.at(kWeightIndex); | |||
| auto *out_y = out_tensors_.at(kOutputIndex); | |||
| conv_param_->output_batch_ = out_y->shape().at(kNHWC_N); | |||
| conv_param_->input_batch_ = input_x->shape().at(kNHWC_N); | |||
| conv_param_->input_h_ = input_x->shape().at(kNHWC_H); | |||
| conv_param_->input_w_ = input_x->shape().at(kNHWC_W); | |||
| conv_param_->output_h_ = out_y->shape().at(kNHWC_H); | |||
| conv_param_->output_w_ = out_y->shape().at(kNHWC_W); | |||
| conv_param_->input_channel_ = input_x->shape().at(kNHWC_C); | |||
| conv_param_->output_channel_ = input_weight->shape().at(kNHWC_N); | |||
| conv_param_->kernel_h_ = input_weight->shape().at(kNHWC_H); | |||
| conv_param_->kernel_w_ = input_weight->shape().at(kNHWC_W); | |||
| conv_param_->group_ = (conv_param_->group_ == 0) ? conv_param_->input_channel_ : conv_param_->group_; | |||
| int ws_size = conv_param_->output_h_ * conv_param_->output_w_ * conv_param_->kernel_h_ * conv_param_->kernel_w_ * | |||
| conv_param_->input_channel_ / conv_param_->group_; | |||
| SetWorkspaceSize(ws_size * sizeof(float)); | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionTrainCPUKernel::ReSize() { return RET_OK; } | |||
| int ConvolutionTrainCPUKernel::Execute(int task_id) { | |||
| auto conv_param_ = reinterpret_cast<ConvParameter *>(op_parameter_); | |||
| auto *input_x = in_tensors_.at(kInputIndex); | |||
| auto *input_w = in_tensors_.at(kWeightIndex); | |||
| auto *out_y = out_tensors_.at(kOutputIndex); | |||
| auto x_addr = reinterpret_cast<float *>(input_x->MutableData()); | |||
| auto y_addr = reinterpret_cast<float *>(out_y->MutableData()); | |||
| auto w_addr = reinterpret_cast<float *>(input_w->MutableData()); | |||
| int i, j; | |||
| int nweights = input_w->ElementsNum(); | |||
| int in_ch = conv_param_->input_channel_; | |||
| int in_h = conv_param_->input_h_; | |||
| int in_w = conv_param_->input_w_; | |||
| int k_h = conv_param_->kernel_h_; | |||
| int k_w = conv_param_->kernel_w_; | |||
| int batch = conv_param_->output_batch_; | |||
| int out_ch = conv_param_->output_channel_; // out_y->shape()[3]; | |||
| int groups = conv_param_->group_; | |||
| int out_h = conv_param_->output_h_; | |||
| int out_w = conv_param_->output_w_; | |||
| int m = out_h * out_w; | |||
| int n = out_ch / groups; | |||
| int k = k_h * k_w * in_ch / groups; | |||
| float *workspace = static_cast<float *>(GetWorkspace()); | |||
| memset(y_addr, 0, out_y->Size()); | |||
| for (i = 0; i < batch; ++i) { | |||
| for (j = 0; j < groups; ++j) { | |||
| float *mat_a = workspace; | |||
| float *mat_b = w_addr + j * nweights / groups; | |||
| float *mat_c = y_addr + (i * groups) * n * m + j * (out_ch / groups); | |||
| float *im = x_addr + (i * groups) * (in_ch / groups) * in_h * in_w + j * (in_ch / groups); | |||
| im2col_hwc(im, mat_a, conv_param_); | |||
| gemm(0, 1, m, n, k, 1, mat_a, k, mat_b, k, 1, mat_c, out_ch); | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionTrainRun(void *cdata, int task_id) { | |||
| auto conv_kernel = reinterpret_cast<ConvolutionTrainCPUKernel *>(cdata); | |||
| auto error_code = conv_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "ConvolutionTrainRun error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionTrainCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, ConvolutionTrainRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "conv train function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuConvTrainFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | |||
| const lite::InnerContext *ctx, const kernel::KernelKey &desc, | |||
| const lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_Conv2D || desc.type == schema::PrimitiveType_DepthwiseConv2D); | |||
| auto *kernel = new (std::nothrow) ConvolutionTrainCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new ConvolutionTrainCPUKernel failed!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (RET_OK != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| } // namespace mindspore::kernel | |||
| @@ -1,44 +0,0 @@ | |||
| /** | |||
| * Copyright 2019 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_GRAD_CONVOLUTION_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_CONVOLUTION_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| namespace mindspore::kernel { | |||
| class ConvolutionTrainCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit ConvolutionTrainCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||
| ~ConvolutionTrainCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| }; | |||
| kernel::LiteKernel *CpuConvTrainFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | |||
| const lite::InnerContext *ctx, const kernel::KernelKey &desc, | |||
| const lite::PrimitiveC *primitive); | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_CONVOLUTION_H_ | |||
| @@ -1,154 +0,0 @@ | |||
| /** | |||
| * Copyright 2019 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_grad/convolution_grad_filter.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "nnacl/pack.h" | |||
| #include "nnacl/fp32_grad/pack_ext.h" | |||
| #include "nnacl/fp32_grad/gemm.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.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_Conv2DGradFilter; | |||
| namespace mindspore::kernel { | |||
| int ConvolutionGradFilterCPUKernel::Init() { | |||
| // dy is in input 0 | |||
| // x is in input 1 | |||
| // dw is output 0 | |||
| auto *x_tensor = in_tensors_.at(1); | |||
| MS_ASSERT(x_tensor != nullptr); | |||
| auto *dy_tensor = in_tensors_.at(0); | |||
| MS_ASSERT(dy_tensor != nullptr); | |||
| auto conv_param = reinterpret_cast<ConvParameter *>(op_parameter_); | |||
| conv_param->output_batch_ = dy_tensor->shape().at(kNHWC_N); | |||
| conv_param->input_batch_ = x_tensor->shape().at(kNHWC_N); | |||
| conv_param->input_h_ = x_tensor->shape().at(kNHWC_H); | |||
| conv_param->input_w_ = x_tensor->shape().at(kNHWC_W); | |||
| // assume OutCh|kh|kw|InCh | |||
| conv_param->input_channel_ = x_tensor->shape().at(kNHWC_C); | |||
| conv_param->output_channel_ = dy_tensor->shape().at(kNHWC_C); | |||
| conv_param->output_h_ = dy_tensor->shape()[kNHWC_H]; | |||
| conv_param->output_w_ = dy_tensor->shape()[kNHWC_W]; | |||
| size_t ws_size = conv_param->output_h_ * conv_param->output_w_ * conv_param->kernel_h_ * conv_param->kernel_w_ * | |||
| conv_param->input_channel_ / conv_param->group_; | |||
| SetWorkspaceSize(ws_size * sizeof(float)); | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionGradFilterCPUKernel::ReSize() { return RET_OK; } | |||
| int ConvolutionGradFilterCPUKernel::Execute(int task_id) { | |||
| auto conv_param = reinterpret_cast<ConvParameter *>(op_parameter_); | |||
| auto *input_dy = in_tensors_.at(0); | |||
| auto *input_x = in_tensors_.at(1); | |||
| auto *out_dw = out_tensors_.at(0); | |||
| auto x_addr = reinterpret_cast<float *>(input_x->MutableData()); | |||
| auto dy_addr = reinterpret_cast<float *>(input_dy->MutableData()); | |||
| auto dw_addr = reinterpret_cast<float *>(out_dw->MutableData()); | |||
| int i, j; | |||
| int nweights = out_dw->ElementsNum(); | |||
| int in_ch = conv_param->input_channel_; | |||
| int in_h = conv_param->input_h_; | |||
| int in_w = conv_param->input_w_; | |||
| int k_h = conv_param->kernel_h_; | |||
| int k_w = conv_param->kernel_w_; | |||
| int batch = conv_param->output_batch_; | |||
| int out_ch = conv_param->output_channel_; | |||
| int groups = conv_param->group_; | |||
| int out_h = conv_param->output_h_; | |||
| int out_w = conv_param->output_w_; | |||
| int m = out_h * out_w; | |||
| int n = k_h * k_w * in_ch / groups; | |||
| int k = out_ch / groups; | |||
| float *workspace = reinterpret_cast<float *>(GetWorkspace()); | |||
| // zero out pointer | |||
| memset(dw_addr, 0, out_dw->Size()); | |||
| for (i = 0; i < batch; ++i) { | |||
| for (j = 0; j < groups; ++j) { | |||
| float *mat_a = dy_addr + (i * groups) * m * k + j * (out_ch / groups); | |||
| float *mat_b = workspace; | |||
| float *mat_c = dw_addr + j * nweights / groups; | |||
| float *im = x_addr + (i * in_ch * in_h * in_w) + j * (in_ch / groups); | |||
| im2row_hwc(im, mat_b, conv_param, false); | |||
| gemm(1, 1, k, n, m, 1, mat_a, out_ch, mat_b, m, 1, mat_c, n); | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionGradFilterRun(void *cdata, int task_id) { | |||
| auto convfilter_kernel = reinterpret_cast<ConvolutionGradFilterCPUKernel *>(cdata); | |||
| auto error_code = convfilter_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "ConvolutionGradFilterRun error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionGradFilterCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, ConvolutionGradFilterRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "conv filter function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuConvGradFilterFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_Conv2DGradFilter); | |||
| auto *kernel = new (std::nothrow) ConvolutionGradFilterCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new kernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (RET_OK != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_Conv2DGradFilter, CpuConvGradFilterFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,41 +0,0 @@ | |||
| /** | |||
| * Copyright 2019 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_GRAD_CONVOLUTION_GRAD_FILTER_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_CONVOLUTION_GRAD_FILTER_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| namespace mindspore::kernel { | |||
| class ConvolutionGradFilterCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit ConvolutionGradFilterCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||
| ~ConvolutionGradFilterCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_CONVOLUTION_GRAD_FILTER_H_ | |||
| @@ -1,155 +0,0 @@ | |||
| /** | |||
| * Copyright 2019 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_grad/convolution_grad_input.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "nnacl/pack.h" | |||
| #include "nnacl/fp32_grad/pack_ext.h" | |||
| #include "nnacl/fp32_grad/gemm.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.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_Conv2DGradInput; | |||
| using mindspore::schema::PrimitiveType_GroupConv2DGradInput; | |||
| namespace mindspore::kernel { | |||
| int ConvolutionGradInputCPUKernel::Init() { | |||
| auto *dy_tensor = in_tensors_.at(kInputIndex); | |||
| MS_ASSERT(dy_tensor != nullptr); | |||
| auto *weight_tensor = in_tensors_.at(kWeightIndex); | |||
| MS_ASSERT(weight_tensor != nullptr); | |||
| auto *dx_tensor = out_tensors_.at(kOutputIndex); | |||
| MS_ASSERT(dx_tensor != nullptr); | |||
| auto conv_param = reinterpret_cast<ConvParameter *>(op_parameter_); | |||
| conv_param->output_batch_ = dx_tensor->shape()[(kNHWC_N)]; | |||
| conv_param->input_batch_ = dy_tensor->shape()[(kNHWC_N)]; | |||
| conv_param->input_h_ = dx_tensor->shape()[(kNHWC_H)]; | |||
| conv_param->input_w_ = dx_tensor->shape()[(kNHWC_W)]; | |||
| // assume OutCh|kh|kw|In | |||
| conv_param->input_channel_ = dx_tensor->shape()[(kNHWC_C)]; | |||
| conv_param->output_channel_ = weight_tensor->shape()[(kNHWC_N)]; | |||
| conv_param->output_h_ = dy_tensor->shape()[kNHWC_H]; | |||
| conv_param->output_w_ = dy_tensor->shape()[kNHWC_W]; | |||
| size_t ws_size = conv_param->output_h_ * conv_param->output_w_ * conv_param->kernel_h_ * conv_param->kernel_w_ * | |||
| conv_param->input_channel_ / conv_param->group_; | |||
| SetWorkspaceSize(ws_size * sizeof(float)); | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionGradInputCPUKernel::ReSize() { return RET_OK; } | |||
| int ConvolutionGradInputCPUKernel::Execute(int task_id) { | |||
| auto conv_param = reinterpret_cast<ConvParameter *>(op_parameter_); | |||
| auto *input_dy = in_tensors_.at(0); | |||
| auto *input_w = in_tensors_.at(1); | |||
| auto *out_dx = out_tensors_.at(0); | |||
| auto dy_addr = reinterpret_cast<float *>(input_dy->MutableData()); | |||
| auto w_addr = reinterpret_cast<float *>(input_w->MutableData()); | |||
| auto dx_addr = reinterpret_cast<float *>(out_dx->MutableData()); | |||
| int i, j; | |||
| int nweights = input_w->ElementsNum(); | |||
| int in_ch = conv_param->input_channel_; | |||
| int in_h = conv_param->input_h_; | |||
| int in_w = conv_param->input_w_; | |||
| int k_h = conv_param->kernel_h_; // out_dw->shape()[1]; | |||
| int k_w = conv_param->kernel_w_; // out_dw->shape()[2]; | |||
| int batch = conv_param->output_batch_; | |||
| int out_ch = conv_param->output_channel_; | |||
| int groups = conv_param->group_; | |||
| int out_h = conv_param->output_h_; | |||
| int out_w = conv_param->output_w_; | |||
| int m = out_h * out_w; | |||
| int n = k_w * k_h * in_ch / groups; | |||
| int k = out_ch / groups; | |||
| float *workspace = reinterpret_cast<float *>(GetWorkspace()); | |||
| memset(dx_addr, 0, sizeof(float) * batch * in_ch * in_h * in_w); | |||
| for (i = 0; i < batch; ++i) { | |||
| for (j = 0; j < groups; ++j) { | |||
| float *mat_a = dy_addr + (i * groups) * m * k + j * (out_ch / groups); | |||
| float *mat_b = w_addr + j * nweights / groups; | |||
| float *mat_c = workspace; | |||
| gemm(0, 0, m, n, k, 1, mat_a, out_ch, mat_b, n, 0, mat_c, n); | |||
| col2im_hwc(mat_c, dx_addr + (i * groups) * (in_ch / groups) * in_h * in_w + j * (in_ch / groups), conv_param); | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionGradInputRun(void *cdata, int task_id) { | |||
| auto convinput_kernel = reinterpret_cast<ConvolutionGradInputCPUKernel *>(cdata); | |||
| auto error_code = convinput_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "conv input error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int ConvolutionGradInputCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, ConvolutionGradInputRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "bias function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuConvGradInputFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_Conv2DGradInput || | |||
| desc.type == schema::PrimitiveType_GroupConv2DGradInput); | |||
| auto *kernel = new (std::nothrow) ConvolutionGradInputCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new kernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (0 != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_Conv2DGradInput, CpuConvGradInputFp32KernelCreator) | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_GroupConv2DGradInput, CpuConvGradInputFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,39 +0,0 @@ | |||
| /** | |||
| * Copyright 2019 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_GRAD_CONVOLUTION_GRAD_INPUT_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_CONVOLUTION_GRAD_INPUT_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| namespace mindspore::kernel { | |||
| class ConvolutionGradInputCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit ConvolutionGradInputCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||
| ~ConvolutionGradInputCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_CONVOLUTION_GRAD_INPUT_H_ | |||
| @@ -1,150 +0,0 @@ | |||
| /** | |||
| * Copyright 2019 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_grad/deconvolution_grad_filter.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "nnacl/pack.h" | |||
| #include "nnacl/fp32_grad/pack_ext.h" | |||
| #include "nnacl/fp32_grad/gemm.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_DeConv2DGradFilter; | |||
| namespace mindspore::kernel { | |||
| int DeConvolutionGradFilterCPUKernel::Init() { | |||
| // dy is in input 0 | |||
| // x is in input 1 | |||
| // dw is output 0 | |||
| auto *x_tensor = in_tensors_.at(1); | |||
| MS_ASSERT(x_tensor != nullptr); | |||
| auto *dy_tensor = in_tensors_.at(0); | |||
| MS_ASSERT(dy_tensor != nullptr); | |||
| auto conv_param = reinterpret_cast<ConvParameter *>(op_parameter_); | |||
| conv_param->output_batch_ = dy_tensor->shape().at(kNHWC_N); | |||
| conv_param->input_batch_ = x_tensor->shape().at(kNHWC_N); | |||
| conv_param->input_h_ = x_tensor->shape().at(kNHWC_H); | |||
| conv_param->input_w_ = x_tensor->shape().at(kNHWC_W); | |||
| // assume OutCh|kh|kw|InCh | |||
| conv_param->input_channel_ = x_tensor->shape().at(kNHWC_C); | |||
| conv_param->output_channel_ = dy_tensor->shape().at(kNHWC_C); | |||
| conv_param->output_h_ = dy_tensor->shape()[kNHWC_H]; | |||
| conv_param->output_w_ = dy_tensor->shape()[kNHWC_W]; | |||
| int ws_size = conv_param->input_h_ * conv_param->input_w_ * conv_param->kernel_h_ * conv_param->kernel_w_ * | |||
| conv_param->output_channel_ / conv_param->group_; | |||
| SetWorkspaceSize(ws_size * sizeof(float)); | |||
| return RET_OK; | |||
| } | |||
| int DeConvolutionGradFilterCPUKernel::ReSize() { return RET_OK; } | |||
| int DeConvolutionGradFilterCPUKernel::Execute(int task_id) { | |||
| auto conv_param = reinterpret_cast<ConvParameter *>(op_parameter_); | |||
| auto *input_dy = in_tensors_.at(0); | |||
| auto *input_x = in_tensors_.at(1); | |||
| auto *out_dw = out_tensors_.at(0); | |||
| auto x_addr = reinterpret_cast<float *>(input_x->MutableData()); | |||
| auto dy_addr = reinterpret_cast<float *>(input_dy->MutableData()); | |||
| auto dw_addr = reinterpret_cast<float *>(out_dw->MutableData()); | |||
| int i, j; | |||
| int in_ch = conv_param->input_channel_; | |||
| int in_h = conv_param->input_h_; | |||
| int in_w = conv_param->input_w_; | |||
| int k_h = conv_param->kernel_h_; | |||
| int k_w = conv_param->kernel_w_; | |||
| int batch = conv_param->output_batch_; | |||
| int out_ch = conv_param->output_channel_; | |||
| int groups = conv_param->group_; | |||
| int out_h = conv_param->output_h_; | |||
| int out_w = conv_param->output_w_; | |||
| int m = in_ch / groups; | |||
| int n = k_h * k_w * out_ch / groups; | |||
| int k = in_h * in_w; | |||
| float *workspace = reinterpret_cast<float *>(GetWorkspace()); | |||
| // zero out pointer | |||
| memset(dw_addr, 0, out_dw->Size()); | |||
| for (i = 0; i < batch; ++i) { | |||
| for (j = 0; j < groups; ++j) { | |||
| float *mat_a = x_addr + (i * (in_ch * in_h * in_w) + j * (in_ch / groups)); | |||
| float *mat_b = workspace; | |||
| float *mat_c = dw_addr + j * m; | |||
| float *im = dy_addr + (i * (out_h * out_w * out_ch) + j * (out_ch / groups)); | |||
| im2row_hwc(im, mat_b, conv_param, true); | |||
| gemm(0, 0, n, m, k, 1, mat_b, k, mat_a, in_ch, 1, mat_c, in_ch); | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int DeConvolutionGradFilterRun(void *cdata, int task_id) { | |||
| auto convfilter_kernel = reinterpret_cast<DeConvolutionGradFilterCPUKernel *>(cdata); | |||
| auto error_code = convfilter_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "DeConvolutionGradFilterRun error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int DeConvolutionGradFilterCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, DeConvolutionGradFilterRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "conv filter function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuDeConvGradFilterFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_DeConv2DGradFilter); | |||
| auto *kernel = new (std::nothrow) DeConvolutionGradFilterCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new kernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (RET_OK != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_DeConv2DGradFilter, CpuDeConvGradFilterFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,40 +0,0 @@ | |||
| /** | |||
| * Copyright 2019 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_GRAD_DECONVOLUTION_GRAD_FILTER_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_DECONVOLUTION_GRAD_FILTER_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| namespace mindspore::kernel { | |||
| class DeConvolutionGradFilterCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit DeConvolutionGradFilterCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||
| ~DeConvolutionGradFilterCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_DECONVOLUTION_GRAD_FILTER_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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_MAKE_TUPLE_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_MAKE_TUPLE_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "src/runtime/kernel/arm/nnacl/fp32/arithmetic.h" | |||
| namespace mindspore::kernel { | |||
| class MakeTupleCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit MakeTupleCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const lite::Primitive *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) { | |||
| param = parameter; | |||
| } | |||
| ~MakeTupleCPUKernel() override = default; | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int DoActivation(int task_id); | |||
| private: | |||
| OpParameter *param; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_MAKE_TUPLE_H_ | |||
| @@ -1,95 +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_grad/neg_grad.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| #include "nnacl/fp32/arithmetic_self.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_NegGrad; | |||
| namespace mindspore::kernel { | |||
| namespace { | |||
| int NegGradRun(void *cdata, int thread_id) { | |||
| MS_ASSERT(cdata != nullptr); | |||
| auto kernel = reinterpret_cast<NegGradCPUKernel *>(cdata); | |||
| return kernel->DoNegGrad(thread_id); | |||
| } | |||
| } // namespace | |||
| int NegGradCPUKernel::Init() { return RET_OK; } | |||
| int NegGradCPUKernel::DoNegGrad(int thread_id) { | |||
| auto dy = reinterpret_cast<float *>(in_tensors_[0]->MutableData()); | |||
| auto dx = reinterpret_cast<float *>(out_tensors_[0]->MutableData()); | |||
| int dy_size = in_tensors_.at(0)->ElementsNum(); | |||
| int size = MSMIN(thread_stride_, static_cast<int>(dy_size - thread_id * thread_stride_)); | |||
| if (size <= 0) { | |||
| return RET_OK; | |||
| } | |||
| int offset = thread_id * thread_stride_; | |||
| ElementNegative(dy + offset, dx + offset, size); | |||
| return RET_OK; | |||
| } | |||
| int NegGradCPUKernel::ReSize() { return RET_OK; } | |||
| int NegGradCPUKernel::Run() { | |||
| int dy_size = in_tensors_.at(0)->ElementsNum(); | |||
| op_parameter_->thread_num_ = MSMIN(op_parameter_->thread_num_, static_cast<int>(dy_size)); | |||
| thread_stride_ = UP_DIV(dy_size, op_parameter_->thread_num_); | |||
| auto ret = ParallelLaunch(this->context_->thread_pool_, NegGradRun, this, op_parameter_->thread_num_); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "parallel launch fail!ret: " << ret; | |||
| return ret; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuNegGradFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, OpParameter *param, | |||
| const lite::InnerContext *ctx, const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| if (param == nullptr) { | |||
| MS_LOG(ERROR) << "input parameter is nullptr!"; | |||
| return nullptr; | |||
| } | |||
| auto *kernel = new (std::nothrow) NegGradCPUKernel(param, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new NegGradCPUKernel fail!"; | |||
| free(param); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << param->name_ | |||
| << ", type: " << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(param->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_NegGrad, CpuNegGradFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,43 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_NEG_GRAD_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_NEG_GRAD_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "schema/model_generated.h" | |||
| namespace mindspore::kernel { | |||
| class NegGradCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit NegGradCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||
| ~NegGradCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int DoNegGrad(int thread_id); | |||
| private: | |||
| int thread_stride_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_NEG_GRAD_H_ | |||
| @@ -1,131 +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_grad/pooling_grad.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "nnacl/fp32/pooling.h" | |||
| #include "nnacl/fp32_grad/pooling_grad.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.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_PoolingGrad; | |||
| namespace mindspore::kernel { | |||
| int PoolingGradCPUKernel::Init() { | |||
| PoolingParameter *pool_param = reinterpret_cast<PoolingParameter *>(op_parameter_); | |||
| auto in_shape = in_tensors_.at(0)->shape(); | |||
| auto out_shape = in_tensors_.at(1)->shape(); | |||
| if (pool_param->pool_mode_ == PoolMode_AvgPool) { | |||
| in_shape = in_tensors_.at(1)->shape(); | |||
| out_shape = in_tensors_.at(0)->shape(); | |||
| } | |||
| int input_h = in_shape.at(1); | |||
| int input_w = in_shape.at(2); | |||
| if (pool_param->global_) { | |||
| pool_param->window_w_ = input_w; | |||
| pool_param->window_h_ = input_h; | |||
| } | |||
| pool_param->input_h_ = in_shape[kNHWC_H]; | |||
| pool_param->input_w_ = in_shape[kNHWC_W]; | |||
| pool_param->input_batch_ = in_shape[kNHWC_N]; | |||
| pool_param->input_channel_ = in_shape[kNHWC_C]; | |||
| pool_param->output_h_ = out_shape[kNHWC_H]; | |||
| pool_param->output_w_ = out_shape[kNHWC_W]; | |||
| pool_param->output_batch_ = out_shape[kNHWC_N]; | |||
| pool_param->output_channel_ = out_shape[kNHWC_C]; | |||
| return RET_OK; | |||
| } | |||
| int PoolingGradCPUKernel::ReSize() { return RET_OK; } | |||
| int PoolingGradCPUKernel::Execute(int task_id) { | |||
| PoolingParameter *pool_param = reinterpret_cast<PoolingParameter *>(op_parameter_); | |||
| auto input_ptr = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||
| auto output_ptr = reinterpret_cast<float *>(out_tensors_.at(0)->MutableData()); | |||
| if (pool_param->pool_mode_ == PoolMode_MaxPool) { | |||
| auto dx_ptr = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | |||
| auto dy_ptr = reinterpret_cast<float *>(in_tensors_.at(2)->MutableData()); | |||
| MaxPoolingGrad(input_ptr, dx_ptr, dy_ptr, output_ptr, pool_param, task_id); | |||
| } else { | |||
| AvgPoolingGrad(input_ptr, output_ptr, pool_param, task_id); | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int PoolingGradImpl(void *cdata, int task_id) { | |||
| auto pooling = reinterpret_cast<PoolingGradCPUKernel *>(cdata); | |||
| auto error_code = pooling->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "Pooling Run error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int PoolingGradCPUKernel::Run() { | |||
| // clear output buffer before parallel run | |||
| PoolingParameter *pooling_param = reinterpret_cast<PoolingParameter *>(op_parameter_); | |||
| auto output_ptr = reinterpret_cast<float *>(out_tensors_.at(0)->MutableData()); | |||
| int size = | |||
| pooling_param->input_w_ * pooling_param->input_h_ * pooling_param->input_channel_ * pooling_param->output_batch_; | |||
| for (int i = 0; i < size; i++) output_ptr[i] = 0.0; | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, PoolingGradImpl, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "pooling error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuPoolingGradFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_PoolingGrad); | |||
| auto *kernel = new (std::nothrow) PoolingGradCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new PoolingGradCPUKernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (RET_OK != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_PoolingGrad, CpuPoolingGradFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,47 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_POOLING_GRAD_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_POOLING_GRAD_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| namespace mindspore::kernel { | |||
| using mindspore::schema::PadMode; | |||
| using mindspore::schema::PoolMode; | |||
| using mindspore::schema::QuantType; | |||
| using mindspore::schema::RoundMode; | |||
| class PoolingGradCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit PoolingGradCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||
| ~PoolingGradCPUKernel() override = default; | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_POOLING_GRAD_H_ | |||
| @@ -1,104 +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_grad/power_grad.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| #include "nnacl/fp32/arithmetic.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| using mindspore::lite::KernelRegistrar; | |||
| using mindspore::lite::RET_ERROR; | |||
| using mindspore::lite::RET_OK; | |||
| using mindspore::schema::PrimitiveType_PowerGrad; | |||
| namespace mindspore::kernel { | |||
| int PowerGradCPUKernel::Init() { | |||
| if (2 != in_tensors_.size()) { | |||
| MS_LOG(ERROR) << "Power Grad Filter should have 2 inputs"; | |||
| return RET_ERROR; | |||
| } | |||
| if (1 != out_tensors_.size()) { | |||
| MS_LOG(ERROR) << "Power Grad Filter should have one output"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int PowerGradCPUKernel::ReSize() { return RET_OK; } | |||
| int PowerGradCPUKernel::Execute(int task_id) { | |||
| auto dy_addr = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||
| auto x_addr = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | |||
| auto dx_addr = reinterpret_cast<float *>(out_tensors_.at(0)->MutableData()); | |||
| auto size = in_tensors_.at(0)->ElementsNum(); | |||
| float exp = power_ - 1; | |||
| Power(x_addr, &exp, dx_addr, size, scale_, shift_, true); | |||
| ElementMul(dx_addr, dy_addr, dx_addr, size); | |||
| float scale = scale_ * power_; | |||
| for (int i = 0; i < size; i++) { | |||
| dx_addr[i] *= scale; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int PowerGradRun(void *cdata, int task_id) { | |||
| auto power_kernel = reinterpret_cast<PowerGradCPUKernel *>(cdata); | |||
| auto error_code = power_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "power grad error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int PowerGradCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, PowerGradRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "power grad function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuPowerGradFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | |||
| const lite::InnerContext *ctx, const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_PowerGrad); | |||
| auto *kernel = new (std::nothrow) PowerGradCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new PowerGradCPUKernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_PowerGrad, CpuPowerGradFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,51 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_POWER_GRAD_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_POWER_GRAD_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/power.h" | |||
| namespace mindspore::kernel { | |||
| class PowerGradCPUKernel : public LiteKernel { | |||
| public: | |||
| PowerGradCPUKernel(OpParameter *param, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(param, inputs, outputs, ctx, primitive) { | |||
| PowerParameter *power_param = reinterpret_cast<PowerParameter *>(param); | |||
| power_ = power_param->power_; | |||
| scale_ = power_param->scale_; | |||
| shift_ = power_param->shift_; | |||
| } | |||
| ~PowerGradCPUKernel() override = default; | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| float power_; | |||
| float scale_; | |||
| float shift_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_POWER_GRAD_H_ | |||
| @@ -1,119 +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_grad/sgd.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| #include "src/runtime/kernel/arm/fp32/nchw2nhwc_fp32.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_Sgd; | |||
| namespace mindspore::kernel { | |||
| int SgdCPUKernel::ReSize() { return RET_OK; } | |||
| int SgdCPUKernel::Execute(int task_id) { | |||
| auto weight = reinterpret_cast<float *>(in_tensors_[0]->MutableData()); | |||
| auto accumulate = reinterpret_cast<float *>(in_tensors_[3]->MutableData()); | |||
| float learning_rate = reinterpret_cast<float *>(in_tensors_[2]->MutableData())[0]; | |||
| auto gradient = reinterpret_cast<float *>(in_tensors_[1]->MutableData()); | |||
| float moment = reinterpret_cast<float *>(in_tensors_[4]->MutableData())[0]; | |||
| size_t elem_num = in_tensors_[0]->ElementsNum(); | |||
| if (sgd_param_->use_nesterov_) { | |||
| for (size_t i = 0; i < elem_num; ++i) { | |||
| accumulate[i] = accumulate[i] * moment + gradient[i]; | |||
| weight[i] -= (accumulate[i] * moment + gradient[i]) * learning_rate; | |||
| } | |||
| } else { | |||
| for (size_t i = 0; i < elem_num; ++i) { | |||
| accumulate[i] = accumulate[i] * moment + gradient[i] * (1.f - sgd_param_->dampening_); | |||
| weight[i] -= accumulate[i] * learning_rate; | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int SgdRun(void *cdata, int task_id) { | |||
| auto Sgd_kernel = reinterpret_cast<SgdCPUKernel *>(cdata); | |||
| auto error_code = Sgd_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "SGD run error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int SgdCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, SgdRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "SGD function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int SgdCPUKernel::Init() { | |||
| // Only for test with uninitialized Data | |||
| size_t elem_num = in_tensors_[0]->ElementsNum(); | |||
| auto accumulate = reinterpret_cast<float *>(in_tensors_[3]->MutableData()); | |||
| for (size_t i = 0; i < elem_num; i++) accumulate[i] = 0.0; | |||
| if (sgd_param_->dampening_ < 0.0f) { | |||
| MS_LOG(ERROR) << "dampening should be at least 0.0"; | |||
| return RET_ERROR; | |||
| } | |||
| if (sgd_param_->use_nesterov_ && sgd_param_->dampening_ > 0.0f) { | |||
| MS_LOG(ERROR) << "If use nesterov, dampening must equal to 0.0"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuSgdFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | |||
| const lite::InnerContext *ctx, const kernel::KernelKey &desc, | |||
| const lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_Sgd); | |||
| auto *kernel = new (std::nothrow) SgdCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new SgdCPUKernel failed!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (RET_OK != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_Sgd, CpuSgdFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,44 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SGD_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SGD_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/fp32_grad/optimizer.h" | |||
| namespace mindspore::kernel { | |||
| class SgdCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit SgdCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive), sgd_param_(nullptr) { | |||
| sgd_param_ = reinterpret_cast<SgdParameter *>(parameter); | |||
| } | |||
| ~SgdCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| SgdParameter *sgd_param_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SGD_H_ | |||
| @@ -1,153 +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 <math.h> | |||
| #include "src/kernel_registry.h" | |||
| #include "nnacl/softmax_parameter.h" | |||
| #include "nnacl/fp32/softmax.h" | |||
| #include "src/runtime/kernel/arm/fp32_grad/softmax_cross_entropy_with_logits.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| using mindspore::lite::KernelRegistrar; | |||
| using mindspore::lite::RET_ERROR; | |||
| using mindspore::lite::RET_OK; | |||
| using mindspore::schema::PrimitiveType_SoftmaxCrossEntropy; | |||
| namespace mindspore::kernel { | |||
| int SoftmaxCrossEntropyWithLogitsCPUKernel::ReSize() { return RET_OK; } | |||
| void SoftmaxCrossEntropyWithLogitsCPUKernel::ForwardPostExecute(const float *labels, const float *logits, float *grads, | |||
| float *output2) const { | |||
| float eps = 1e-6; | |||
| float total_loss = 0.0; | |||
| if (grads != nullptr) { | |||
| for (int i = 0; i < param_->batch_size_; ++i) { | |||
| for (size_t j = 0; j < param_->number_of_classes_; ++j) { | |||
| float logit = | |||
| -logf(logits[i * param_->number_of_classes_ + j] <= 0.0 ? eps : logits[i * param_->number_of_classes_ + j]); | |||
| grads[i * param_->number_of_classes_ + j] = | |||
| (logits[i * param_->number_of_classes_ + j] - labels[i * param_->number_of_classes_ + j]) / | |||
| param_->batch_size_; | |||
| total_loss += labels[i * param_->number_of_classes_ + j] * logit; | |||
| } | |||
| } | |||
| } else { | |||
| for (int i = 0; i < param_->batch_size_; ++i) { | |||
| for (size_t j = 0; j < param_->number_of_classes_; ++j) { | |||
| float logit = | |||
| -logf(logits[i * param_->number_of_classes_ + j] <= 0.0 ? eps : logits[i * param_->number_of_classes_ + j]); | |||
| total_loss += labels[i * param_->number_of_classes_ + j] * logit; | |||
| } | |||
| } | |||
| } | |||
| output2[0] = total_loss / param_->batch_size_; | |||
| } | |||
| int SoftmaxCrossEntropyWithLogitsCPUKernel::Execute(int task_id) { | |||
| auto ins = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||
| auto labels = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | |||
| float *out = reinterpret_cast<float *>(out_tensors_.at(0)->MutableData()); | |||
| float *grads = NULL; | |||
| if (is_train() && out_tensors_.size() > 1) { | |||
| grads = reinterpret_cast<float *>(out_tensors_.at(1)->MutableData()); | |||
| } | |||
| size_t data_size = in_tensors_.at(0)->ElementsNum(); | |||
| MS_ASSERT(out != nullptr); | |||
| MS_ASSERT(labels != nullptr); | |||
| MS_ASSERT(ins != nullptr); | |||
| float *losses_ = static_cast<float *>(GetWorkspace()); | |||
| float *sum_data_ = losses_ + data_size; | |||
| std::fill(losses_, losses_ + data_size, 0); | |||
| std::fill(sum_data_, sum_data_ + sm_params_.input_shape_[0], 0); | |||
| Softmax(ins, losses_, sum_data_, &sm_params_); | |||
| ForwardPostExecute(labels, losses_, grads, out); | |||
| return RET_OK; | |||
| } | |||
| int SoftmaxCrossEntropyWithLogitsRun(void *cdata, int task_id) { | |||
| auto softmax_kernel = reinterpret_cast<SoftmaxCrossEntropyWithLogitsCPUKernel *>(cdata); | |||
| auto error_code = softmax_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "SoftmaxCrossEntropy error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int SoftmaxCrossEntropyWithLogitsCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, SoftmaxCrossEntropyWithLogitsRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "SoftmaxCrossEntropy function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int SoftmaxCrossEntropyWithLogitsCPUKernel::Init() { | |||
| auto dims = in_tensors_[0]->shape(); | |||
| param_->n_dim_ = 2; | |||
| param_->number_of_classes_ = dims[1]; | |||
| param_->batch_size_ = dims[0]; | |||
| for (unsigned int i = 0; i < dims.size(); i++) param_->input_shape_[i] = dims[i]; | |||
| if (2 != this->in_tensors_.size()) { | |||
| MS_LOG(ERROR) << "softmax entropy loss should have two inputs"; | |||
| return RET_ERROR; | |||
| } | |||
| auto *in0 = in_tensors_.front(); | |||
| if (in0 == nullptr) { | |||
| MS_LOG(ERROR) << "softmax etropy loss in0 have no data"; | |||
| return RET_ERROR; | |||
| } | |||
| size_t data_size = in_tensors_.at(0)->ElementsNum(); | |||
| SetWorkspaceSize((data_size + dims[0]) * sizeof(float)); | |||
| sm_params_.n_dim_ = 2; | |||
| sm_params_.element_size_ = data_size; | |||
| sm_params_.axis_ = 1; | |||
| for (size_t i = 0; i < dims.size(); i++) sm_params_.input_shape_[i] = dims[i]; | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuSoftmaxCrossEntropyFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_SoftmaxCrossEntropy); | |||
| auto *kernel = | |||
| new (std::nothrow) SoftmaxCrossEntropyWithLogitsCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new SoftmaxCrossEntropyWithLogitsCPUKernel failed"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (RET_OK != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_SoftmaxCrossEntropy, CpuSoftmaxCrossEntropyFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,53 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SOFTMAX_CROSS_ENTROPY_WITH_LOGITS_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SOFTMAX_CROSS_ENTROPY_WITH_LOGITS_H_ | |||
| #include <vector> | |||
| #include "src/train/loss_kernel.h" | |||
| #include "nnacl/fp32_grad/softmax_grad.h" | |||
| #include "nnacl/fp32/arithmetic.h" | |||
| #include "nnacl/softmax_parameter.h" | |||
| namespace mindspore::kernel { | |||
| class SoftmaxCrossEntropyWithLogitsCPUKernel : public LossKernel { | |||
| public: | |||
| explicit SoftmaxCrossEntropyWithLogitsCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LossKernel(parameter, inputs, outputs, ctx, primitive) { | |||
| param_ = reinterpret_cast<SoftmaxCrossEntropyParameter *>(parameter); | |||
| } | |||
| ~SoftmaxCrossEntropyWithLogitsCPUKernel() override {} | |||
| void ForwardPostExecute(const float *labels, const float *logits, float *output1, float *output2) const; | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| SoftmaxCrossEntropyParameter *param_; | |||
| SoftmaxParameter sm_params_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SOFTMAX_CROSS_ENTROPY_WITH_LOGITS_H_ | |||
| @@ -1,112 +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_grad/softmax_grad.h" | |||
| #include <string.h> | |||
| #include <vector> | |||
| #include "nnacl/fp32_grad/softmax_grad.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| #include "include/errorcode.h" | |||
| using mindspore::lite::KernelRegistrar; | |||
| using mindspore::lite::RET_ERROR; | |||
| using mindspore::lite::RET_OK; | |||
| namespace mindspore::kernel { | |||
| int SoftmaxGradCPUKernel::Init() { | |||
| param = reinterpret_cast<SoftmaxParameter *>(op_parameter_); | |||
| auto in_shape = in_tensors_.at(0)->shape(); | |||
| auto in_dims = in_shape.size(); | |||
| int ele_size = 1; | |||
| param->n_dim_ = in_dims; | |||
| for (size_t i = 0; i < in_dims; i++) { | |||
| param->input_shape_[i] = in_shape[i]; | |||
| ele_size *= in_shape[i]; | |||
| } | |||
| param->element_size_ = ele_size; | |||
| auto axis = param->axis_; | |||
| if ((axis < -1) || (axis > param->n_dim_)) { | |||
| MS_LOG(ERROR) << "SoftmaxGrad axis is invalid!"; | |||
| } else if (axis == -1) { | |||
| axis = param->axis_ = (in_dims - 1); | |||
| } | |||
| inner_size_ = 1; | |||
| for (size_t i = axis + 1; i < in_dims; i++) { | |||
| inner_size_ *= in_shape[i]; | |||
| } | |||
| SetWorkspaceSize(inner_size_ * (1 + in_shape[axis]) * sizeof(float)); | |||
| return RET_OK; | |||
| } | |||
| int SoftmaxGradCPUKernel::ReSize() { return RET_OK; } | |||
| int SoftmaxGradCPUKernel::Execute(int task_id) { | |||
| auto input_ptr = reinterpret_cast<float *>(in_tensors_.at(kInputIndex)->MutableData()); | |||
| auto yt_ptr = reinterpret_cast<float *>(in_tensors_.at(1)->MutableData()); | |||
| auto output_ptr = reinterpret_cast<float *>(out_tensors_.at(kOutputIndex)->MutableData()); | |||
| float *sum_data_ = static_cast<float *>(GetWorkspace()); | |||
| float *sum_mul_ = sum_data_ + inner_size_; | |||
| SoftmaxGrad(input_ptr, yt_ptr, output_ptr, sum_data_, sum_mul_, reinterpret_cast<SoftmaxParameter *>(op_parameter_)); | |||
| return RET_OK; | |||
| } | |||
| int SoftmaxGradRun(void *cdata, int task_id) { | |||
| auto softmax_kernel = reinterpret_cast<SoftmaxGradCPUKernel *>(cdata); | |||
| auto error_code = softmax_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "softmax_kernel SoftmaxGradRun task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int SoftmaxGradCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, SoftmaxGradRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "SoftmaxGradRun function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuSoftmaxGradFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, | |||
| const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| auto *kernel = new (std::nothrow) SoftmaxGradCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new SoftmaxGradCPUKernel fail!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| } // namespace mindspore::kernel | |||
| @@ -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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SOFTMAX_GRAD_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SOFTMAX_GRAD_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/softmax_parameter.h" | |||
| namespace mindspore::kernel { | |||
| class SoftmaxGradCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit SoftmaxGradCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) { | |||
| param = reinterpret_cast<SoftmaxParameter *>(parameter); | |||
| } | |||
| ~SoftmaxGradCPUKernel() override {} | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| SoftmaxParameter *param; | |||
| size_t inner_size_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SOFTMAX_GRAD_H_ | |||
| @@ -1,176 +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 <math.h> | |||
| #include "src/kernel_registry.h" | |||
| #include "nnacl/softmax_parameter.h" | |||
| #include "nnacl/fp32/softmax.h" | |||
| #include "src/runtime/kernel/arm/fp32_grad/sparse_softmax_cross_entropy_with_logits.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| using mindspore::lite::KernelRegistrar; | |||
| using mindspore::lite::RET_ERROR; | |||
| using mindspore::lite::RET_OK; | |||
| using mindspore::schema::PrimitiveType_SoftmaxCrossEntropy; | |||
| namespace mindspore::kernel { | |||
| int SparseSoftmaxCrossEntropyWithLogitsCPUKernel::ReSize() { return RET_OK; } | |||
| int SparseSoftmaxCrossEntropyWithLogitsCPUKernel::ForwardPostExecute(const int *labels, const float *losses, | |||
| float *output) const { | |||
| float total_loss = 0; | |||
| for (int i = 0; i < param->batch_size_; ++i) { | |||
| if (labels[i] < 0) { | |||
| MS_LOG(ERROR) << "label value must >= 0"; | |||
| return RET_ERROR; | |||
| } | |||
| size_t label = labels[i]; | |||
| if (label > param->number_of_classes_) { | |||
| MS_LOG(ERROR) << "error label input!"; | |||
| return RET_ERROR; | |||
| } else { | |||
| total_loss -= logf(losses[i * param->number_of_classes_ + label]); | |||
| } | |||
| } | |||
| output[0] = total_loss / param->batch_size_; | |||
| return RET_OK; | |||
| } | |||
| int SparseSoftmaxCrossEntropyWithLogitsCPUKernel::GradPostExecute(const int *labels, const float *losses, float *grads, | |||
| float *output) const { | |||
| size_t row_start = 0; | |||
| float total_loss = 0; | |||
| for (int i = 0; i < param->batch_size_; ++i) { | |||
| if (labels[i] < 0) { | |||
| MS_LOG(ERROR) << "label value must >= 0"; | |||
| return RET_ERROR; | |||
| } | |||
| size_t label = labels[i]; | |||
| if (label > param->number_of_classes_) { | |||
| MS_LOG(ERROR) << "error label input!"; | |||
| return RET_ERROR; | |||
| } else { | |||
| total_loss -= logf(losses[i * param->number_of_classes_ + label]); | |||
| for (size_t j = 0; j < param->number_of_classes_; ++j) { | |||
| size_t index = row_start + j; | |||
| if (j == label) { | |||
| grads[index] = (losses[index] - 1) / param->batch_size_; | |||
| } else { | |||
| grads[index] = losses[index] / param->batch_size_; | |||
| } | |||
| } | |||
| } | |||
| row_start += param->number_of_classes_; | |||
| } | |||
| output[0] = total_loss / param->batch_size_; | |||
| return RET_OK; | |||
| } | |||
| int SparseSoftmaxCrossEntropyWithLogitsCPUKernel::Execute(int task_id) { | |||
| auto ins = reinterpret_cast<float *>(in_tensors_.at(0)->data_c()); | |||
| auto labels = reinterpret_cast<int *>(in_tensors_.at(1)->data_c()); | |||
| float *out = reinterpret_cast<float *>(out_tensors_.at(0)->data_c()); | |||
| float *grads = NULL; | |||
| if (is_train() && out_tensors_.size() > 1) { | |||
| grads = reinterpret_cast<float *>(out_tensors_.at(1)->MutableData()); | |||
| } | |||
| size_t data_size = in_tensors_.at(0)->ElementsNum(); | |||
| MS_ASSERT(out != nullptr); | |||
| MS_ASSERT(labels != nullptr); | |||
| MS_ASSERT(ins != nullptr); | |||
| float *losses_ = static_cast<float *>(GetWorkspace()); | |||
| float *sum_data_ = losses_ + data_size; | |||
| std::fill(losses_, losses_ + data_size, 0.f); | |||
| std::fill(sum_data_, sum_data_ + sm_params_.input_shape_[0], 0.f); | |||
| Softmax(ins, losses_, sum_data_, &sm_params_); | |||
| if (is_train()) { | |||
| GradPostExecute(labels, losses_, grads, out); | |||
| } else { | |||
| ForwardPostExecute(labels, losses_, out); | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int SparseSoftmaxCrossEntropyRun(void *cdata, int task_id) { | |||
| auto sparse_kernel = reinterpret_cast<SparseSoftmaxCrossEntropyWithLogitsCPUKernel *>(cdata); | |||
| auto error_code = sparse_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "SparseSoftmaxCrossEntropyRun error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int SparseSoftmaxCrossEntropyWithLogitsCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, SparseSoftmaxCrossEntropyRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "SparseSoftmaxCrossEntropy function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int SparseSoftmaxCrossEntropyWithLogitsCPUKernel::Init() { | |||
| auto dims = in_tensors_[0]->shape(); | |||
| param->n_dim_ = 2; | |||
| param->number_of_classes_ = dims[1]; | |||
| param->batch_size_ = dims[0]; | |||
| for (unsigned int i = 0; i < dims.size(); i++) param->input_shape_[i] = dims[i]; | |||
| if (2 != this->in_tensors_.size()) { | |||
| MS_LOG(ERROR) << "softmax entropy loss should have two inputs"; | |||
| return RET_ERROR; | |||
| } | |||
| auto *in0 = in_tensors_.front(); | |||
| if (in0 == nullptr) { | |||
| MS_LOG(ERROR) << "softmax etropy loss in0 have no data"; | |||
| return RET_ERROR; | |||
| } | |||
| size_t data_size = in_tensors_.at(0)->ElementsNum(); | |||
| SetWorkspaceSize((data_size + dims[0]) * sizeof(float)); | |||
| sm_params_.n_dim_ = 2; | |||
| sm_params_.element_size_ = data_size; | |||
| sm_params_.axis_ = 1; | |||
| for (size_t i = 0; i < dims.size(); i++) sm_params_.input_shape_[i] = dims[i]; | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuSparseSoftmaxCrossEntropyFp32KernelCreator( | |||
| const std::vector<lite::Tensor *> &inputs, const std::vector<lite::Tensor *> &outputs, OpParameter *opParameter, | |||
| const lite::InnerContext *ctx, const kernel::KernelKey &desc, const mindspore::lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_SoftmaxCrossEntropy); | |||
| auto *kernel = | |||
| new (std::nothrow) SparseSoftmaxCrossEntropyWithLogitsCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new SparseSoftmaxCrossEntropyWithLogitsCPUKernel failed!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (RET_OK != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| } // namespace mindspore::kernel | |||
| @@ -1,55 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SPARSE_SOFTMAX_CROSS_ENTROPY_WITH_LOGITS_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SPARSE_SOFTMAX_CROSS_ENTROPY_WITH_LOGITS_H_ | |||
| #include <vector> | |||
| #include "src/train/loss_kernel.h" | |||
| #include "nnacl/fp32_grad/softmax_grad.h" | |||
| #include "nnacl/fp32/arithmetic.h" | |||
| #include "nnacl/softmax_parameter.h" | |||
| namespace mindspore::kernel { | |||
| class SparseSoftmaxCrossEntropyWithLogitsCPUKernel : public LossKernel { | |||
| public: | |||
| explicit SparseSoftmaxCrossEntropyWithLogitsCPUKernel(OpParameter *parameter, | |||
| const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| const lite::InnerContext *ctx, | |||
| const mindspore::lite::PrimitiveC *primitive) | |||
| : LossKernel(parameter, inputs, outputs, ctx, primitive) { | |||
| param = reinterpret_cast<SoftmaxCrossEntropyParameter *>(parameter); | |||
| } | |||
| ~SparseSoftmaxCrossEntropyWithLogitsCPUKernel() override {} | |||
| int ForwardPostExecute(const int *labels, const float *losses, float *output) const; | |||
| int GradPostExecute(const int *labels, const float *losses, float *grads, float *output) const; | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| SoftmaxCrossEntropyParameter *param; | |||
| SoftmaxParameter sm_params_; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_SPARSE_SOFTMAX_CROSS_ENTROPY_WITH_LOGITS_H_ | |||
| @@ -1,98 +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 <vector> | |||
| #include "src/runtime/kernel/arm/fp32_grad/tuple_getitem.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/runtime/runtime_api.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_TupleGetItem; | |||
| namespace mindspore::kernel { | |||
| int TupleGetItemCPUKernel::Init() { | |||
| if (1 != in_tensors_.size()) { | |||
| MS_LOG(ERROR) << "Tuple Grad Filter should have one input"; | |||
| return RET_ERROR; | |||
| } | |||
| if (1 != out_tensors_.size()) { | |||
| MS_LOG(ERROR) << "Tuple Grad Filter should have one output"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int TupleGetItemCPUKernel::ReSize() { return RET_OK; } | |||
| int TupleGetItemCPUKernel::Execute(int task_id) { | |||
| auto in = reinterpret_cast<float *>(in_tensors_.at(0)->MutableData()); | |||
| auto out = reinterpret_cast<float *>(out_tensors_.at(0)->MutableData()); | |||
| memcpy(out, in, in_tensors_.at(0)->Size()); | |||
| return RET_OK; | |||
| } | |||
| int TupleRun(void *cdata, int task_id) { | |||
| auto tuple_kernel = reinterpret_cast<TupleGetItemCPUKernel *>(cdata); | |||
| auto error_code = tuple_kernel->Execute(task_id); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "tuple grad error task_id[" << task_id << "] error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int TupleGetItemCPUKernel::Run() { | |||
| int error_code = ParallelLaunch(this->context_->thread_pool_, TupleRun, this, 1); | |||
| if (error_code != RET_OK) { | |||
| MS_LOG(ERROR) << "tuple function error error_code[" << error_code << "]"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| kernel::LiteKernel *CpuTupleGetItemFp32KernelCreator(const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, | |||
| OpParameter *opParameter, const lite::InnerContext *ctx, | |||
| const kernel::KernelKey &desc, const lite::PrimitiveC *primitive) { | |||
| MS_ASSERT(opParameter != nullptr); | |||
| MS_ASSERT(desc.type == schema::PrimitiveType_TupleGetItem); | |||
| auto *kernel = new (std::nothrow) TupleGetItemCPUKernel(opParameter, inputs, outputs, ctx, primitive); | |||
| if (kernel == nullptr) { | |||
| MS_LOG(ERROR) << "new TupleGetItemCPUKernel failed!"; | |||
| free(opParameter); | |||
| return nullptr; | |||
| } | |||
| auto ret = kernel->Init(); | |||
| if (RET_OK != ret) { | |||
| MS_LOG(ERROR) << "Init kernel failed, name: " << opParameter->name_ << ", type: " | |||
| << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(opParameter->type_)); | |||
| delete kernel; | |||
| return nullptr; | |||
| } | |||
| return kernel; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_TupleGetItem, CpuTupleGetItemFp32KernelCreator) | |||
| } // namespace mindspore::kernel | |||
| @@ -1,45 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_TUPLE_GETITEM_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_TUPLE_GETITEM_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "nnacl/fp32/arithmetic.h" | |||
| namespace mindspore::kernel { | |||
| class TupleGetItemCPUKernel : public LiteKernel { | |||
| public: | |||
| explicit TupleGetItemCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) { | |||
| param = parameter; | |||
| } | |||
| ~TupleGetItemCPUKernel() override = default; | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int Execute(int task_id); | |||
| private: | |||
| OpParameter *param; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_GRAD_TUPLE_GETITEM_H_ | |||
| @@ -1,33 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_TRAIN_LOSS_KERNEL_H_ | |||
| #define MINDSPORE_LITE_SRC_TRAIN_LOSS_KERNEL_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| namespace mindspore::kernel { | |||
| class LossKernel : public LiteKernel { | |||
| public: | |||
| LossKernel() = default; | |||
| explicit LossKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx, | |||
| const lite::PrimitiveC *primitive) | |||
| : LiteKernel(parameter, inputs, outputs, ctx, primitive) {} | |||
| ~LossKernel() = default; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_TRAIN_LOSS_KERNEL_H_ | |||
| @@ -1,126 +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/ops/primitive_c.h" | |||
| #include "include/train_model.h" | |||
| #include "src/common/log_adapter.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/common/graph_util.h" | |||
| #include "src/model_common.h" | |||
| namespace mindspore::lite { | |||
| bool ConvertNodes(const schema::MetaGraph *meta_graph, Model *model); | |||
| bool ConvertTensors(const schema::MetaGraph *meta_graph, Model *model); | |||
| TrainModel *TrainModel::Import(const char *model_buf, size_t size) { | |||
| if (model_buf == nullptr) { | |||
| MS_LOG(ERROR) << "The model buf is nullptr"; | |||
| return nullptr; | |||
| } | |||
| flatbuffers::Verifier verify((const uint8_t *)model_buf, size); | |||
| if (!schema::VerifyMetaGraphBuffer(verify)) { | |||
| MS_LOG(ERROR) << "The buffer is invalid and fail to create graph."; | |||
| return nullptr; | |||
| } | |||
| TrainModel *model = new (std::nothrow) TrainModel(); | |||
| if (model == nullptr) { | |||
| MS_LOG(ERROR) << "new model fail!"; | |||
| return nullptr; | |||
| } | |||
| model->buf = reinterpret_cast<char *>(malloc(size)); | |||
| if (model->buf == nullptr) { | |||
| delete model; | |||
| MS_LOG(ERROR) << "new inner model buf fail!"; | |||
| return nullptr; | |||
| } | |||
| memcpy(model->buf, model_buf, size); | |||
| model->buf_size_ = size; | |||
| auto meta_graph = schema::GetMetaGraph(model->buf); | |||
| if (meta_graph == nullptr) { | |||
| free(model->buf); | |||
| delete model; | |||
| MS_LOG(ERROR) << "meta_graph is nullptr!"; | |||
| return nullptr; | |||
| } | |||
| if (meta_graph->name() != nullptr) { | |||
| model->name_ = meta_graph->name()->c_str(); | |||
| } | |||
| if (meta_graph->version() != nullptr) { | |||
| model->version_ = meta_graph->version()->c_str(); | |||
| } | |||
| if (!ConvertNodes(meta_graph, model)) { | |||
| delete model; | |||
| return nullptr; | |||
| } | |||
| if (!ConvertTensors(meta_graph, model)) { | |||
| delete model; | |||
| return nullptr; | |||
| } | |||
| if (meta_graph->subGraph() == nullptr) { | |||
| int ret = MetaGraphMappingSubGraph(meta_graph, model); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "converter old version model wrong."; | |||
| return nullptr; | |||
| } | |||
| } else { | |||
| auto sub_graphs = meta_graph->subGraph(); | |||
| auto sub_graph_size = sub_graphs->size(); | |||
| for (size_t i = 0; i < sub_graph_size; i++) { | |||
| auto sub_graph = sub_graphs->GetAs<schema::SubGraph>(i); | |||
| int ret = ConvertSubGraph(sub_graph, model); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "converter subgraph wrong."; | |||
| return nullptr; | |||
| } | |||
| } | |||
| } | |||
| return model; | |||
| } | |||
| void TrainModel::Free() {} | |||
| char *TrainModel::ExportBuf(char *buffer, size_t *len) const { | |||
| if (len == nullptr) { | |||
| MS_LOG(ERROR) << "len is nullptr"; | |||
| return nullptr; | |||
| } | |||
| if (buf_size_ == 0 || buf == nullptr) { | |||
| MS_LOG(ERROR) << "Model::Export is only available for Train Session"; | |||
| return nullptr; | |||
| } | |||
| if (*len < buf_size_ && buffer != nullptr) { | |||
| MS_LOG(ERROR) << "Buffer is too small, Export Failed"; | |||
| return nullptr; | |||
| } | |||
| if (buffer == nullptr) { | |||
| buffer = reinterpret_cast<char *>(malloc(buf_size_)); | |||
| } | |||
| if (buffer == nullptr) { | |||
| MS_LOG(ERROR) << "allocated model buf fail!"; | |||
| return nullptr; | |||
| } | |||
| memcpy(buffer, buf, buf_size_); | |||
| *len = buf_size_; | |||
| return buffer; | |||
| } | |||
| TrainModel::~TrainModel() { Model::Free(); } | |||
| } // namespace mindspore::lite | |||
| @@ -1,435 +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/train/train_populate_parameter.h" | |||
| #include "src/ops/populate/populate_register.h" | |||
| #include "src/ops/pooling_grad.h" | |||
| #include "nnacl/pooling_parameter.h" | |||
| #include "src/ops/softmax_cross_entropy.h" | |||
| #include "nnacl/fp32_grad/softmax_grad.h" | |||
| #include "src/ops/activation_grad.h" | |||
| #include "nnacl/fp32/activation.h" | |||
| #include "src/ops/conv2d_grad_filter.h" | |||
| #include "src/ops/conv2d_grad_input.h" | |||
| #include "src/ops/group_conv2d_grad_input.h" | |||
| #include "nnacl/conv_parameter.h" | |||
| #include "src/ops/power_grad.h" | |||
| #include "nnacl/power_parameter.h" | |||
| #include "src/ops/bias_grad.h" | |||
| #include "nnacl/arithmetic_common.h" | |||
| #include "nnacl/fp32_grad/optimizer.h" | |||
| #include "src/ops/apply_momentum.h" | |||
| #include "src/ops/sgd.h" | |||
| #include "src/ops/bn_grad.h" | |||
| #include "nnacl/fp32_grad/batch_norm.h" | |||
| #include "src/ops/adam.h" | |||
| #include "src/ops/oneslike.h" | |||
| #include "src/ops/binary_cross_entropy.h" | |||
| #include "src/ops/binary_cross_entropy_grad.h" | |||
| namespace mindspore::kernel { | |||
| OpParameter *DefaultPopulateParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| OpParameter *param = reinterpret_cast<OpParameter *>(malloc(sizeof(OpParameter))); | |||
| if (param == nullptr) { | |||
| MS_LOG(ERROR) << "new Param for primitive failed."; | |||
| return nullptr; | |||
| } | |||
| param->type_ = primitive->Type(); | |||
| return param; | |||
| } | |||
| OpParameter *PopulateApplyMomentumParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| ApplyMomentumParameter *p = reinterpret_cast<ApplyMomentumParameter *>(malloc(sizeof(ApplyMomentumParameter))); | |||
| if (p == nullptr) { | |||
| MS_LOG(ERROR) << "new ApplyMomentumParameter failed."; | |||
| return nullptr; | |||
| } | |||
| p->op_parameter_.type_ = primitive->Type(); | |||
| auto apply_momentum_primitive = | |||
| reinterpret_cast<mindspore::lite::ApplyMomentum *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| p->grad_scale_ = apply_momentum_primitive->GetGradientScale(); | |||
| p->use_nesterov_ = apply_momentum_primitive->GetUseNesterov(); | |||
| return reinterpret_cast<OpParameter *>(p); | |||
| } | |||
| OpParameter *PopulateBCEParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| int32_t *reduction = reinterpret_cast<int32_t *>(malloc(sizeof(int32_t))); | |||
| if (reduction == nullptr) { | |||
| MS_LOG(ERROR) << "malloc reduction failed."; | |||
| return nullptr; | |||
| } | |||
| auto param = | |||
| reinterpret_cast<mindspore::lite::BinaryCrossEntropy *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| *reduction = param->GetReduction(); | |||
| return reinterpret_cast<OpParameter *>(reduction); | |||
| } | |||
| OpParameter *PopulateBCEGradParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| int32_t *reduction = reinterpret_cast<int32_t *>(malloc(sizeof(int32_t))); | |||
| if (reduction == nullptr) { | |||
| MS_LOG(ERROR) << "malloc reduction failed."; | |||
| return nullptr; | |||
| } | |||
| auto param = | |||
| reinterpret_cast<mindspore::lite::BinaryCrossEntropyGrad *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| *reduction = param->GetReduction(); | |||
| return reinterpret_cast<OpParameter *>(reduction); | |||
| } | |||
| OpParameter *PopulateAdamParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| AdamParameter *p = reinterpret_cast<AdamParameter *>(malloc(sizeof(AdamParameter))); | |||
| if (p == nullptr) { | |||
| MS_LOG(ERROR) << "new AdamParameter failed."; | |||
| return nullptr; | |||
| } | |||
| p->op_parameter_.type_ = primitive->Type(); | |||
| auto apply_momentum_primitive = | |||
| reinterpret_cast<mindspore::lite::Adam *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| p->use_nesterov_ = apply_momentum_primitive->GetUseNesterov(); | |||
| return reinterpret_cast<OpParameter *>(p); | |||
| } | |||
| OpParameter *PopulateSgdParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| SgdParameter *p = reinterpret_cast<SgdParameter *>(malloc(sizeof(SgdParameter))); | |||
| if (p == nullptr) { | |||
| MS_LOG(ERROR) << "new SgdParameter failed."; | |||
| return nullptr; | |||
| } | |||
| p->op_parameter_.type_ = primitive->Type(); | |||
| auto sgd_primitive = reinterpret_cast<mindspore::lite::Sgd *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| p->weight_decay_ = sgd_primitive->GetWeightDecay(); | |||
| p->dampening_ = sgd_primitive->GetDampening(); | |||
| p->use_nesterov_ = sgd_primitive->GetUseNesterov(); | |||
| return reinterpret_cast<OpParameter *>(p); | |||
| } | |||
| OpParameter *PopulateSoftmaxCrossEntropyParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| SoftmaxCrossEntropyParameter *sce_param = | |||
| reinterpret_cast<SoftmaxCrossEntropyParameter *>(malloc(sizeof(SoftmaxCrossEntropyParameter))); | |||
| if (sce_param == nullptr) { | |||
| MS_LOG(ERROR) << "new SoftmaxCrossEntropyParameter failed."; | |||
| return nullptr; | |||
| } | |||
| sce_param->op_parameter_.type_ = primitive->Type(); | |||
| return reinterpret_cast<OpParameter *>(sce_param); | |||
| } | |||
| OpParameter *PopulatePoolingGradParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| PoolingParameter *pooling_param = reinterpret_cast<PoolingParameter *>(malloc(sizeof(PoolingParameter))); | |||
| if (pooling_param == nullptr) { | |||
| MS_LOG(ERROR) << "new PoolingParameter failed."; | |||
| return nullptr; | |||
| } | |||
| pooling_param->op_parameter_.type_ = primitive->Type(); | |||
| auto pooling_primitive = | |||
| reinterpret_cast<mindspore::lite::PoolingGrad *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| pooling_param->global_ = pooling_primitive->GetGlobal(); | |||
| pooling_param->window_w_ = pooling_primitive->GetWindowW(); | |||
| pooling_param->window_h_ = pooling_primitive->GetWindowH(); | |||
| pooling_param->pad_u_ = pooling_primitive->GetPadUp(); | |||
| pooling_param->pad_d_ = pooling_primitive->GetPadDown(); | |||
| pooling_param->pad_l_ = pooling_primitive->GetPadLeft(); | |||
| pooling_param->pad_r_ = pooling_primitive->GetPadRight(); | |||
| pooling_param->stride_w_ = pooling_primitive->GetStrideW(); | |||
| pooling_param->stride_h_ = pooling_primitive->GetStrideH(); | |||
| pooling_param->pool_mode_ = PoolMode_No; | |||
| pooling_param->round_mode_ = RoundMode_No; | |||
| switch (pooling_primitive->GetPoolingMode()) { | |||
| case schema::PoolMode_MAX_POOLING: | |||
| pooling_param->pool_mode_ = PoolMode_MaxPool; | |||
| break; | |||
| case schema::PoolMode_MEAN_POOLING: | |||
| pooling_param->pool_mode_ = PoolMode_AvgPool; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| switch (pooling_primitive->GetRoundMode()) { | |||
| case schema::RoundMode_FLOOR: | |||
| pooling_param->round_mode_ = RoundMode_Floor; | |||
| break; | |||
| case schema::RoundMode_CEIL: | |||
| pooling_param->round_mode_ = RoundMode_Ceil; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| return reinterpret_cast<OpParameter *>(pooling_param); | |||
| } | |||
| OpParameter *PopulateActivationGradParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| ActivationParameter *act_param = reinterpret_cast<ActivationParameter *>(malloc(sizeof(ActivationParameter))); | |||
| if (act_param == nullptr) { | |||
| MS_LOG(ERROR) << "new ActivationParameter failed."; | |||
| return nullptr; | |||
| } | |||
| act_param->op_parameter_.type_ = primitive->Type(); | |||
| auto activation = | |||
| reinterpret_cast<mindspore::lite::ActivationGrad *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| act_param->type_ = static_cast<int>(activation->GetType()); | |||
| act_param->alpha_ = activation->GetAlpha(); | |||
| return reinterpret_cast<OpParameter *>(act_param); | |||
| } | |||
| OpParameter *PopulateConvolutionGradFilterParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| ConvParameter *param = reinterpret_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| if (param == nullptr) { | |||
| MS_LOG(ERROR) << "new Param for conv grad filter failed."; | |||
| return nullptr; | |||
| } | |||
| param->op_parameter_.type_ = primitive->Type(); | |||
| auto convg_primitive = | |||
| reinterpret_cast<mindspore::lite::Conv2DGradFilter *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| param->kernel_h_ = convg_primitive->GetKernelH(); | |||
| param->kernel_w_ = convg_primitive->GetKernelW(); | |||
| param->stride_h_ = convg_primitive->GetStrideH(); | |||
| param->stride_w_ = convg_primitive->GetStrideW(); | |||
| param->dilation_h_ = convg_primitive->GetDilateH(); | |||
| param->dilation_w_ = convg_primitive->GetDilateW(); | |||
| param->pad_u_ = convg_primitive->GetPadUp(); | |||
| param->pad_d_ = convg_primitive->GetPadDown(); | |||
| param->pad_l_ = convg_primitive->GetPadLeft(); | |||
| param->pad_r_ = convg_primitive->GetPadRight(); | |||
| param->group_ = convg_primitive->GetGroup(); | |||
| param->act_type_ = ActType_No; | |||
| switch (convg_primitive->GetActivationType()) { | |||
| case schema::ActivationType_RELU: | |||
| param->act_type_ = ActType_Relu; | |||
| break; | |||
| case schema::ActivationType_RELU6: | |||
| param->act_type_ = ActType_Relu6; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| return reinterpret_cast<OpParameter *>(param); | |||
| } | |||
| OpParameter *PopulateConvolutionGradInputParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| ConvParameter *param = reinterpret_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| if (param == nullptr) { | |||
| MS_LOG(ERROR) << "new Param for conv grad filter failed."; | |||
| return nullptr; | |||
| } | |||
| param->op_parameter_.type_ = primitive->Type(); | |||
| auto convg_primitive = | |||
| reinterpret_cast<mindspore::lite::Conv2DGradInput *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| param->kernel_h_ = convg_primitive->GetKernelH(); | |||
| param->kernel_w_ = convg_primitive->GetKernelW(); | |||
| param->stride_h_ = convg_primitive->GetStrideH(); | |||
| param->stride_w_ = convg_primitive->GetStrideW(); | |||
| param->dilation_h_ = convg_primitive->GetDilateH(); | |||
| param->dilation_w_ = convg_primitive->GetDilateW(); | |||
| param->pad_u_ = convg_primitive->GetPadUp(); | |||
| param->pad_d_ = convg_primitive->GetPadDown(); | |||
| param->pad_l_ = convg_primitive->GetPadLeft(); | |||
| param->pad_r_ = convg_primitive->GetPadRight(); | |||
| param->group_ = convg_primitive->GetGroup(); | |||
| param->act_type_ = ActType_No; | |||
| switch (convg_primitive->GetActivationType()) { | |||
| case schema::ActivationType_RELU: | |||
| param->act_type_ = ActType_Relu; | |||
| break; | |||
| case schema::ActivationType_RELU6: | |||
| param->act_type_ = ActType_Relu6; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| return reinterpret_cast<OpParameter *>(param); | |||
| } | |||
| OpParameter *PopulateGroupConvolutionGradInputParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| ConvParameter *param = reinterpret_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| if (param == nullptr) { | |||
| MS_LOG(ERROR) << "new Param for conv grad filter failed."; | |||
| return nullptr; | |||
| } | |||
| param->op_parameter_.type_ = primitive->Type(); | |||
| auto convg_primitive = | |||
| reinterpret_cast<mindspore::lite::GroupConv2DGradInput *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| param->kernel_h_ = convg_primitive->GetKernelH(); | |||
| param->kernel_w_ = convg_primitive->GetKernelW(); | |||
| param->stride_h_ = convg_primitive->GetStrideH(); | |||
| param->stride_w_ = convg_primitive->GetStrideW(); | |||
| param->dilation_h_ = convg_primitive->GetDilateH(); | |||
| param->dilation_w_ = convg_primitive->GetDilateW(); | |||
| param->pad_u_ = convg_primitive->GetPadUp(); | |||
| param->pad_d_ = convg_primitive->GetPadDown(); | |||
| param->pad_l_ = convg_primitive->GetPadLeft(); | |||
| param->pad_r_ = convg_primitive->GetPadRight(); | |||
| param->group_ = convg_primitive->GetGroup(); | |||
| param->act_type_ = ActType_No; | |||
| switch (convg_primitive->GetActivationType()) { | |||
| case schema::ActivationType_RELU: | |||
| param->act_type_ = ActType_Relu; | |||
| break; | |||
| case schema::ActivationType_RELU6: | |||
| param->act_type_ = ActType_Relu6; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| return reinterpret_cast<OpParameter *>(param); | |||
| } | |||
| OpParameter *PopulatePowerGradParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| PowerParameter *power_param = reinterpret_cast<PowerParameter *>(malloc(sizeof(PowerParameter))); | |||
| if (power_param == nullptr) { | |||
| MS_LOG(ERROR) << "new PowerParameter failed."; | |||
| return nullptr; | |||
| } | |||
| power_param->op_parameter_.type_ = primitive->Type(); | |||
| auto power = reinterpret_cast<mindspore::lite::PowerGrad *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| power_param->power_ = power->GetPower(); | |||
| power_param->scale_ = power->GetScale(); | |||
| power_param->shift_ = power->GetShift(); | |||
| return reinterpret_cast<OpParameter *>(power_param); | |||
| } | |||
| OpParameter *PopulateBiasGradParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| ArithmeticParameter *arithmetic_param = reinterpret_cast<ArithmeticParameter *>(malloc(sizeof(ArithmeticParameter))); | |||
| if (arithmetic_param == nullptr) { | |||
| MS_LOG(ERROR) << "new ArithmeticParameter failed."; | |||
| return nullptr; | |||
| } | |||
| arithmetic_param->op_parameter_.type_ = primitive->Type(); | |||
| return reinterpret_cast<OpParameter *>(arithmetic_param); | |||
| } | |||
| OpParameter *PopulateBNGradParameter(const mindspore::lite::PrimitiveC *primitive) { | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "Primitive is nullptr when populating parameter for op."; | |||
| return nullptr; | |||
| } | |||
| BNGradParameter *bnGrad_param = reinterpret_cast<BNGradParameter *>(malloc(sizeof(BNGradParameter))); | |||
| if (bnGrad_param == nullptr) { | |||
| MS_LOG(ERROR) << "new BNGradParameter failed."; | |||
| return nullptr; | |||
| } | |||
| bnGrad_param->op_parameter_.type_ = primitive->Type(); | |||
| auto bngrad = reinterpret_cast<mindspore::lite::BNGrad *>(const_cast<mindspore::lite::PrimitiveC *>(primitive)); | |||
| bnGrad_param->epsilon_ = bngrad->GetEps(); | |||
| bnGrad_param->momentum_ = 0.1; | |||
| return reinterpret_cast<OpParameter *>(bnGrad_param); | |||
| } | |||
| void PopulateTrainParameters() { | |||
| lite::Registry ApplyMomentumParameterRegistry(schema::PrimitiveType_ApplyMomentum, PopulateApplyMomentumParameter); | |||
| lite::Registry BiasGradParameterRegistry(schema::PrimitiveType_BiasGrad, PopulateBiasGradParameter); | |||
| lite::Registry SoftmaxCrossEntropyParameterRegistry(schema::PrimitiveType_SoftmaxCrossEntropy, | |||
| PopulateSoftmaxCrossEntropyParameter); | |||
| lite::Registry ActivationParameterRegistry(schema::PrimitiveType_ActivationGrad, PopulateActivationGradParameter); | |||
| lite::Registry TupleGetItemParameterRegistry(schema::PrimitiveType_TupleGetItem, DefaultPopulateParameter); | |||
| lite::Registry DependParameterRegistry(schema::PrimitiveType_Depend, DefaultPopulateParameter); | |||
| lite::Registry Conv2DGradFilterParameterRegistry(schema::PrimitiveType_Conv2DGradFilter, | |||
| PopulateConvolutionGradFilterParameter); | |||
| lite::Registry Conv2DGradInputParameterRegistry(schema::PrimitiveType_Conv2DGradInput, | |||
| PopulateConvolutionGradInputParameter); | |||
| lite::Registry GroupConv2DGradInputParameterRegistry(schema::PrimitiveType_GroupConv2DGradInput, | |||
| PopulateGroupConvolutionGradInputParameter); | |||
| lite::Registry PoolingParameterRegistry(schema::PrimitiveType_PoolingGrad, PopulatePoolingGradParameter); | |||
| lite::Registry PowerGradParameterRegistry(schema::PrimitiveType_PowerGrad, PopulatePowerGradParameter); | |||
| lite::Registry SgdParameterRegistry(schema::PrimitiveType_Sgd, PopulateSgdParameter); | |||
| lite::Registry BNGradParameterRegistry(schema::PrimitiveType_BNGrad, PopulateBNGradParameter); | |||
| lite::Registry AdamParameterRegistry(schema::PrimitiveType_Adam, PopulateAdamParameter); | |||
| lite::Registry AssignParameterRegistry(schema::PrimitiveType_Assign, DefaultPopulateParameter); | |||
| lite::Registry AssignAddParameterRegistry(schema::PrimitiveType_AssignAdd, DefaultPopulateParameter); | |||
| lite::Registry BinaryCrossEntropyParameterRegistry(schema::PrimitiveType_BinaryCrossEntropy, PopulateBCEParameter); | |||
| lite::Registry BinaryCrossEntropyGradParameterRegistry(schema::PrimitiveType_BinaryCrossEntropyGrad, | |||
| PopulateBCEGradParameter); | |||
| lite::Registry OnesLikeParameterRegistry(schema::PrimitiveType_OnesLike, DefaultPopulateParameter); | |||
| lite::Registry UnsortedSegmentSumParameterRegistry(schema::PrimitiveType_UnsortedSegmentSum, | |||
| DefaultPopulateParameter); | |||
| } | |||
| } // namespace mindspore::kernel | |||
| @@ -1,27 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_TRAIN_TRAIN_POPULATE_PARAMETER_H_ | |||
| #define MINDSPORE_LITE_SRC_TRAIN_TRAIN_POPULATE_PARAMETER_H_ | |||
| #include "src/ops/primitive_c.h" | |||
| namespace mindspore::kernel { | |||
| void PopulateTrainParameters(); | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_TRAIN_TRAIN_POPULATE_PARAMETER_H_ | |||
| @@ -1,292 +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/train/train_session.h" | |||
| #include <algorithm> | |||
| #include <utility> | |||
| #include <vector> | |||
| #include "include/errorcode.h" | |||
| #include "include/train_model.h" | |||
| #include "src/common/utils.h" | |||
| #include "src/tensor.h" | |||
| #include "src/train/loss_kernel.h" | |||
| #include "src/sub_graph_kernel.h" | |||
| #include "src/train/train_populate_parameter.h" | |||
| #include "src/runtime/runtime_api.h" | |||
| #include "src/executor.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "src/runtime/kernel/arm/fp32_grad/convolution.h" | |||
| namespace mindspore { | |||
| namespace lite { | |||
| static size_t TSFindTensor(const std::vector<lite::Tensor *> &where, const lite::Tensor *searchParameter) { | |||
| for (size_t i = 0; i < where.size(); i++) { | |||
| if (where[i] == searchParameter) { | |||
| return i; | |||
| } | |||
| } | |||
| return where.size(); | |||
| } | |||
| TrainSession::TrainSession() { kernel::PopulateTrainParameters(); } | |||
| std::vector<CreatorOp> TrainSession::ReplaceOps() { | |||
| const std::vector<CreatorOp> replace = { | |||
| {{mindspore::kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, mindspore::schema::PrimitiveType_Conv2D}, | |||
| mindspore::kernel::CpuConvTrainFp32KernelCreator}, | |||
| {{mindspore::kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, mindspore::schema::PrimitiveType_DepthwiseConv2D}, | |||
| mindspore::kernel::CpuConvTrainFp32KernelCreator}}; | |||
| mindspore::lite::KernelRegistry *reg = mindspore::lite::KernelRegistry::GetInstance(); | |||
| std::vector<CreatorOp> results; | |||
| for (auto v : replace) { | |||
| const CreatorOp cl = make_tuple(std::get<0>(v), reg->GetCreator(std::get<0>(v))); | |||
| results.push_back(cl); | |||
| reg->RegKernel(std::get<0>(v), std::get<1>(v)); | |||
| } | |||
| return results; | |||
| } | |||
| void TrainSession::RestoreOps(const std::vector<CreatorOp> &restore) { | |||
| mindspore::lite::KernelRegistry *reg = mindspore::lite::KernelRegistry::GetInstance(); | |||
| for (auto v : restore) { | |||
| reg->RegKernel(std::get<0>(v), std::get<1>(v)); | |||
| } | |||
| } | |||
| void TrainSession::AllocWorkSpace() { | |||
| size_t workspace_size = 0; | |||
| for (auto ori_kernel : kernels_) { | |||
| if (ori_kernel->subgraph_type() == kernel::kNotSubGraph) { | |||
| if (workspace_size < ori_kernel->GetWorkspaceSize()) { | |||
| workspace_size = ori_kernel->GetWorkspaceSize(); | |||
| } | |||
| } else { | |||
| auto sub_graph = reinterpret_cast<kernel::SubGraphKernel *>(ori_kernel); | |||
| for (auto kernel : sub_graph->nodes()) { | |||
| if (workspace_size < kernel->GetWorkspaceSize()) { | |||
| workspace_size = kernel->GetWorkspaceSize(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(workspace_size); | |||
| } | |||
| int TrainSession::CompileGraph(lite::Model *model) { return lite::RET_ERROR; } | |||
| int TrainSession::CompileTrainGraph(mindspore::lite::TrainModel *model) { | |||
| model_ = model; | |||
| auto restore = ReplaceOps(); | |||
| auto ret = lite::LiteSession::CompileGraph(model); | |||
| orig_output_map_ = output_node_map_; | |||
| orig_output_tensor_map_ = output_tensor_map_; | |||
| for (auto inTensor : inputs_) inTensor->MutableData(); | |||
| RestoreOps(restore); | |||
| AllocWorkSpace(); | |||
| return ret; | |||
| } | |||
| TrainSession::~TrainSession() { | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| delete model_; | |||
| } | |||
| void *TrainSession::ExportToBuf(char *buf, size_t *len) const { return model_->ExportBuf(buf, len); } | |||
| int TrainSession::RunGraph(const KernelCallBack &before, const KernelCallBack &after) { | |||
| this->outputs_.clear(); | |||
| for (auto ms_tensors : output_node_map_) | |||
| for (auto ms_tensor : ms_tensors.second) this->outputs_.push_back((static_cast<lite::Tensor *>(ms_tensor))); | |||
| if (train_mode_) return lite::LiteSession::RunGraph(before, after); | |||
| if (this->context_ == nullptr) { | |||
| MS_LOG(ERROR) << "context is null"; | |||
| return lite::RET_NULL_PTR; | |||
| } | |||
| lite::Executor executor; | |||
| if (before == nullptr && after == nullptr) { | |||
| return executor.Run(this->inputs_, this->outputs_, inference_kernels_, this->context_->allocator.get()); | |||
| } else { | |||
| return executor.Run(this->inputs_, this->outputs_, inference_kernels_, this->context_->allocator.get(), before, | |||
| after); | |||
| } | |||
| } | |||
| void TrainSession::Train() { | |||
| for (auto ori_kernel : kernels_) { | |||
| MS_ASSERT(nullptr != ori_kernel); | |||
| if (ori_kernel->subgraph_type() == kernel::kNotSubGraph) { | |||
| ori_kernel->train(); | |||
| } else { | |||
| auto sub_graph = reinterpret_cast<kernel::SubGraphKernel *>(ori_kernel); | |||
| MS_ASSERT(nullptr != sub_graph); | |||
| for (auto kernel : sub_graph->nodes()) { | |||
| MS_ASSERT(nullptr != kernel); | |||
| kernel->train(); | |||
| } | |||
| } | |||
| } | |||
| output_node_map_.clear(); | |||
| output_tensor_map_.clear(); | |||
| train_mode_ = true; | |||
| for (auto ori_kernel : kernels_) { | |||
| MS_ASSERT(nullptr != ori_kernel); | |||
| if (ori_kernel->subgraph_type() == kernel::kNotSubGraph) { | |||
| UpdateOutputMapByLossKernel(ori_kernel); | |||
| } else { | |||
| auto sub_graph = reinterpret_cast<kernel::SubGraphKernel *>(ori_kernel); | |||
| MS_ASSERT(nullptr != sub_graph); | |||
| for (auto kernel : sub_graph->nodes()) { | |||
| MS_ASSERT(nullptr != kernel); | |||
| UpdateOutputMapByLossKernel(kernel); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void TrainSession::UpdateOutputMapByLossKernel(const kernel::LiteKernel *kernel) { | |||
| if (IsLossKernel(kernel)) { | |||
| auto *ms_tensor = kernel->out_tensors().at(0); | |||
| if (ms_tensor != nullptr) { | |||
| (void)ms_tensor->MutableData(); | |||
| output_node_map_[kernel->name()].emplace_back(ms_tensor); | |||
| auto index = TSFindTensor(tensors_, ms_tensor); | |||
| if (index != tensors_.size()) { | |||
| output_tensor_map_.insert(std::make_pair(std::to_string(index), ms_tensor)); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void TrainSession::UpdateOutputMapByInKernel(const kernel::LiteKernel *kernel) { | |||
| if (IsLossKernel(kernel)) { | |||
| for (auto in_kernel : kernel->in_kernels()) { | |||
| if (output_node_map_.find(in_kernel->name()) == output_node_map_.end()) { | |||
| auto *ms_tensor = in_kernel->out_tensors().at(0); | |||
| if (ms_tensor != nullptr) { | |||
| output_node_map_[in_kernel->name()].emplace_back(ms_tensor); | |||
| auto index = TSFindTensor(tensors_, ms_tensor); | |||
| if (index != tensors_.size()) { | |||
| output_tensor_map_.insert(std::make_pair(std::to_string(index), ms_tensor)); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void TrainSession::Eval() { | |||
| for (auto ori_kernel : kernels_) { | |||
| MS_ASSERT(nullptr != ori_kernel); | |||
| if (ori_kernel->subgraph_type() == kernel::kNotSubGraph) { | |||
| ori_kernel->eval(); | |||
| } else { | |||
| auto sub_graph = reinterpret_cast<kernel::SubGraphKernel *>(ori_kernel); | |||
| MS_ASSERT(nullptr != sub_graph); | |||
| for (auto kernel : sub_graph->nodes()) { | |||
| MS_ASSERT(nullptr != kernel); | |||
| kernel->eval(); | |||
| } | |||
| } | |||
| } | |||
| output_node_map_ = orig_output_map_; | |||
| output_tensor_map_ = orig_output_tensor_map_; | |||
| train_mode_ = false; | |||
| for (auto ori_kernel : kernels_) { | |||
| if (ori_kernel->subgraph_type() == kernel::kNotSubGraph) { | |||
| UpdateOutputMapByInKernel(ori_kernel); | |||
| } else { | |||
| auto sub_graph = reinterpret_cast<kernel::SubGraphKernel *>(ori_kernel); | |||
| for (auto kernel : sub_graph->nodes()) { | |||
| UpdateOutputMapByInKernel(kernel); | |||
| } | |||
| } | |||
| } | |||
| if (inference_kernels_.size() == 0) { | |||
| BuildInferenceKernelsMap(); | |||
| } | |||
| } | |||
| void TrainSession::BuildInferenceKernelsRecursive(kernel::LiteKernel *kernel, std::vector<kernel::LiteKernel *> *v) { | |||
| if (std::find(v->begin(), v->end(), kernel) == v->end()) { // kernel is not in vector | |||
| v->push_back(kernel); | |||
| for (auto in_node : kernel->in_kernels()) { | |||
| BuildInferenceKernelsRecursive(in_node, v); | |||
| } | |||
| } | |||
| } | |||
| void TrainSession::BuildInferenceKernelsMap() { | |||
| std::vector<kernel::LiteKernel *> req_kernels; | |||
| for (auto ori_kernel : kernels_) { | |||
| if (ori_kernel->subgraph_type() == kernel::kNotSubGraph) { | |||
| if (IsLossKernel(ori_kernel)) { // For each loss in the system add backward tree | |||
| for (auto in_node : ori_kernel->in_kernels()) { | |||
| BuildInferenceKernelsRecursive(in_node, &req_kernels); | |||
| } | |||
| } | |||
| } else { | |||
| auto sub_graph = reinterpret_cast<kernel::SubGraphKernel *>(ori_kernel); | |||
| for (auto kernel : sub_graph->nodes()) { | |||
| if (IsLossKernel(kernel)) { // For each loss in the system add backward tree | |||
| for (auto in_node : kernel->in_kernels()) { | |||
| BuildInferenceKernelsRecursive(in_node, &req_kernels); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| inference_kernels_.clear(); | |||
| for (auto ori_kernel : kernels_) { | |||
| if (ori_kernel->subgraph_type() == kernel::kNotSubGraph) { | |||
| if (std::find(req_kernels.begin(), req_kernels.end(), ori_kernel) != req_kernels.end()) { | |||
| inference_kernels_.push_back(ori_kernel); | |||
| } | |||
| } else { | |||
| auto sub_graph = reinterpret_cast<kernel::SubGraphKernel *>(ori_kernel); | |||
| for (auto kernel : sub_graph->nodes()) { | |||
| if (std::find(req_kernels.begin(), req_kernels.end(), kernel) != req_kernels.end()) { | |||
| inference_kernels_.push_back(kernel); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| if (inference_kernels_.size() == 0) { | |||
| inference_kernels_ = this->kernels_; | |||
| } | |||
| } | |||
| bool TrainSession::IsLossKernel(const kernel::LiteKernel *kernel) { | |||
| return (kernel->Type() == schema::PrimitiveType_SoftmaxCrossEntropy); | |||
| } | |||
| } // namespace lite | |||
| session::TrainSession *session::TrainSession::CreateSession(lite::Context *context) { | |||
| auto session = new lite::TrainSession(); | |||
| auto ret = session->Init(context); | |||
| if (ret != mindspore::lite::RET_OK) { | |||
| MS_LOG(ERROR) << "init sesssion failed"; | |||
| delete session; | |||
| return nullptr; | |||
| } | |||
| return session; | |||
| } | |||
| } // namespace mindspore | |||
| @@ -1,100 +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. | |||
| */ | |||
| #ifndef MINDSPORE_LITE_SRC_TRAIN_TRAIN_SESSION_H_ | |||
| #define MINDSPORE_LITE_SRC_TRAIN_TRAIN_SESSION_H_ | |||
| #include <vector> | |||
| #include <string> | |||
| #include <tuple> | |||
| #include <unordered_map> | |||
| #include "src/ops/primitive_c.h" | |||
| #include "include/train_session.h" | |||
| #include "include/train_model.h" | |||
| #include "src/lite_session.h" | |||
| /* | |||
| Inheritance Diagram | |||
| +-------------------------------+ | |||
| | session::LiteSession | | |||
| +--------+------------+---------+ | |||
| / \ | |||
| +-----------------+-----+ +-------+------------+ | |||
| | session::TrainSession | | lite::LiteSession | | |||
| +-----------------+-----+ +-------+------------+ | |||
| \ / | |||
| +--------+------------+---------+ | |||
| | lite::TrainSession | | |||
| +-------------------------------+ | |||
| */ | |||
| namespace mindspore { | |||
| namespace lite { | |||
| using CreatorOp = std::tuple<mindspore::kernel::KernelKey, mindspore::kernel::KernelCreator>; | |||
| class TrainSession : virtual public session::TrainSession, virtual public lite::LiteSession { | |||
| public: | |||
| TrainSession(); | |||
| ~TrainSession(); | |||
| int RunGraph(const KernelCallBack &before = nullptr, const KernelCallBack &after = nullptr) override; | |||
| int CompileGraph(lite::Model *model) override; | |||
| int CompileTrainGraph(lite::TrainModel *model) override; | |||
| void *ExportToBuf(char *buf, size_t *len) const override; | |||
| void Train() override; | |||
| void Eval() override; | |||
| void BindThread(bool if_bind) override { return lite::LiteSession::BindThread(if_bind); } | |||
| std::vector<tensor::MSTensor *> GetInputs() const override { return lite::LiteSession::GetInputs(); } | |||
| mindspore::tensor::MSTensor *GetInputsByTensorName(const std::string &tensor_name) const override { | |||
| return lite::LiteSession::GetInputsByTensorName(tensor_name); | |||
| } | |||
| std::vector<tensor::MSTensor *> GetOutputsByNodeName(const std::string &node_name) const override { | |||
| return lite::LiteSession::GetOutputsByNodeName(node_name); | |||
| } | |||
| std::unordered_map<std::string, mindspore::tensor::MSTensor *> GetOutputs() const override { | |||
| return lite::LiteSession::GetOutputs(); | |||
| } | |||
| std::vector<std::string> GetOutputTensorNames() const override { return lite::LiteSession::GetOutputTensorNames(); } | |||
| mindspore::tensor::MSTensor *GetOutputByTensorName(const std::string &tensor_name) const override { | |||
| return lite::LiteSession::GetOutputByTensorName(tensor_name); | |||
| } | |||
| int Resize(const std::vector<tensor::MSTensor *> &inputs, const std::vector<std::vector<int>> &dims) override { | |||
| return lite::LiteSession::Resize(inputs, dims); | |||
| } | |||
| void UpdateOutputMapByInKernel(const kernel::LiteKernel *kernel); | |||
| void UpdateOutputMapByLossKernel(const kernel::LiteKernel *kernel); | |||
| protected: | |||
| void AllocWorkSpace(); | |||
| bool IsLossKernel(const kernel::LiteKernel *kernel); | |||
| virtual std::vector<CreatorOp> ReplaceOps(); | |||
| virtual void RestoreOps(const std::vector<CreatorOp> &restore); | |||
| virtual void BuildInferenceKernelsMap(); | |||
| virtual void BuildInferenceKernelsRecursive(kernel::LiteKernel *ker, std::vector<kernel::LiteKernel *> *req_kernels); | |||
| TrainModel *model_ = nullptr; | |||
| std::unordered_map<std::string, std::vector<mindspore::tensor::MSTensor *>> orig_output_map_; | |||
| std::unordered_map<std::string, mindspore::tensor::MSTensor *> orig_output_tensor_map_; | |||
| std::vector<kernel::LiteKernel *> inference_kernels_; | |||
| }; | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| #endif // MINDSPORE_LITE_SRC_TRAIN_TRAIN_SESSION_H_ | |||
| @@ -214,10 +214,6 @@ endif() | |||
| if (SUPPORT_TRAIN) | |||
| set(TEST_LITE_SRC | |||
| ${TEST_LITE_SRC} | |||
| # ${LITE_DIR}/src/train/ops/train_ops.cc | |||
| ${LITE_DIR}/src/train/train_populate_parameter.cc | |||
| ${LITE_DIR}/src/train/train_session.cc | |||
| ${LITE_DIR}/src/train/train_model.cc | |||
| ${LITE_DIR}/src/lite_session.cc | |||
| ) | |||
| else() | |||
| @@ -58,7 +58,7 @@ inception_resnet_v2.tflite | |||
| ml_ocr_latin.tflite | |||
| hiai_PoseEstimation_Pcm.tflite | |||
| hiai_ssd_mobilenetv2_object.tflite | |||
| hiai_cv_focusShootOCRModel_02.tflite | |||
| #hiai_cv_focusShootOCRModel_02.tflite | |||
| hiai_cv_poseEstimation.tflite | |||
| inception_v4.tflite | |||
| mtk_model_normalize_object_scene_ps_20200519_f16.tflite | |||
| @@ -1,5 +1 @@ | |||
| #!/bin/bash | |||
| cd ./ut/src/runtime/kernel/arm || exit 1 | |||
| ../../../../../../build/test/lite-test --gtest_filter=NetworkTest.efficient_net | |||
| ../../../../../../build/test/lite-test --gtest_filter=NetworkTest.tuning_layer | |||
| ../../../../../../build/test/lite-test --gtest_filter=NetworkTest.lenetnet | |||
| #!/bin/bash | |||
| @@ -1,316 +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 <iostream> | |||
| #include <memory> | |||
| #include <vector> | |||
| #include <algorithm> | |||
| #include "src/common/log_adapter.h" | |||
| #include "common/common_test.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/common/file_utils_ext.h" | |||
| #include "mindspore/lite/src/kernel_registry.h" | |||
| #include "mindspore/lite/src/tensor.h" | |||
| #include "mindspore/lite/src/lite_kernel.h" | |||
| #include "mindspore/lite/src/runtime/kernel/arm/fp32_grad/activation_grad.h" | |||
| #include "nnacl/fp32_grad/activation_grad.h" | |||
| namespace mindspore { | |||
| class TestActGradFp32 : public mindspore::CommonTest { | |||
| public: | |||
| TestActGradFp32() {} | |||
| }; | |||
| TEST_F(TestActGradFp32, ReluGradFp32) { | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = 50; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/activationGrad/relu_y_50.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| EXPECT_EQ(input_size, output_data_size * sizeof(float)); | |||
| std::string yt_path = "./test_data/activationGrad/relu_yt_50.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| EXPECT_EQ(input_size, output_data_size * sizeof(float)); | |||
| auto output_data = new float[output_data_size]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| ReluGrad(yt_data, input_data, output_data_size, output_data); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| ReluGrad(yt_data, input_data, 50, output_data); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 20; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/activationGrad/relu_out_50.bin"; | |||
| int res = lite::CompareRelativeOutput(output_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] output_data; | |||
| delete[] yt_data; | |||
| MS_LOG(INFO) << "ReluGradFp32 passed"; | |||
| } | |||
| TEST_F(TestActGradFp32, Relu6GradFp32) { | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = 50; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/activationGrad/relu6_y_50.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::string yt_path = "./test_data/activationGrad/relu6_yt_50.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| auto output_data = new float[output_data_size]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| Relu6Grad(yt_data, input_data, 50, output_data); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| Relu6Grad(yt_data, input_data, 50, output_data); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 20; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/activationGrad/relu6_out_50.bin"; | |||
| int res = lite::CompareRelativeOutput(output_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] output_data; | |||
| delete[] yt_data; | |||
| MS_LOG(INFO) << "Relu6GradFp32 passed"; | |||
| } | |||
| TEST_F(TestActGradFp32, LReluGradFp32) { | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = 50; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/activationGrad/lrelu_y_50.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::string yt_path = "./test_data/activationGrad/lrelu_yt_50.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| auto output_data = new float[output_data_size]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| LReluGrad(yt_data, input_data, 50, output_data, 0.1); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| LReluGrad(yt_data, input_data, 50, output_data, 0.1); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 20; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/activationGrad/lrelu_out_50.bin"; | |||
| int res = lite::CompareRelativeOutput(output_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] output_data; | |||
| delete[] yt_data; | |||
| MS_LOG(INFO) << "LReluGradFp32 passed"; | |||
| } | |||
| TEST_F(TestActGradFp32, SigmoidGradFp32) { | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = 50; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/activationGrad/sigmoid_y_50.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::string yt_path = "./test_data/activationGrad/sigmoid_yt_50.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| auto output_data = new float[output_data_size]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| SigmoidGrad(yt_data, input_data, 50, output_data); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| SigmoidGrad(yt_data, input_data, 50, output_data); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 20; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/activationGrad/sigmoid_out_50.bin"; | |||
| int res = lite::CompareRelativeOutput(output_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| // lite::CompareOutput(output_data, output_data_size, output_path); | |||
| delete[] input_data; | |||
| delete[] output_data; | |||
| delete[] yt_data; | |||
| MS_LOG(INFO) << "SigmoidGradFp32 passed"; | |||
| } | |||
| TEST_F(TestActGradFp32, tanhGradFp32) { | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = 50; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/activationGrad/tanh_y_50.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::string yt_path = "./test_data/activationGrad/tanh_yt_50.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| auto output_data = new float[output_data_size]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| TanhGrad(yt_data, input_data, 50, output_data); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| TanhGrad(yt_data, input_data, 50, output_data); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 20; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/activationGrad/tanh_out_50.bin"; | |||
| int res = lite::CompareRelativeOutput(output_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] output_data; | |||
| delete[] yt_data; | |||
| MS_LOG(INFO) << "TanhGradFp32 passed"; | |||
| } | |||
| TEST_F(TestActGradFp32, hswishGradFp32) { | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| const size_t output_data_size = 10; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/activationGrad/hswish_x_50.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| EXPECT_EQ(input_size, output_data_size * sizeof(float)); | |||
| std::string yt_path = "./test_data/activationGrad/hswish_yt_50.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| EXPECT_EQ(input_size, output_data_size * sizeof(float)); | |||
| auto output_data = new float[output_data_size]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| HSwishGrad(yt_data, input_data, static_cast<int>(output_data_size), output_data); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| HSwishGrad(yt_data, input_data, output_data_size, output_data); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| printf("==================output data=================\n"); | |||
| size_t min = (output_data_size < 20UL) ? output_data_size : 20UL; | |||
| for (size_t i = 0; i < min; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/activationGrad/hswish_out_50.bin"; | |||
| int res = lite::CompareRelativeOutput(output_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] output_data; | |||
| delete[] yt_data; | |||
| MS_LOG(INFO) << "hswishGradFp32 passed"; | |||
| } | |||
| } // namespace mindspore | |||
| @@ -1,636 +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 <iostream> | |||
| #include <memory> | |||
| #include <vector> | |||
| #include "src/common/log_adapter.h" | |||
| #include "common/common_test.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/common/file_utils_ext.h" | |||
| #include "nnacl/fp32/reduce.h" | |||
| #include "src/runtime/kernel/arm/fp32_grad/arithmetic_grad.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "src/ops/arithmetic_grad.h" | |||
| #ifdef PRIMITIVE_WRITEABLE | |||
| namespace mindspore { | |||
| ArithmeticParameter *PopulateArithmeticParameter(mindspore::schema::PrimitiveType type, | |||
| std::vector<lite::Tensor *> inputs, | |||
| std::vector<lite::Tensor *> outputs) { | |||
| ArithmeticParameter *arithmetic_param = static_cast<ArithmeticParameter *>(malloc(sizeof(ArithmeticParameter))); | |||
| if (arithmetic_param == nullptr) { | |||
| MS_LOG(ERROR) << "new ArithmeticParameter failed."; | |||
| return nullptr; | |||
| } | |||
| arithmetic_param->op_parameter_.type_ = type; | |||
| schema::PrimitiveT *prim = new schema::PrimitiveT; | |||
| prim->value.type = type; | |||
| auto agrad = mindspore::lite::ArithmeticGrad(prim); | |||
| agrad.InferShape(inputs, outputs); | |||
| arithmetic_param->ndim_ = agrad.NDims(); | |||
| for (size_t i = 0; i < agrad.dyShape().size(); i++) arithmetic_param->out_shape_[i] = (agrad.dyShape())[i]; | |||
| for (size_t i = 0; i < agrad.x1Shape().size(); i++) arithmetic_param->in_shape0_[i] = (agrad.x1Shape())[i]; | |||
| for (size_t i = 0; i < agrad.x2Shape().size(); i++) arithmetic_param->in_shape1_[i] = (agrad.x2Shape())[i]; | |||
| return arithmetic_param; | |||
| } | |||
| class TestArithmeticGradFp32 : public mindspore::CommonTest { | |||
| public: | |||
| TestArithmeticGradFp32() {} | |||
| }; | |||
| std::vector<lite::Tensor *> GenerateTensorsForTest(const char *test, int test_id) { | |||
| size_t input_size; | |||
| std::vector<int> large_dim({4, 6}); | |||
| std::vector<int> small_dim({6}); | |||
| int large_size = (4 * 6); | |||
| int small_size = (1 * 6); | |||
| char *dx1_file = const_cast<char *>("./test_data/operators/arithmetic_fp32_1_x1_4_6.bin"); | |||
| char *dx2_file = const_cast<char *>("./test_data/operators/arithmetic_fp32_1_x2_1_6.bin"); | |||
| if (test_id == 7) { | |||
| large_dim = std::vector<int>({4, 5, 6}); | |||
| small_dim = std::vector<int>({6}); | |||
| large_size = (4 * 5 * 6); | |||
| small_size = (6); | |||
| dx1_file = const_cast<char *>("./test_data/operators/arithmetic_fp32_7_x1_4_5_6.bin"); | |||
| dx2_file = const_cast<char *>("./test_data/operators/arithmetic_fp32_7_x2_1_1_6.bin"); | |||
| } | |||
| if (test_id >= 8) { | |||
| large_dim = std::vector<int>({5, 4, 6}); | |||
| small_dim = std::vector<int>({5, 1, 6}); | |||
| large_size = (4 * 5 * 6); | |||
| small_size = (5 * 6); | |||
| dx1_file = const_cast<char *>("./test_data/operators/arithmetic_fp32_8_x1_5_4_6.bin"); | |||
| dx2_file = const_cast<char *>("./test_data/operators/arithmetic_fp32_8_x2_5_1_6.bin"); | |||
| } | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(test, &input_size)); | |||
| lite::Tensor *dy_tensor = new lite::Tensor(TypeId::kNumberTypeFloat32, large_dim); | |||
| dy_tensor->set_data(dy_data); | |||
| auto x1_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dx1_file, &input_size)); | |||
| lite::Tensor *x1_tensor = new lite::Tensor(TypeId::kNumberTypeFloat32, large_dim); | |||
| x1_tensor->set_data(x1_data); | |||
| auto x2_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dx2_file, &input_size)); | |||
| lite::Tensor *x2_tensor = new lite::Tensor(TypeId::kNumberTypeFloat32, small_dim); | |||
| x2_tensor->set_data(x2_data); | |||
| auto dx1_data = new float[large_size]; | |||
| lite::Tensor *dx1_tensor = new lite::Tensor(TypeId::kNumberTypeFloat32, large_dim); | |||
| dx1_tensor->set_data(dx1_data); | |||
| auto dx2_data = new float[small_size]; | |||
| lite::Tensor *dx2_tensor = new lite::Tensor(TypeId::kNumberTypeFloat32, small_dim); | |||
| dx2_tensor->set_data(dx2_data); | |||
| std::vector<lite::Tensor *> ret_vector = {dy_tensor, x1_tensor, x2_tensor, dx1_tensor, dx2_tensor}; | |||
| return ret_vector; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestAddGradFp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_1_dy_4_6.bin", 1); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[1], all_tensors[2]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[3], all_tensors[4]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_AddGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_AddGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[1]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_1_dx1_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[0]->MutableData()), output_path)); | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_1_dx2_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, dx2_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestAddGradFp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestAddGrad2Fp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_1_dy_4_6.bin", 1); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[2], all_tensors[1]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[4], all_tensors[3]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_AddGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_AddGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[0]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_1_dx1_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[1]->MutableData()), output_path)); | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_1_dx2_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, dx2_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| // for (int i = 0; i < 5; i++) delete all_tensors[i]; //TODO tensor data is unique pointer | |||
| // delete param; | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestAddGrad2Fp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestAddGrad3Fp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_8_dy_5_4_6.bin", 8); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[1], all_tensors[2]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[3], all_tensors[4]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_AddGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_AddGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[0]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_8_dx2_5_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[1]->MutableData()), output_path)); | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_8_dx1_5_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, dx2_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| // for (int i = 0; i < 5; i++) delete all_tensors[i]; | |||
| // delete param; | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestAddGrad3Fp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestSubGradFp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_2_dy_4_6.bin", 2); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[1], all_tensors[2]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[3], all_tensors[4]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_SubGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_SubGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[1]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_2_dx1_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[0]->MutableData()), output_path)); | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_2_dx2_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, dx2_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| // for (int i = 0; i < 5; i++) delete all_tensors[i]; | |||
| // delete param; | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestSubGradFp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestSubGrad2Fp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_3_dy_4_6.bin", 3); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[2], all_tensors[1]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[4], all_tensors[3]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_SubGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_SubGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[0]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_3_dx1_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[1]->MutableData()), output_path)); | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_3_dx2_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, dx2_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestSubGrad2Fp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestMulGradFp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_4_dy_4_6.bin", 4); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[1], all_tensors[2]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[3], all_tensors[4]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_MulGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_MulGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| int loop_count = 1000; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel_obj->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| printf("total cost (for %d loops): %lu us\n", loop_count, cost); | |||
| // auto time_avg = cost / loop_count; | |||
| // printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[1]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_4_dx1_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[0]->MutableData()), output_path)); | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_4_dx2_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, dx2_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| delete kernel_obj; | |||
| // delete param; | |||
| MS_LOG(INFO) << "TestMulGradFp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestMulGrad2Fp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_4_dy_4_6.bin", 4); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[2], all_tensors[1]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[4], all_tensors[3]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_MulGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_MulGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[0]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_4_dx1_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[1]->MutableData()), output_path)); | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_4_dx2_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, dx2_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| // for (int i = 0; i < 5; i++) delete all_tensors[i]; | |||
| // delete param; | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestMulGrad2Fp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestMulGrad3Fp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_9_dy_5_4_6.bin", 9); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[1], all_tensors[2]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[3], all_tensors[4]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_MulGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_MulGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[1]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_9_dx1_5_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[0]->MutableData()), output_path)); | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_9_dx2_5_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, dx2_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| // for (int i = 0; i < 5; i++) delete all_tensors[i]; | |||
| // delete param; | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestMulGrad3Fp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestMulGrad4Fp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_9_dy_5_4_6.bin", 9); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[2], all_tensors[1]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[4], all_tensors[3]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_MulGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_MulGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[0]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_9_dx1_5_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[1]->MutableData()), output_path)); | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_9_dx2_5_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, dx2_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| // for (int i = 0; i < 5; i++) delete all_tensors[i]; | |||
| // delete param; | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestMulGrad4Fp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestDivGradFp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_5_dy_4_6.bin", 5); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[1], all_tensors[2]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[3], all_tensors[4]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_DivGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_DivGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[1]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_5_dx1_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[0]->MutableData()), output_path)); | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_5_dx2_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, dx2_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| // for (int i = 0; i < 5; i++) delete all_tensors[i]; | |||
| delete kernel_obj; | |||
| // delete param; | |||
| MS_LOG(INFO) << "TestDivGradFp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestDivGrad2Fp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_6_dy_4_6.bin", 6); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[2], all_tensors[1]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[4], all_tensors[3]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_DivGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_DivGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[0]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string dx2_path = "./test_data/operators/arithmetic_fp32_6_dx2_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[1]->MutableData()), dx2_path)); | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_6_dx1_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, output_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| // for (int i = 0; i < 5; i++) delete all_tensors[i]; | |||
| // delete param; | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestDivGrad2Fp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, TestDivGrad3Fp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_10_dy_5_4_6.bin", 10); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[1], all_tensors[2]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[3], all_tensors[4]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_DivGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_DivGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[1]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string dx1_path = "./test_data/operators/arithmetic_fp32_10_dx1_5_4_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[0]->MutableData()), dx1_path)); | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_10_dx2_5_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, output_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| // for (int i = 0; i < 5; i++) delete all_tensors[i]; | |||
| // delete param; | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestDivGrad3Fp32 passed"; | |||
| } | |||
| TEST_F(TestArithmeticGradFp32, Test3DDivGrad2Fp32) { | |||
| std::vector<lite::Tensor *> all_tensors = | |||
| GenerateTensorsForTest("./test_data/operators/arithmetic_fp32_7_dy_4_5_6.bin", 7); | |||
| std::vector<lite::Tensor *> inputs = {all_tensors[0], all_tensors[1], all_tensors[2]}; | |||
| std::vector<lite::Tensor *> outputs = {all_tensors[3], all_tensors[4]}; | |||
| auto param = PopulateArithmeticParameter(schema::PrimitiveType_DivGrad, inputs, outputs); | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_DivGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| float *output_ptr = reinterpret_cast<float *>(outputs[1]->MutableData()); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 6; i++) { | |||
| std::cout << output_ptr[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string dx1_path = "./test_data/operators/arithmetic_fp32_7_dx1_4_5_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(reinterpret_cast<float *>(outputs[0]->MutableData()), dx1_path)); | |||
| std::string output_path = "./test_data/operators/arithmetic_fp32_7_dx2_1_1_6.bin"; | |||
| EXPECT_EQ(0, lite::CompareRelativeOutput(output_ptr, output_path)); | |||
| for (auto tensor : all_tensors) { | |||
| delete[] reinterpret_cast<float *>(tensor->MutableData()); | |||
| tensor->set_data(nullptr); | |||
| delete tensor; | |||
| } | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestDivGrad2Fp32 passed"; | |||
| } | |||
| } // namespace mindspore | |||
| #endif | |||
| @@ -1,75 +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 <iostream> | |||
| #include <memory> | |||
| #include "src/common/log_adapter.h" | |||
| #include "common/common_test.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/runtime/kernel/arm/fp32_grad/bias_grad.h" | |||
| #include "src/kernel_registry.h" | |||
| namespace mindspore { | |||
| class TestBiasGradFp32 : public mindspore::CommonTest { | |||
| public: | |||
| TestBiasGradFp32() {} | |||
| }; | |||
| TEST_F(TestBiasGradFp32, BiasGradFp32) { | |||
| // prepare stage | |||
| ArithmeticParameter *bias_param = static_cast<ArithmeticParameter *>(malloc(sizeof(ArithmeticParameter))); | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/operators/biasgradfp32_1_dy_10_28_28_7.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_dy({10, 28, 28, 7}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(input_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor}; | |||
| auto output_data = new float[7]; | |||
| std::vector<int> dim_dw = {7}; | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(output_data); | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_BiasGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(bias_param), &ctx, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 7; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/operators/biasgradfp32_1_db_7.bin"; | |||
| lite::CompareOutput(output_data, 7, output_path); | |||
| delete[] input_data; | |||
| delete[] output_data; | |||
| // delete bias_param; | |||
| dy_tensor.set_data(nullptr); | |||
| dw_tensor.set_data(nullptr); | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "BiasGradFp32 passed"; | |||
| } | |||
| } // namespace mindspore | |||
| @@ -1,205 +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 <iostream> | |||
| #include <memory> | |||
| #include "src/common/log_adapter.h" | |||
| #include "common/common_test.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/common/file_utils_ext.h" | |||
| #include "src/runtime/kernel/arm/fp32_grad/bn_grad.h" | |||
| #include "nnacl/fp32_grad/batch_norm.h" | |||
| #include "nnacl/fp32/batchnorm.h" | |||
| #include "src/kernel_registry.h" | |||
| namespace mindspore { | |||
| class TestBNGradFp32 : public mindspore::CommonTest { | |||
| public: | |||
| TestBNGradFp32() {} | |||
| lite::Tensor *CreateInTensor(std::string file_name, std::vector<int> dim); | |||
| }; | |||
| lite::Tensor *TestBNGradFp32::CreateInTensor(std::string file_name, std::vector<int> dim) { | |||
| size_t input_size = 0; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(file_name.c_str(), &input_size)); | |||
| auto tensor = new lite::Tensor(TypeId::kNumberTypeFloat32, dim); | |||
| tensor->set_data(input_data); | |||
| EXPECT_EQ(input_size, tensor->Size()); | |||
| return tensor; | |||
| } | |||
| TEST_F(TestBNGradFp32, BNGradFp32) { | |||
| // prepare stage | |||
| auto bn_param = static_cast<BNGradParameter *>(malloc(sizeof(BNGradParameter))); | |||
| bn_param->epsilon_ = 0.00001; | |||
| bn_param->momentum_ = 0.1; | |||
| const int batch = 2; | |||
| const int channels = 3; | |||
| const int height = 4; | |||
| const int width = 5; | |||
| auto dy_tensor = CreateInTensor("./test_data/bngrad/dy_2_4_5_3.bin", {batch, height, width, channels}); | |||
| auto x_tensor = CreateInTensor("./test_data/bngrad/input_x_2_4_5_3.bin", {batch, height, width, channels}); | |||
| auto scale_tensor = CreateInTensor("./test_data/bngrad/scale_3.bin", {1, 1, 1, channels}); | |||
| auto mean_tensor = CreateInTensor("./test_data/bngrad/save_mean_3.bin", {1, 1, 1, channels}); | |||
| auto var_tensor = CreateInTensor("././test_data/bngrad/save_var_3.bin", {1, 1, 1, channels}); | |||
| // prepare output tensors | |||
| lite::Tensor dx_tensor(TypeId::kNumberTypeFloat32, {batch, height, width, channels}); | |||
| ASSERT_EQ(dx_tensor.MallocData(), 0); | |||
| lite::Tensor dscale_tensor(TypeId::kNumberTypeFloat32, {1, 1, 1, channels}); | |||
| ASSERT_EQ(dscale_tensor.MallocData(), 0); | |||
| lite::Tensor dbias_tensor(TypeId::kNumberTypeFloat32, {1, 1, 1, channels}); | |||
| ASSERT_EQ(dbias_tensor.MallocData(), 0); | |||
| std::vector<lite::Tensor *> inputs = {dy_tensor, x_tensor, scale_tensor, mean_tensor, var_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dx_tensor, &dscale_tensor, &dbias_tensor}; | |||
| lite::InnerContext ctx; | |||
| ctx.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, ctx.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_BNGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(bn_param), &ctx, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel_obj->GetWorkspaceSize()); | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel_obj->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel_obj->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| auto time_avg = cost / loop_count; | |||
| std::cout << "single thread running time : " << time_avg << "us\n"; | |||
| std::cout << "==========dx==========\n"; | |||
| auto dx = reinterpret_cast<float *>(outputs[0]->MutableData()); | |||
| for (int i = 0; i < 7; i++) std::cout << dx[i] << " "; | |||
| std::cout << "\n"; | |||
| auto res = mindspore::lite::CompareRelativeOutput(dx, "./test_data/bngrad/output_dx_2_4_5_3.bin"); | |||
| std::cout << "\n=======dscale=======\n"; | |||
| auto dscale = reinterpret_cast<float *>(outputs[1]->MutableData()); | |||
| for (int i = 0; i < channels; i++) std::cout << dscale[i] << " "; | |||
| std::cout << "\n"; | |||
| res = mindspore::lite::CompareRelativeOutput(dscale, "./test_data/bngrad/output_dscale_3.bin"); | |||
| EXPECT_EQ(res, 0); | |||
| std::cout << "==========dbias==========\n"; | |||
| auto dbias = reinterpret_cast<float *>(outputs[2]->MutableData()); | |||
| for (int i = 0; i < 3; i++) std::cout << dbias[i] << " "; | |||
| std::cout << "\n"; | |||
| res = mindspore::lite::CompareRelativeOutput(dbias, "./test_data/bngrad/output_dbias_3.bin"); | |||
| EXPECT_EQ(res, 0); | |||
| for (auto v : inputs) { | |||
| delete[] reinterpret_cast<float *>(v->MutableData()); | |||
| v->set_data(nullptr); | |||
| delete v; | |||
| } | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "BNGradFp32 passed"; | |||
| } | |||
| TEST_F(TestBNGradFp32, BNTtrainFp32) { | |||
| auto bn_param = static_cast<BatchNormParameter *>(malloc(sizeof(BatchNormParameter))); | |||
| bn_param->epsilon_ = 0.00001; | |||
| bn_param->momentum_ = 0.; | |||
| const int batch = 2; | |||
| const int channels = 3; | |||
| const int height = 4; | |||
| const int width = 5; | |||
| bn_param->channel_ = channels; | |||
| auto x_tensor = CreateInTensor("./test_data/bngrad/input_x_2_4_5_3.bin", {batch, height, width, channels}); | |||
| lite::Tensor scale_tensor(TypeId::kNumberTypeFloat32, {1, 1, 1, channels}); | |||
| ASSERT_EQ(scale_tensor.MallocData(), 0); | |||
| auto scale = reinterpret_cast<float *>(scale_tensor.MutableData()); | |||
| std::fill(scale, scale + channels, 1.0f); | |||
| lite::Tensor bias_tensor(TypeId::kNumberTypeFloat32, {1, 1, 1, channels}); | |||
| ASSERT_EQ(bias_tensor.MallocData(), 0); | |||
| auto bias = reinterpret_cast<float *>(bias_tensor.MutableData()); | |||
| std::fill(bias, bias + channels, 1.0f); | |||
| lite::Tensor mean_tensor(TypeId::kNumberTypeFloat32, {1, 1, 1, channels}); | |||
| ASSERT_EQ(mean_tensor.MallocData(), 0); | |||
| auto mean = reinterpret_cast<float *>(mean_tensor.MutableData()); | |||
| std::fill(mean, mean + channels, 0.0f); | |||
| lite::Tensor var_tensor(TypeId::kNumberTypeFloat32, {1, 1, 1, channels}); | |||
| ASSERT_EQ(var_tensor.MallocData(), 0); | |||
| auto var = reinterpret_cast<float *>(var_tensor.MutableData()); | |||
| std::fill(var, var + channels, 1.0f); | |||
| std::vector<lite::Tensor *> inputs = {x_tensor, &scale_tensor, &bias_tensor, &mean_tensor, &var_tensor}; | |||
| lite::Tensor out_tensor(TypeId::kNumberTypeFloat32, {batch, height, width, channels}); | |||
| ASSERT_EQ(out_tensor.MallocData(), 0); | |||
| lite::Tensor save_scale_tensor(TypeId::kNumberTypeFloat32, {1, 1, 1, channels}); | |||
| ASSERT_EQ(save_scale_tensor.MallocData(), 0); | |||
| lite::Tensor save_bias_tensor(TypeId::kNumberTypeFloat32, {1, 1, 1, channels}); | |||
| ASSERT_EQ(save_bias_tensor.MallocData(), 0); | |||
| lite::Tensor save_mean_tensor(TypeId::kNumberTypeFloat32, {1, 1, 1, channels}); | |||
| ASSERT_EQ(save_mean_tensor.MallocData(), 0); | |||
| lite::Tensor save_var_tensor(TypeId::kNumberTypeFloat32, {1, 1, 1, channels}); | |||
| ASSERT_EQ(save_var_tensor.MallocData(), 0); | |||
| std::vector<lite::Tensor *> outputs = {&out_tensor, &save_scale_tensor, &save_bias_tensor, &save_mean_tensor, | |||
| &save_var_tensor}; | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_FusedBatchNorm}; | |||
| mindspore::lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(bn_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel_obj->GetWorkspaceSize()); | |||
| float *save_mean = reinterpret_cast<float *>(save_mean_tensor.MutableData()); | |||
| float *save_var = reinterpret_cast<float *>(save_var_tensor.MutableData()); | |||
| std::fill(save_mean, save_mean + channels, 0.f); | |||
| std::fill(save_var, save_var + channels, 0.f); | |||
| kernel_obj->train(); | |||
| kernel_obj->Run(); | |||
| std::cout << "================save_mean==============================\n"; | |||
| for (int i = 0; i < channels; i++) std::cout << save_mean[i] << " "; | |||
| std::cout << "\n"; | |||
| std::cout << "===============save_var==============================\n"; | |||
| for (int i = 0; i < channels; i++) std::cout << save_var[i] << " "; | |||
| std::cout << "\n"; | |||
| delete[] reinterpret_cast<float *>(x_tensor->MutableData()); | |||
| auto res = mindspore::lite::CompareRelativeOutput(save_mean, "./test_data/bngrad/running_mean_3.bin"); | |||
| EXPECT_EQ(res, 0); | |||
| res = mindspore::lite::CompareRelativeOutput(save_var, "./test_data/bngrad/running_var_3.bin"); | |||
| EXPECT_EQ(res, 0); | |||
| x_tensor->set_data(nullptr); | |||
| delete x_tensor; | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| delete kernel_obj; | |||
| } | |||
| } // namespace mindspore | |||
| @@ -1,777 +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 <iostream> | |||
| #include <memory> | |||
| #include <vector> | |||
| #include "src/common/log_adapter.h" | |||
| #include "common/common_test.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/common/file_utils_ext.h" | |||
| #include "mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution.h" | |||
| #include "mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution_grad_filter.h" | |||
| #include "mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution_grad_input.h" | |||
| #include "mindspore/lite/nnacl/conv_parameter.h" | |||
| #include "mindspore/lite/src/kernel_registry.h" | |||
| namespace mindspore { | |||
| class TestConvolutionGradFp32 : public mindspore::CommonTest { | |||
| public: | |||
| TestConvolutionGradFp32() {} | |||
| }; | |||
| void InitConvParamGroup1FP32(ConvParameter *conv_param) { | |||
| conv_param->input_batch_ = 1; | |||
| conv_param->input_h_ = 28; | |||
| conv_param->input_w_ = 28; | |||
| conv_param->input_channel_ = 3; | |||
| conv_param->output_batch_ = 1; | |||
| conv_param->output_h_ = 28; | |||
| conv_param->output_w_ = 28; | |||
| conv_param->output_channel_ = 32; | |||
| conv_param->kernel_h_ = 3; | |||
| conv_param->kernel_w_ = 3; | |||
| conv_param->stride_h_ = 1; | |||
| conv_param->stride_w_ = 1; | |||
| conv_param->dilation_h_ = 1; | |||
| conv_param->dilation_w_ = 1; | |||
| conv_param->pad_u_ = 1; | |||
| conv_param->pad_l_ = 1; | |||
| conv_param->group_ = 1; | |||
| conv_param->act_type_ = ActType_No; | |||
| conv_param->thread_num_ = 1; | |||
| } | |||
| void InitConvParamGroup3FP32(ConvParameter *conv_param) { | |||
| InitConvParamGroup1FP32(conv_param); | |||
| conv_param->group_ = 3; | |||
| conv_param->output_channel_ = 18; | |||
| } | |||
| void InitConvParamGroup3Dilation2FP32(ConvParameter *conv_param) { | |||
| InitConvParamGroup3FP32(conv_param); | |||
| conv_param->dilation_h_ = 2; | |||
| conv_param->dilation_w_ = 2; | |||
| conv_param->output_h_ = 26; | |||
| conv_param->output_w_ = 26; | |||
| } | |||
| TEST_F(TestConvolutionGradFp32, ConvFp32FilterGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| InitConvParamGroup1FP32(conv_param); | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/conv/convfp32_dy_1_28_28_32.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({1, 28, 28, 32}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| conv_param->output_channel_ * conv_param->kernel_h_ * conv_param->kernel_w_ * conv_param->input_channel_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/conv/convfp32_x_1_28_28_3.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({1, 28, 28, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input_data); | |||
| auto dw_data = new float[output_data_size]; | |||
| std::vector<int> dim_dw({32, 3, 3, 3}); | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(dw_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_Conv2DGradFilter}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/conv/convfp32_dw_32_3_3_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dw_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] dy_data; | |||
| delete[] dw_data; | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| delete kernel; | |||
| // delete conv_param; | |||
| dw_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| MS_LOG(INFO) << "TestConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestConvolutionGradFp32, ConvFp32InputGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| InitConvParamGroup1FP32(conv_param); | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/conv/convfp32_dy_1_28_28_32.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({1, 28, 28, 32}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| size_t w_size; | |||
| std::string w_path = "./test_data/conv/convfp32_w_32_3_3_3.bin"; | |||
| auto w_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(w_path.c_str(), &w_size)); | |||
| std::vector<int> dim_dw({32, 3, 3, 3}); | |||
| lite::Tensor w_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| w_tensor.set_data(w_data); | |||
| size_t output_data_size = | |||
| conv_param->input_batch_ * conv_param->input_h_ * conv_param->input_w_ * conv_param->input_channel_; | |||
| auto dx_data = new float[output_data_size]; | |||
| std::vector<int> dim_dx({1, 28, 28, 3}); | |||
| lite::Tensor dx_tensor(TypeId::kNumberTypeFloat32, dim_dx); | |||
| dx_tensor.set_data(dx_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &w_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dx_tensor}; | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_Conv2DGradInput}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/conv/convfp32_dx_1_28_28_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dx_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] dx_data; | |||
| delete[] w_data; | |||
| delete[] dy_data; | |||
| w_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| dx_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| delete kernel; | |||
| // delete conv_param; | |||
| MS_LOG(INFO) << "TestConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestConvolutionGradFp32, ConvFp32GroupFilterGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| InitConvParamGroup3FP32(conv_param); | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/conv/convfp32_dy_g3_1_28_28_18.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({1, 28, 28, 18}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = conv_param->output_channel_ * conv_param->kernel_h_ * conv_param->kernel_w_ * | |||
| conv_param->input_channel_ / conv_param->group_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/conv/convfp32_x_g3_1_28_28_3.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({1, 28, 28, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input_data); | |||
| auto dw_data = new float[output_data_size]; | |||
| std::vector<int> dim_dw({18, 3, 3, 1}); | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(dw_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_Conv2DGradFilter}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/conv/convfp32_dw_g3_18_3_3_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dw_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] dy_data; | |||
| delete[] dw_data; | |||
| dw_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| delete kernel; | |||
| // delete conv_param; | |||
| MS_LOG(INFO) << "TestConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestConvolutionGradFp32, ConvFp32GroupInputGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| InitConvParamGroup3FP32(conv_param); | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/conv/convfp32_dy_g3_1_28_28_18.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({1, 28, 28, 18}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| size_t w_size; | |||
| std::string w_path = "./test_data/conv/convfp32_w_g3_18_3_3_3.bin"; | |||
| auto w_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(w_path.c_str(), &w_size)); | |||
| std::vector<int> dim_dw({18, 3, 3, 1}); | |||
| lite::Tensor w_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| w_tensor.set_data(w_data); | |||
| size_t output_data_size = | |||
| conv_param->input_batch_ * conv_param->input_h_ * conv_param->input_w_ * conv_param->input_channel_; | |||
| auto dx_data = new float[output_data_size]; | |||
| std::vector<int> dim_dx({1, 28, 28, 3}); | |||
| lite::Tensor dx_tensor(TypeId::kNumberTypeFloat32, dim_dx); | |||
| dx_tensor.set_data(dx_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &w_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dx_tensor}; | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_Conv2DGradInput}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/conv/convfp32_dx_g3_1_28_28_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dx_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] dx_data; | |||
| delete[] w_data; | |||
| delete[] dy_data; | |||
| dx_tensor.set_data(nullptr); | |||
| w_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| delete kernel; | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| // delete conv_param; | |||
| MS_LOG(INFO) << "TestConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestConvolutionGradFp32, ConvFp32GroupDilationFilterGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| InitConvParamGroup3Dilation2FP32(conv_param); | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/conv/convfp32_dy_g3_d2_1_26_26_18.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({1, 26, 26, 18}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = conv_param->output_channel_ * conv_param->kernel_h_ * conv_param->kernel_w_ * | |||
| conv_param->input_channel_ / conv_param->group_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/conv/convfp32_x_g3_d2_1_28_28_3.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({1, 28, 28, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input_data); | |||
| auto dw_data = new float[output_data_size]; | |||
| std::vector<int> dim_dw({18, 3, 3, 1}); | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(dw_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_Conv2DGradFilter}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/conv/convfp32_dw_g3_d2_18_3_3_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dw_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] dy_data; | |||
| delete[] dw_data; | |||
| dw_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| delete kernel; | |||
| // delete conv_param; | |||
| MS_LOG(INFO) << "TestConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestConvolutionGradFp32, ConvFp32GroupDilationInputGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| InitConvParamGroup3Dilation2FP32(conv_param); | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/conv/convfp32_dy_g3_d2_1_26_26_18.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({1, 26, 26, 18}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| size_t w_size; | |||
| std::string w_path = "./test_data/conv/convfp32_w_g3_d2_18_3_3_3.bin"; | |||
| auto w_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(w_path.c_str(), &w_size)); | |||
| std::vector<int> dim_w({18, 3, 3, 1}); | |||
| lite::Tensor w_tensor(TypeId::kNumberTypeFloat32, dim_w); | |||
| w_tensor.set_data(w_data); | |||
| size_t output_data_size = | |||
| conv_param->input_batch_ * conv_param->input_h_ * conv_param->input_w_ * conv_param->input_channel_; | |||
| auto dx_data = new float[output_data_size]; | |||
| std::vector<int> dim_dx({1, 28, 28, 3}); | |||
| lite::Tensor dx_tensor(TypeId::kNumberTypeFloat32, dim_dx); | |||
| dx_tensor.set_data(dx_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &w_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dx_tensor}; | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_Conv2DGradInput}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/conv/convfp32_dx_g3_d2_1_28_28_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dx_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] dx_data; | |||
| delete[] w_data; | |||
| delete[] dy_data; | |||
| dx_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| w_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| delete kernel; | |||
| // delete conv_param; | |||
| MS_LOG(INFO) << "TestConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestConvolutionGradFp32, ConvGroupDilation) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| InitConvParamGroup3Dilation2FP32(conv_param); | |||
| size_t x_size; | |||
| std::string x_path = "./test_data/conv/convfp32_x_g3_d2_1_28_28_3.bin"; | |||
| auto x_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(x_path.c_str(), &x_size)); | |||
| std::vector<int> dim_x({1, 28, 28, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(x_data); | |||
| size_t w_size; | |||
| std::string w_path = "./test_data/conv/convfp32_w_g3_d2_18_3_3_3.bin"; | |||
| auto w_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(w_path.c_str(), &w_size)); | |||
| std::vector<int> dim_w({18, 3, 3, 1}); | |||
| lite::Tensor w_tensor(TypeId::kNumberTypeFloat32, dim_w); | |||
| w_tensor.set_data(w_data); | |||
| size_t output_data_size = | |||
| conv_param->output_batch_ * conv_param->output_h_ * conv_param->output_w_ * conv_param->output_channel_; | |||
| auto y_data = new float[output_data_size]; | |||
| std::vector<int> dim_y({1, 26, 26, 18}); | |||
| lite::Tensor y_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| y_tensor.set_data(y_data); | |||
| std::vector<lite::Tensor *> inputs = {&x_tensor, &w_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&y_tensor}; | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| auto *kernel = new mindspore::kernel::ConvolutionTrainCPUKernel(reinterpret_cast<OpParameter *>(conv_param), inputs, | |||
| outputs, &context, 0); | |||
| kernel->Init(); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| kernel->train(); | |||
| EXPECT_EQ(kernel->is_train(), 1); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/conv/convfp32_y_g3_d2_1_26_26_18.bin"; | |||
| auto res = lite::CompareRelativeOutput(y_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] y_data; | |||
| delete[] x_data; | |||
| delete[] w_data; | |||
| x_tensor.set_data(nullptr); | |||
| y_tensor.set_data(nullptr); | |||
| w_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| delete kernel; | |||
| MS_LOG(INFO) << "TestConvolutionFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestConvolutionGradFp32, ConvFp32Dilation2Group2Stride2FilterGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| conv_param->input_batch_ = 2; | |||
| conv_param->input_h_ = 32; | |||
| conv_param->input_w_ = 32; | |||
| conv_param->input_channel_ = 4; | |||
| conv_param->output_batch_ = 2; | |||
| conv_param->output_h_ = 15; | |||
| conv_param->output_w_ = 15; | |||
| conv_param->output_channel_ = 12; | |||
| conv_param->kernel_h_ = 3; | |||
| conv_param->kernel_w_ = 3; | |||
| conv_param->stride_h_ = 2; | |||
| conv_param->stride_w_ = 2; | |||
| conv_param->dilation_h_ = 2; | |||
| conv_param->dilation_w_ = 2; | |||
| conv_param->pad_u_ = 1; | |||
| conv_param->pad_l_ = 1; | |||
| conv_param->pad_r_ = 1; | |||
| conv_param->pad_d_ = 1; | |||
| conv_param->group_ = 2; | |||
| conv_param->act_type_ = ActType_No; | |||
| conv_param->thread_num_ = 1; | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/conv/convfp32_dy_d2_g2_s2_2_12_15_15.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({2, 15, 15, 12}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| conv_param->output_channel_ * conv_param->kernel_h_ * conv_param->kernel_w_ * conv_param->input_channel_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/conv/convfp32_input0_d2_g2_s2_2_4_32_32.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({2, 32, 32, 4}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input_data); | |||
| auto dw_data = new float[output_data_size]; | |||
| std::vector<int> dim_dw({12, 3, 3, 2}); | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(dw_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_Conv2DGradFilter}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/conv/convfp32_dw_d2_g2_s2_12_2_3_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dw_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] dy_data; | |||
| delete[] dw_data; | |||
| delete kernel; | |||
| // delete conv_param; | |||
| dw_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| MS_LOG(INFO) << "TestConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestConvolutionGradFp32, ConvGroup2Dilation2Stride2) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| conv_param->input_batch_ = 2; | |||
| conv_param->input_h_ = 32; | |||
| conv_param->input_w_ = 32; | |||
| conv_param->input_channel_ = 4; | |||
| conv_param->output_batch_ = 2; | |||
| conv_param->output_h_ = 15; | |||
| conv_param->output_w_ = 15; | |||
| conv_param->output_channel_ = 12; | |||
| conv_param->kernel_h_ = 3; | |||
| conv_param->kernel_w_ = 3; | |||
| conv_param->stride_h_ = 2; | |||
| conv_param->stride_w_ = 2; | |||
| conv_param->dilation_h_ = 2; | |||
| conv_param->dilation_w_ = 2; | |||
| conv_param->pad_u_ = 1; | |||
| conv_param->pad_l_ = 1; | |||
| conv_param->pad_r_ = 1; | |||
| conv_param->pad_d_ = 1; | |||
| conv_param->group_ = 2; | |||
| conv_param->act_type_ = ActType_No; | |||
| conv_param->thread_num_ = 1; | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/conv/convfp32_dy_d2_g2_s2_2_12_15_15.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({2, 15, 15, 12}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| size_t w_size; | |||
| std::string w_path = "./test_data/conv/convfp32_w_d2_g2_s2_12_2_3_3.bin"; | |||
| auto w_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(w_path.c_str(), &w_size)); | |||
| std::vector<int> dim_w({12, 3, 3, 2}); | |||
| lite::Tensor w_tensor(TypeId::kNumberTypeFloat32, dim_w); | |||
| w_tensor.set_data(w_data); | |||
| size_t output_data_size = | |||
| conv_param->input_batch_ * conv_param->input_h_ * conv_param->input_w_ * conv_param->input_channel_; | |||
| auto dx_data = new float[output_data_size]; | |||
| std::vector<int> dim_dx({2, 32, 32, 4}); | |||
| lite::Tensor dx_tensor(TypeId::kNumberTypeFloat32, dim_dx); | |||
| dx_tensor.set_data(dx_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &w_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dx_tensor}; | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_Conv2DGradInput}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/conv/convfp32_inputdx_d2_g2_s2_2_4_32_32.bin"; | |||
| auto res = lite::CompareRelativeOutput(dx_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] dx_data; | |||
| delete[] w_data; | |||
| delete[] dy_data; | |||
| dx_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| w_tensor.set_data(nullptr); | |||
| delete kernel; | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| MS_LOG(INFO) << "TestConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| } // namespace mindspore | |||
| @@ -1,628 +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 <iostream> | |||
| #include <memory> | |||
| #include <vector> | |||
| // #include "utils/log_adapter.h" | |||
| #include "common/common_test.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/common/file_utils_ext.h" | |||
| #include "mindspore/lite/src/runtime/kernel/arm/fp32_grad/deconvolution_grad_filter.h" | |||
| #include "mindspore/lite/nnacl/conv_parameter.h" | |||
| #include "mindspore/lite/src/kernel_registry.h" | |||
| namespace mindspore { | |||
| class TestDeConvolutionGradFp32 : public mindspore::CommonTest { | |||
| public: | |||
| TestDeConvolutionGradFp32() {} | |||
| }; | |||
| TEST_F(TestDeConvolutionGradFp32, DeConvFp32FilterGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| conv_param->input_batch_ = 2; | |||
| conv_param->input_h_ = 32; | |||
| conv_param->input_w_ = 32; | |||
| conv_param->input_channel_ = 3; | |||
| conv_param->output_batch_ = 2; | |||
| conv_param->output_h_ = 63; | |||
| conv_param->output_w_ = 63; | |||
| conv_param->output_channel_ = 9; | |||
| conv_param->kernel_h_ = 3; | |||
| conv_param->kernel_w_ = 3; | |||
| conv_param->stride_h_ = 2; | |||
| conv_param->stride_w_ = 2; | |||
| conv_param->dilation_h_ = 1; | |||
| conv_param->dilation_w_ = 1; | |||
| conv_param->pad_u_ = 1; | |||
| conv_param->pad_l_ = 1; | |||
| conv_param->pad_r_ = 1; | |||
| conv_param->pad_d_ = 1; | |||
| conv_param->group_ = 1; | |||
| conv_param->act_type_ = ActType_No; | |||
| conv_param->thread_num_ = 1; | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/deconv/deconvfp32_dy_2_9_63_63.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({2, 63, 63, 9}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| conv_param->output_channel_ * conv_param->kernel_h_ * conv_param->kernel_w_ * conv_param->input_channel_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/deconv/deconvfp32_input0_2_3_32_32.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({2, 32, 32, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input_data); | |||
| auto dw_data = new float[output_data_size]; | |||
| std::vector<int> dim_dw({3, 3, 3, 9}); | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(dw_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_DeConv2DGradFilter}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/deconv/deconvfp32_dw_9_3_3_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dw_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] dy_data; | |||
| delete[] dw_data; | |||
| delete kernel; | |||
| // delete conv_param; | |||
| dw_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| MS_LOG(INFO) << "TestDeConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestDeConvolutionGradFp32, DeConvFp32Dilation2FilterGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| conv_param->input_batch_ = 2; | |||
| conv_param->input_h_ = 32; | |||
| conv_param->input_w_ = 32; | |||
| conv_param->input_channel_ = 3; | |||
| conv_param->output_batch_ = 2; | |||
| conv_param->output_h_ = 65; | |||
| conv_param->output_w_ = 65; | |||
| conv_param->output_channel_ = 9; | |||
| conv_param->kernel_h_ = 3; | |||
| conv_param->kernel_w_ = 3; | |||
| conv_param->stride_h_ = 2; | |||
| conv_param->stride_w_ = 2; | |||
| conv_param->dilation_h_ = 2; | |||
| conv_param->dilation_w_ = 2; | |||
| conv_param->pad_u_ = 1; | |||
| conv_param->pad_l_ = 1; | |||
| conv_param->pad_r_ = 1; | |||
| conv_param->pad_d_ = 1; | |||
| conv_param->group_ = 1; | |||
| conv_param->act_type_ = ActType_No; | |||
| conv_param->thread_num_ = 1; | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/deconv/deconvfp32_dy_d2_2_9_65_65.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({2, 65, 65, 9}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| conv_param->output_channel_ * conv_param->kernel_h_ * conv_param->kernel_w_ * conv_param->input_channel_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/deconv/deconvfp32_input0_d2_2_3_32_32.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({2, 32, 32, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input_data); | |||
| auto dw_data = new float[output_data_size]; | |||
| std::vector<int> dim_dw({9, 3, 3, 3}); | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(dw_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_DeConv2DGradFilter}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/deconv/deconvfp32_dw_d2_9_3_3_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dw_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] dy_data; | |||
| delete[] dw_data; | |||
| delete kernel; | |||
| // delete conv_param; | |||
| dw_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| MS_LOG(INFO) << "TestDeConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestDeConvolutionGradFp32, DeConvFp32Dilation2Group3FilterGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| conv_param->input_batch_ = 2; | |||
| conv_param->input_h_ = 32; | |||
| conv_param->input_w_ = 32; | |||
| conv_param->input_channel_ = 3; | |||
| conv_param->output_batch_ = 2; | |||
| conv_param->output_h_ = 65; | |||
| conv_param->output_w_ = 65; | |||
| conv_param->output_channel_ = 9; | |||
| conv_param->kernel_h_ = 3; | |||
| conv_param->kernel_w_ = 3; | |||
| conv_param->stride_h_ = 2; | |||
| conv_param->stride_w_ = 2; | |||
| conv_param->dilation_h_ = 2; | |||
| conv_param->dilation_w_ = 2; | |||
| conv_param->pad_u_ = 1; | |||
| conv_param->pad_l_ = 1; | |||
| conv_param->pad_r_ = 1; | |||
| conv_param->pad_d_ = 1; | |||
| conv_param->group_ = 3; | |||
| conv_param->act_type_ = ActType_No; | |||
| conv_param->thread_num_ = 1; | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/deconv/deconvfp32_dy_d2_g3_2_9_65_65.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({2, 65, 65, 9}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| conv_param->output_channel_ * conv_param->kernel_h_ * conv_param->kernel_w_ * conv_param->input_channel_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/deconv/deconvfp32_input0_d2_g3_2_3_32_32.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({2, 32, 32, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input_data); | |||
| auto dw_data = new float[output_data_size]; | |||
| std::vector<int> dim_dw({3, 3, 3, 3}); | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(dw_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_DeConv2DGradFilter}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/deconv/deconvfp32_dw_d2_g3_3_3_3_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dw_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] dy_data; | |||
| delete[] dw_data; | |||
| delete kernel; | |||
| // delete conv_param; | |||
| dw_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| MS_LOG(INFO) << "TestDeConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestDeConvolutionGradFp32, DeConvFp32Dilation2Group3Stride1FilterGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| conv_param->input_batch_ = 2; | |||
| conv_param->input_h_ = 32; | |||
| conv_param->input_w_ = 32; | |||
| conv_param->input_channel_ = 3; | |||
| conv_param->output_batch_ = 2; | |||
| conv_param->output_h_ = 34; | |||
| conv_param->output_w_ = 34; | |||
| conv_param->output_channel_ = 9; | |||
| conv_param->kernel_h_ = 3; | |||
| conv_param->kernel_w_ = 3; | |||
| conv_param->stride_h_ = 1; | |||
| conv_param->stride_w_ = 1; | |||
| conv_param->dilation_h_ = 2; | |||
| conv_param->dilation_w_ = 2; | |||
| conv_param->pad_u_ = 1; | |||
| conv_param->pad_l_ = 1; | |||
| conv_param->pad_r_ = 1; | |||
| conv_param->pad_d_ = 1; | |||
| conv_param->group_ = 3; | |||
| conv_param->act_type_ = ActType_No; | |||
| conv_param->thread_num_ = 1; | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/deconv/deconvfp32_dy_d2_g3_s1_2_9_34_34.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({2, 34, 34, 9}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| conv_param->output_channel_ * conv_param->kernel_h_ * conv_param->kernel_w_ * conv_param->input_channel_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/deconv/deconvfp32_input0_d2_g3_s1_2_3_32_32.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({2, 32, 32, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input_data); | |||
| auto dw_data = new float[output_data_size]; | |||
| std::vector<int> dim_dw({3, 3, 3, 3}); | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(dw_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_DeConv2DGradFilter}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/deconv/deconvfp32_dw_d2_g3_s1_3_3_3_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dw_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] dy_data; | |||
| delete[] dw_data; | |||
| delete kernel; | |||
| // delete conv_param; | |||
| dw_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| MS_LOG(INFO) << "TestDeConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestDeConvolutionGradFp32, DeConvFp32Dilation2Group2Stride2FilterGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| conv_param->input_batch_ = 2; | |||
| conv_param->input_h_ = 32; | |||
| conv_param->input_w_ = 32; | |||
| conv_param->input_channel_ = 4; | |||
| conv_param->output_batch_ = 2; | |||
| conv_param->output_h_ = 65; | |||
| conv_param->output_w_ = 65; | |||
| conv_param->output_channel_ = 12; | |||
| conv_param->kernel_h_ = 3; | |||
| conv_param->kernel_w_ = 3; | |||
| conv_param->stride_h_ = 2; | |||
| conv_param->stride_w_ = 2; | |||
| conv_param->dilation_h_ = 2; | |||
| conv_param->dilation_w_ = 2; | |||
| conv_param->pad_u_ = 1; | |||
| conv_param->pad_l_ = 1; | |||
| conv_param->pad_r_ = 1; | |||
| conv_param->pad_d_ = 1; | |||
| conv_param->group_ = 2; | |||
| conv_param->act_type_ = ActType_No; | |||
| conv_param->thread_num_ = 1; | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/deconv/deconvfp32_dy_d2_g2_s2_2_12_65_65.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({2, 65, 65, 12}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| conv_param->output_channel_ * conv_param->kernel_h_ * conv_param->kernel_w_ * conv_param->input_channel_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/deconv/deconvfp32_input0_d2_g2_s2_2_4_32_32.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({2, 32, 32, 4}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input_data); | |||
| auto dw_data = new float[output_data_size]; | |||
| std::vector<int> dim_dw({6, 3, 3, 4}); | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(dw_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_DeConv2DGradFilter}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/deconv/deconvfp32_dw_d2_g2_s2_6_4_3_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dw_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] dy_data; | |||
| delete[] dw_data; | |||
| delete kernel; | |||
| // delete conv_param; | |||
| dw_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| MS_LOG(INFO) << "TestDeConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestDeConvolutionGradFp32, DeConvFp32Dilation2Group12Stride2FilterGrad) { | |||
| // prepare stage | |||
| auto conv_param = static_cast<ConvParameter *>(malloc(sizeof(ConvParameter))); | |||
| conv_param->input_batch_ = 2; | |||
| conv_param->input_h_ = 32; | |||
| conv_param->input_w_ = 32; | |||
| conv_param->input_channel_ = 12; | |||
| conv_param->output_batch_ = 2; | |||
| conv_param->output_h_ = 65; | |||
| conv_param->output_w_ = 65; | |||
| conv_param->output_channel_ = 12; | |||
| conv_param->kernel_h_ = 3; | |||
| conv_param->kernel_w_ = 3; | |||
| conv_param->stride_h_ = 2; | |||
| conv_param->stride_w_ = 2; | |||
| conv_param->dilation_h_ = 2; | |||
| conv_param->dilation_w_ = 2; | |||
| conv_param->pad_u_ = 1; | |||
| conv_param->pad_l_ = 1; | |||
| conv_param->pad_r_ = 1; | |||
| conv_param->pad_d_ = 1; | |||
| conv_param->group_ = 12; | |||
| conv_param->act_type_ = ActType_No; | |||
| conv_param->thread_num_ = 1; | |||
| size_t dy_size; | |||
| std::string dy_path = "./test_data/deconv/deconvfp32_dy_d2_g12_s2_2_12_65_65.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &dy_size)); | |||
| std::vector<int> dim_dy({2, 65, 65, 12}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(dy_data); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| conv_param->output_channel_ * conv_param->kernel_h_ * conv_param->kernel_w_ * conv_param->input_channel_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/deconv/deconvfp32_input0_d2_g12_s2_2_12_32_32.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({2, 32, 32, 12}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input_data); | |||
| auto dw_data = new float[output_data_size]; | |||
| std::vector<int> dim_dw({1, 3, 3, 12}); | |||
| lite::Tensor dw_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| dw_tensor.set_data(dw_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&dw_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_DeConv2DGradFilter}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel = creator(inputs, outputs, reinterpret_cast<OpParameter *>(conv_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel->GetWorkspaceSize()); | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| kernel->Run(); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| kernel->Run(); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/deconv/deconvfp32_dw_d2_g12_s2_12_1_3_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(dw_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] dy_data; | |||
| delete[] dw_data; | |||
| delete kernel; | |||
| // delete conv_param; | |||
| dw_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| MS_LOG(INFO) << "TestDeConvolutionGradFp32 Filter Grad passed"; | |||
| } | |||
| } // namespace mindspore | |||
| @@ -1,659 +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 <dirent.h> | |||
| #include <climits> | |||
| #include <cmath> | |||
| #include <iostream> | |||
| #include <fstream> | |||
| #include <memory> | |||
| #include <string> | |||
| #include <functional> | |||
| #include "schema/inner/model_generated.h" | |||
| #include "mindspore/lite/include/train_model.h" | |||
| #include "common/common_test.h" | |||
| #include "include/train_session.h" | |||
| #include "include/context.h" | |||
| #include "include/errorcode.h" | |||
| #include "src/common/log_adapter.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/common/file_utils_ext.h" | |||
| #include "src/kernel_registry.h" | |||
| #include "src/runtime/kernel/arm/fp32_grad/convolution.h" | |||
| namespace mindspore { | |||
| class NetworkTest : public mindspore::CommonTest { | |||
| public: | |||
| NetworkTest() {} | |||
| }; | |||
| int32_t runNet(mindspore::session::LiteSession *session, const std::string &in, const std::string &out, | |||
| const char *tensor_name, bool debug = false); | |||
| // INPUT(0) | |||
| // V | |||
| // +-------------+ | |||
| // | ReLU | | |||
| // +-------------+ | |||
| // +---output(1) V | |||
| // | V V weights(2) <----+ | |||
| // | +-------------+ | | |||
| // | | MatMul | | | |||
| // | +-------------+ | | |||
| // | output(3) V | | |||
| // | V V weights(4)<-+ | | |||
| // | +-------------+ | | | |||
| // | | Bias | | | | |||
| // | +-------------+ | | | |||
| // | output(5) V | | | |||
| // | V V LABELS(6) | | | |||
| // | +-------------+ | | | |||
| // | | CrossEntropy| | | | |||
| // | +-------------+ | | | |||
| // | +-dy(7) V V------------------------->Loss (14) | |||
| // | | V | | | |||
| // | | +-------------+ | | | |||
| // | | | BiasGrad | | | | |||
| // | | +-------------+ | | | |||
| // | | V db(8) | | | |||
| // | | +--------Update---+ | | |||
| // | +-------+ | | |||
| // +------V V | | |||
| // +-------------+ | | |||
| // | MatMul | | | |||
| // +-------------+ | | |||
| // V dw(9) | | |||
| // +-----------Update-----+ | |||
| TEST_F(NetworkTest, tuning_layer) { | |||
| const int BATCH_SIZE = 32; | |||
| const int NUM_CLASSES = 10; | |||
| const int FEATURE_SIZE = 1000; | |||
| auto meta_graph = std::make_shared<schema::MetaGraphT>(); | |||
| meta_graph->name = "graph"; | |||
| // define nodes | |||
| { | |||
| auto node = std::make_unique<schema::CNodeT>(); | |||
| node->inputIndex = {0}; | |||
| node->outputIndex = {1}; | |||
| node->primitive = std::make_unique<schema::PrimitiveT>(); | |||
| node->primitive->value.type = schema::PrimitiveType_Activation; | |||
| auto primitive = new schema::ActivationT; | |||
| primitive->type = schema::ActivationType_RELU; | |||
| node->primitive->value.value = primitive; | |||
| node->name = "ReLU"; | |||
| meta_graph->nodes.emplace_back(std::move(node)); | |||
| } | |||
| { | |||
| auto node = std::make_unique<schema::CNodeT>(); | |||
| node->inputIndex = {1, 2}; | |||
| node->outputIndex = {3}; | |||
| node->primitive = std::make_unique<schema::PrimitiveT>(); | |||
| node->primitive->value.type = schema::PrimitiveType_MatMul; | |||
| auto primitive = new schema::MatMulT; | |||
| primitive->transposeA = false; | |||
| primitive->transposeB = true; | |||
| node->primitive->value.value = primitive; | |||
| node->name = "MatMul1"; | |||
| meta_graph->nodes.emplace_back(std::move(node)); | |||
| } | |||
| { | |||
| auto node = std::make_unique<schema::CNodeT>(); | |||
| node->inputIndex = {3, 4}; | |||
| node->outputIndex = {5}; | |||
| node->primitive = std::make_unique<schema::PrimitiveT>(); | |||
| node->primitive->value.type = schema::PrimitiveType_BiasAdd; | |||
| auto primitive = new schema::BiasAddT; | |||
| primitive->axis.push_back(0); | |||
| node->primitive->value.value = primitive; | |||
| node->name = "BiasAdd"; | |||
| meta_graph->nodes.emplace_back(std::move(node)); | |||
| } | |||
| { | |||
| auto node = std::make_unique<schema::CNodeT>(); | |||
| node->inputIndex = {5, 6}; | |||
| node->outputIndex = {14, 7}; | |||
| node->primitive = std::make_unique<schema::PrimitiveT>(); | |||
| node->primitive->value.type = schema::PrimitiveType_SoftmaxCrossEntropy; | |||
| auto primitive = new schema::SoftmaxCrossEntropyT; | |||
| primitive->axis.push_back(0); | |||
| node->primitive->value.value = primitive; | |||
| node->name = "SoftmaxCrossEntropy"; | |||
| meta_graph->nodes.emplace_back(std::move(node)); | |||
| } | |||
| { | |||
| auto node = std::make_unique<schema::CNodeT>(); | |||
| node->inputIndex = {7}; | |||
| node->outputIndex = {8}; | |||
| node->primitive = std::make_unique<schema::PrimitiveT>(); | |||
| node->primitive->value.type = schema::PrimitiveType_BiasGrad; | |||
| auto primitive = new schema::BiasGradT; | |||
| primitive->axis.push_back(0); | |||
| node->primitive->value.value = primitive; | |||
| node->name = "BiasGrad"; | |||
| meta_graph->nodes.emplace_back(std::move(node)); | |||
| } | |||
| { | |||
| auto node = std::make_unique<schema::CNodeT>(); | |||
| node->inputIndex = {7, 1}; | |||
| node->outputIndex = {9}; | |||
| node->primitive = std::make_unique<schema::PrimitiveT>(); | |||
| node->primitive->value.type = schema::PrimitiveType_MatMul; | |||
| auto primitive = new schema::MatMulT; | |||
| primitive->transposeA = true; | |||
| primitive->transposeB = false; | |||
| node->primitive->value.value = primitive; | |||
| node->name = "MatMul2"; | |||
| meta_graph->nodes.emplace_back(std::move(node)); | |||
| } | |||
| { | |||
| auto node = std::make_unique<schema::CNodeT>(); | |||
| node->inputIndex = {2, 10, 11, 9, 12}; | |||
| node->outputIndex = {}; | |||
| node->primitive = std::make_unique<schema::PrimitiveT>(); | |||
| node->primitive->value.type = schema::PrimitiveType_ApplyMomentum; | |||
| auto primitive = new schema::ApplyMomentumT; | |||
| node->primitive->value.value = primitive; | |||
| node->name = "Momentum"; | |||
| meta_graph->nodes.emplace_back(std::move(node)); | |||
| } | |||
| { | |||
| auto node = std::make_unique<schema::CNodeT>(); | |||
| node->inputIndex = {4, 13, 11, 8, 12}; | |||
| node->outputIndex = {}; | |||
| node->primitive = std::make_unique<schema::PrimitiveT>(); | |||
| node->primitive->value.type = schema::PrimitiveType_ApplyMomentum; | |||
| auto primitive = new schema::ApplyMomentumT; | |||
| node->primitive->value.value = primitive; | |||
| node->name = "Momentum"; | |||
| meta_graph->nodes.emplace_back(std::move(node)); | |||
| } | |||
| meta_graph->inputIndex = {0, 6}; | |||
| meta_graph->outputIndex = {5, 14}; | |||
| auto input0 = std::make_unique<schema::TensorT>(); | |||
| input0->nodeType = schema::NodeType::NodeType_ValueNode; | |||
| input0->format = schema::Format_NHWC; | |||
| input0->dataType = TypeId::kNumberTypeFloat32; | |||
| input0->dims = {BATCH_SIZE, FEATURE_SIZE}; | |||
| input0->offset = -1; | |||
| meta_graph->allTensors.emplace_back(std::move(input0)); | |||
| // tensor 1 - relu | |||
| auto relu_out = std::make_unique<schema::TensorT>(); | |||
| relu_out->nodeType = schema::NodeType::NodeType_Parameter; | |||
| relu_out->format = schema::Format_NHWC; | |||
| relu_out->dataType = TypeId::kNumberTypeFloat32; | |||
| relu_out->dims = {BATCH_SIZE, FEATURE_SIZE}; | |||
| relu_out->offset = -1; | |||
| meta_graph->allTensors.emplace_back(std::move(relu_out)); | |||
| // tensor 2 - matmul weights | |||
| auto weight = std::make_unique<schema::TensorT>(); | |||
| weight->nodeType = schema::NodeType::NodeType_ValueNode; | |||
| weight->format = schema::Format_KHWC; | |||
| weight->dataType = TypeId::kNumberTypeFloat32; | |||
| weight->dims = {NUM_CLASSES, FEATURE_SIZE}; | |||
| size_t weight_size; | |||
| char *buf; | |||
| std::string weight_path = "./test_data/train/train_weight_10_1000.bin"; | |||
| ReadFile(weight_path.c_str(), &weight_size, &buf); | |||
| ASSERT_NE(nullptr, buf); | |||
| weight->data.resize(weight_size); | |||
| std::copy(buf, buf + weight_size, weight->data.data()); | |||
| meta_graph->allTensors.emplace_back(std::move(weight)); | |||
| delete[] buf; | |||
| // tensor 3 - matmul | |||
| auto input3 = std::make_unique<schema::TensorT>(); | |||
| input3->nodeType = schema::NodeType::NodeType_Parameter; | |||
| input3->format = schema::Format_NHWC; | |||
| input3->dataType = TypeId::kNumberTypeFloat32; | |||
| input3->dims = {BATCH_SIZE, NUM_CLASSES}; | |||
| input3->offset = -1; | |||
| meta_graph->allTensors.emplace_back(std::move(input3)); | |||
| // tensor 4 - fc bias | |||
| auto bias = std::make_unique<schema::TensorT>(); | |||
| bias->nodeType = schema::NodeType::NodeType_ValueNode; | |||
| bias->format = schema::Format_NHWC; | |||
| bias->dataType = TypeId::kNumberTypeFloat32; | |||
| bias->dims = {NUM_CLASSES}; | |||
| bias->offset = -1; | |||
| std::string bias_path = "./test_data/train/train_bias_10.bin"; | |||
| size_t bias_size; | |||
| ReadFile(bias_path.c_str(), &bias_size, &buf); | |||
| ASSERT_NE(nullptr, buf); | |||
| bias->data.resize(bias_size); | |||
| std::copy(buf, buf + bias_size, bias->data.data()); | |||
| meta_graph->allTensors.emplace_back(std::move(bias)); | |||
| delete[] buf; | |||
| // tensor 5 - bias_add | |||
| auto input5 = std::make_unique<schema::TensorT>(); | |||
| input5->nodeType = schema::NodeType::NodeType_Parameter; | |||
| input5->format = schema::Format_NHWC; | |||
| input5->dataType = TypeId::kNumberTypeFloat32; | |||
| input5->dims = {BATCH_SIZE, NUM_CLASSES}; | |||
| input5->offset = -1; | |||
| meta_graph->allTensors.emplace_back(std::move(input5)); | |||
| // tensor 6 - Label | |||
| { | |||
| auto label = std::make_unique<schema::TensorT>(); | |||
| label->nodeType = schema::NodeType::NodeType_ValueNode; | |||
| label->format = schema::Format_NHWC; | |||
| label->dataType = TypeId::kNumberTypeFloat32; | |||
| label->dims = {BATCH_SIZE * NUM_CLASSES}; | |||
| label->offset = -1; | |||
| meta_graph->allTensors.emplace_back(std::move(label)); | |||
| } | |||
| // tensor 7 - Softmaxentropy | |||
| auto input7 = std::make_unique<schema::TensorT>(); | |||
| input7->nodeType = schema::NodeType::NodeType_Parameter; | |||
| input7->format = schema::Format_NHWC; | |||
| input7->dataType = TypeId::kNumberTypeFloat32; | |||
| input7->dims = {BATCH_SIZE, NUM_CLASSES}; | |||
| input7->offset = -1; | |||
| meta_graph->allTensors.emplace_back(std::move(input7)); | |||
| // tensor 8 - biasGrad | |||
| auto input8 = std::make_unique<schema::TensorT>(); | |||
| input8->nodeType = schema::NodeType::NodeType_Parameter; | |||
| input8->format = schema::Format_NHWC; | |||
| input8->dataType = TypeId::kNumberTypeFloat32; | |||
| input8->dims = {NUM_CLASSES}; | |||
| input8->offset = -1; | |||
| meta_graph->allTensors.emplace_back(std::move(input8)); | |||
| // tensor 9 - matmul2 | |||
| auto input9 = std::make_unique<schema::TensorT>(); | |||
| input9->nodeType = schema::NodeType::NodeType_Parameter; | |||
| input9->format = schema::Format_NHWC; | |||
| input9->dataType = TypeId::kNumberTypeFloat32; | |||
| input9->dims = {NUM_CLASSES, FEATURE_SIZE}; | |||
| input9->offset = -1; | |||
| meta_graph->allTensors.emplace_back(std::move(input9)); | |||
| // tensor 10 weights accumulate | |||
| auto input10 = std::make_unique<schema::TensorT>(); | |||
| input10->nodeType = schema::NodeType::NodeType_ValueNode; | |||
| input10->format = schema::Format_NHWC; | |||
| input10->dataType = TypeId::kNumberTypeFloat32; | |||
| input10->dims = {NUM_CLASSES, FEATURE_SIZE}; | |||
| input10->offset = -1; | |||
| size_t input10_size = NUM_CLASSES * FEATURE_SIZE * sizeof(float); | |||
| input10->data.resize(input10_size); | |||
| std::fill(input10->data.data(), input10->data.data() + input10_size, 0.f); | |||
| meta_graph->allTensors.emplace_back(std::move(input10)); | |||
| // tensor 11 - lr | |||
| { | |||
| auto lr = std::make_unique<schema::TensorT>(); | |||
| lr->nodeType = schema::NodeType::NodeType_ValueNode; | |||
| lr->format = schema::Format_NHWC; | |||
| lr->dataType = TypeId::kNumberTypeFloat32; | |||
| lr->dims = {1}; | |||
| lr->offset = -1; | |||
| lr->data.resize(sizeof(float)); | |||
| float *data = reinterpret_cast<float *>(lr->data.data()); | |||
| *data = 0.01f; | |||
| meta_graph->allTensors.emplace_back(std::move(lr)); | |||
| } | |||
| // tensor 12 - momentum | |||
| { | |||
| auto input12 = std::make_unique<schema::TensorT>(); | |||
| input12->nodeType = schema::NodeType::NodeType_ValueNode; | |||
| input12->format = schema::Format_NHWC; | |||
| input12->dataType = TypeId::kNumberTypeFloat32; | |||
| input12->dims = {1}; | |||
| input12->offset = -1; | |||
| input12->data.resize(sizeof(float)); | |||
| float *data = reinterpret_cast<float *>(input12->data.data()); | |||
| *data = 0.f; | |||
| meta_graph->allTensors.emplace_back(std::move(input12)); | |||
| } | |||
| // tensor 13 - bias accumulate | |||
| auto input13 = std::make_unique<schema::TensorT>(); | |||
| input13->nodeType = schema::NodeType::NodeType_ValueNode; | |||
| input13->format = schema::Format_NHWC; | |||
| input13->dataType = TypeId::kNumberTypeFloat32; | |||
| input13->dims = {NUM_CLASSES}; | |||
| input13->offset = -1; | |||
| size_t input13_size = NUM_CLASSES * sizeof(float); | |||
| input13->data.resize(input13_size); | |||
| std::fill(input13->data.data(), input13->data.data() + input13_size, 0.f); | |||
| meta_graph->allTensors.emplace_back(std::move(input13)); | |||
| // tensor 14 - loss | |||
| { | |||
| auto loss14 = std::make_unique<schema::TensorT>(); | |||
| loss14->nodeType = schema::NodeType::NodeType_ValueNode; | |||
| loss14->format = schema::Format_NHWC; | |||
| loss14->dataType = TypeId::kNumberTypeFloat32; | |||
| loss14->dims = {1}; | |||
| loss14->offset = -1; | |||
| loss14->data.resize(sizeof(float)); | |||
| float *data = reinterpret_cast<float *>(loss14->data.data()); | |||
| *data = 0.0f; | |||
| meta_graph->allTensors.emplace_back(std::move(loss14)); | |||
| } | |||
| //================================================================ | |||
| buf = nullptr; | |||
| flatbuffers::FlatBufferBuilder builder(1024); | |||
| auto offset = schema::MetaGraph::Pack(builder, meta_graph.get()); | |||
| builder.Finish(offset); | |||
| size_t size = builder.GetSize(); | |||
| const char *content = reinterpret_cast<char *>(builder.GetBufferPointer()); | |||
| std::cout << "build fb size= " << size << std::endl; | |||
| auto model = lite::TrainModel::Import(content, size); | |||
| ASSERT_NE(nullptr, model); | |||
| meta_graph.reset(); | |||
| content = nullptr; | |||
| lite::Context context; | |||
| context.device_list_[0].device_info_.cpu_device_info_.cpu_bind_mode_ = lite::NO_BIND; | |||
| context.thread_num_ = 1; | |||
| auto session = session::TrainSession::CreateSession(&context); | |||
| ASSERT_NE(nullptr, session); | |||
| auto ret = session->CompileTrainGraph(model); | |||
| ASSERT_EQ(lite::RET_OK, ret); | |||
| session->Train(); | |||
| session->Train(); // Just double check that calling Train twice does not cause a problem | |||
| auto inputs = session->GetInputs(); | |||
| ASSERT_EQ(inputs.size(), 2); | |||
| auto inTensor = inputs.at(0); | |||
| ASSERT_NE(nullptr, inTensor); | |||
| auto data = inTensor->MutableData(); | |||
| //=================================================== | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/train/train_input_32_1000.bin"; | |||
| ReadFile(input_path.c_str(), &input_size, &buf); | |||
| ASSERT_NE(nullptr, buf); | |||
| auto input_data = reinterpret_cast<float *>(buf); | |||
| ASSERT_NE(nullptr, input_data); | |||
| //=================================================== | |||
| ASSERT_EQ(input_size, inTensor->Size()); | |||
| memcpy(data, input_data, input_size); | |||
| delete[] buf; | |||
| auto labelTensor = inputs.at(1); | |||
| ASSERT_NE(nullptr, labelTensor); | |||
| ASSERT_EQ(BATCH_SIZE * NUM_CLASSES, labelTensor->ElementsNum()); | |||
| auto labels = reinterpret_cast<float *>(labelTensor->MutableData()); | |||
| std::fill(labels, labels + labelTensor->ElementsNum(), 0.f); | |||
| for (int i = 0; i < BATCH_SIZE; i++) labels[i * NUM_CLASSES + (i * 97) % NUM_CLASSES] = 1.0; | |||
| ret = session->RunGraph(); | |||
| ASSERT_EQ(lite::RET_OK, ret); | |||
| auto outputs = session->GetOutputsByNodeName("SoftmaxCrossEntropy"); | |||
| ASSERT_EQ(outputs.size(), 1); | |||
| auto outTensor = (outputs.at(0)); | |||
| ASSERT_NE(nullptr, outTensor); | |||
| ASSERT_EQ(TypeId::kNumberTypeFloat32, outTensor->data_type()); | |||
| auto *outData = reinterpret_cast<float *>(outTensor->MutableData()); | |||
| ASSERT_NE(nullptr, outData); | |||
| std::cout << "==============Initial=Loss=====================" << std::endl; | |||
| std::cout << outData[0] << ", " << std::endl; | |||
| session->Eval(); | |||
| session->Eval(); // Just double check that calling eval twice does not cause a problem | |||
| ret = session->RunGraph(); | |||
| outputs = session->GetOutputsByNodeName("BiasAdd"); | |||
| ASSERT_EQ(outputs.size(), 1); | |||
| outTensor = (outputs.at(0)); | |||
| ASSERT_NE(nullptr, outTensor); | |||
| ASSERT_EQ(TypeId::kNumberTypeFloat32, outTensor->data_type()); | |||
| outData = reinterpret_cast<float *>(outTensor->MutableData()); | |||
| ASSERT_NE(nullptr, outData); | |||
| std::cout << "==============Scores=after-single=train========" << std::endl; | |||
| for (int i = 0; i < 10; i++) { | |||
| std::cout << outData[i] << ", "; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/train/train_output_32_10.bin"; | |||
| auto error = lite::RelativeOutputError(outData, output_path); | |||
| EXPECT_LT(error, 2e-3); | |||
| ret = session->RunGraph(); | |||
| auto all_output_tensors = session->GetOutputs(); | |||
| outTensor = (all_output_tensors["5"]); | |||
| ASSERT_NE(nullptr, outTensor); | |||
| ASSERT_EQ(TypeId::kNumberTypeFloat32, outTensor->data_type()); | |||
| outData = reinterpret_cast<float *>(outTensor->MutableData()); | |||
| ASSERT_NE(nullptr, outData); | |||
| std::cout << "==============Scores=eval-second-time==========" << std::endl; | |||
| for (int i = 0; i < 10; i++) { | |||
| std::cout << outData[i] << ", "; | |||
| } | |||
| std::cout << std::endl; | |||
| error = lite::RelativeOutputError(outData, output_path); | |||
| EXPECT_LT(error, 2e-3); | |||
| session->Train(); | |||
| session->Eval(); // do some more zig-zags | |||
| ret = session->RunGraph(); | |||
| outTensor = session->GetOutputByTensorName("5"); | |||
| ASSERT_NE(nullptr, outTensor); | |||
| ASSERT_EQ(TypeId::kNumberTypeFloat32, outTensor->data_type()); | |||
| outData = reinterpret_cast<float *>(outTensor->MutableData()); | |||
| ASSERT_NE(nullptr, outData); | |||
| std::cout << "==============Scores=Just Checking 3rd time====" << std::endl; | |||
| for (int i = 0; i < 10; i++) { | |||
| std::cout << outData[i] << ", "; | |||
| } | |||
| std::cout << std::endl; | |||
| error = lite::RelativeOutputError(outData, output_path); | |||
| EXPECT_LT(error, 2e-3); | |||
| delete session; | |||
| MS_LOG(INFO) << "TuningLayer passed"; | |||
| } | |||
| int32_t fileIterator(mindspore::session::TrainSession *session, const std::string &path, | |||
| std::function<int32_t(mindspore::session::TrainSession *session, const std::string &)> cb) { | |||
| int32_t res = 0; | |||
| if (auto dir = opendir(path.c_str())) { | |||
| while (auto f = readdir(dir)) { | |||
| if (f->d_name[0] == '.') continue; | |||
| if (f->d_type == DT_DIR) fileIterator(session, path + f->d_name + "/", cb); | |||
| if (f->d_type == DT_REG) res |= cb(session, path + f->d_name); | |||
| } | |||
| closedir(dir); | |||
| } | |||
| return res; | |||
| } | |||
| void replaceExt(const std::string &src, std::string *dst) { *dst = src.substr(0, src.find_last_of('.')) + ".emb"; } | |||
| int32_t runNet(mindspore::session::LiteSession *session, const std::string &in, const std::string &out, | |||
| const char *tensor_name, bool debug) { | |||
| // setup input | |||
| auto inputs = session->GetInputs(); | |||
| auto inTensor = inputs.at(0); | |||
| float *data = reinterpret_cast<float *>(inTensor->MutableData()); | |||
| size_t input_size; | |||
| float *in_buf = reinterpret_cast<float *>(lite::ReadFile(in.c_str(), &input_size)); | |||
| auto input_data = reinterpret_cast<float *>(in_buf); | |||
| std::copy(input_data, input_data + inTensor->ElementsNum(), data); | |||
| std::cout << "==============Input===========================" << std::endl; | |||
| for (int i = 0; i < 10; i++) { | |||
| std::cout << data[i] << ", "; | |||
| } | |||
| std::cout << std::endl; | |||
| delete[] in_buf; | |||
| // execute network | |||
| session->RunGraph(); | |||
| auto output = session->GetOutputByTensorName(tensor_name); | |||
| if (output != nullptr) { | |||
| float *output_data = reinterpret_cast<float *>(output->MutableData()); | |||
| // compare outputs | |||
| if (debug) { | |||
| std::cout << "==============Output===========================" << std::endl; | |||
| for (int i = 0; i < 10; i++) { | |||
| std::cout << output_data[i] << ", "; | |||
| } | |||
| std::cout << std::endl; | |||
| } | |||
| return mindspore::lite::CompareRelativeOutput(output_data, out); | |||
| } | |||
| return lite::RET_ERROR; | |||
| } | |||
| TEST_F(NetworkTest, efficient_net) { | |||
| char *buf = nullptr; | |||
| size_t net_size = 0; | |||
| std::string net = "./test_data/nets/effnetb0_fwd_nofuse.ms"; | |||
| ReadFile(net.c_str(), &net_size, &buf); | |||
| auto model = lite::TrainModel::Import(buf, net_size); | |||
| delete[] buf; | |||
| auto context = new lite::Context; | |||
| context->device_list_[0].device_info_.cpu_device_info_.cpu_bind_mode_ = lite::NO_BIND; | |||
| context->thread_num_ = 1; | |||
| auto session = session::TrainSession::CreateSession(context); | |||
| ASSERT_NE(session, nullptr); | |||
| auto ret = session->CompileTrainGraph(model); | |||
| ASSERT_EQ(lite::RET_OK, ret); | |||
| session->Eval(); | |||
| std::string in = "./test_data/nets/effNet_input_x_1_3_224_224.bin"; | |||
| std::string out = "./test_data/nets/effNet_output_y_1_1000.bin"; | |||
| auto res = runNet(session, in, out, "650"); | |||
| delete session; | |||
| delete context; | |||
| ASSERT_EQ(res, 0); | |||
| } | |||
| TEST_F(NetworkTest, lenetnet) { | |||
| char *buf = nullptr; | |||
| size_t net_size = 0; | |||
| std::string net = "./test_data/nets/lenet_train.ms"; | |||
| ReadFile(net.c_str(), &net_size, &buf); | |||
| auto model = lite::TrainModel::Import(buf, net_size); | |||
| delete[] buf; | |||
| auto context = new lite::Context; | |||
| context->device_list_[0].device_info_.cpu_device_info_.cpu_bind_mode_ = lite::NO_BIND; | |||
| context->thread_num_ = 1; | |||
| // check registration | |||
| mindspore::lite::KernelRegistry *reg = mindspore::lite::KernelRegistry::GetInstance(); | |||
| mindspore::kernel::KernelKey desc1 = {mindspore::kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, | |||
| mindspore::schema::PrimitiveType_Conv2D}; | |||
| mindspore::kernel::KernelKey desc2 = {mindspore::kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, | |||
| mindspore::schema::PrimitiveType_DepthwiseConv2D}; | |||
| auto regb1 = reg->GetCreator(desc1); | |||
| auto regb2 = reg->GetCreator(desc2); | |||
| ASSERT_EQ(regb1 == mindspore::kernel::CpuConvTrainFp32KernelCreator, false); | |||
| auto session = session::TrainSession::CreateSession(context); | |||
| ASSERT_NE(session, nullptr); | |||
| auto ret = session->CompileTrainGraph(model); | |||
| ASSERT_EQ(lite::RET_OK, ret); | |||
| auto rega1 = reg->GetCreator(desc1); | |||
| auto rega2 = reg->GetCreator(desc2); | |||
| ASSERT_EQ(regb1, rega1); | |||
| ASSERT_EQ(regb2, rega2); | |||
| ASSERT_EQ(rega1 == mindspore::kernel::CpuConvTrainFp32KernelCreator, false); | |||
| // end of check registration | |||
| session->Eval(); | |||
| std::string in = "./test_data/nets/x_lenet.bin"; | |||
| std::string out = "./test_data/nets/y_lenet.bin"; | |||
| auto res = runNet(session, in, out, "24"); | |||
| delete session; | |||
| delete context; | |||
| ASSERT_EQ(res, 0); | |||
| } | |||
| TEST_F(NetworkTest, retina_net) { | |||
| char *buf = nullptr; | |||
| size_t net_size = 0; | |||
| std::string net = "./test_data/nets/retinaface1.ms"; | |||
| ReadFile(net.c_str(), &net_size, &buf); | |||
| // auto model = lite::TrainModel::Import(buf, net_size); | |||
| auto model = lite::Model::Import(buf, net_size); | |||
| delete[] buf; | |||
| auto context = new lite::Context; | |||
| context->device_list_[0].device_info_.cpu_device_info_.cpu_bind_mode_ = lite::NO_BIND; | |||
| context->thread_num_ = 1; | |||
| // auto session = session::TrainSession::CreateSession(context); | |||
| auto session = session::LiteSession::CreateSession(context); | |||
| ASSERT_NE(session, nullptr); | |||
| auto ret = session->CompileGraph(model); | |||
| ASSERT_EQ(lite::RET_OK, ret); | |||
| // session->Eval(); | |||
| std::string in = "./test_data/nets/test1.hwc_normalized_f32"; | |||
| std::cout << "----- Output 0 -----" << std::endl; | |||
| std::string out = "./test_data/nets/test1_loc.f32"; | |||
| int final_res = 0; | |||
| auto res = runNet(session, in, out, "448", true); | |||
| // ASSERT_EQ(res, 0); | |||
| if (res != 0) { | |||
| final_res = res; | |||
| } | |||
| std::cout << "----- Output 1 -----" << std::endl; | |||
| out = "./test_data/nets/test1_conf.f32"; | |||
| res = runNet(session, in, out, "435", true); | |||
| // ASSERT_EQ(res, 0); | |||
| if (res != 0) { | |||
| final_res |= res; | |||
| } | |||
| std::cout << "----- Output 2 -----" << std::endl; | |||
| out = "./test_data/nets/test1_landms.f32"; | |||
| res = runNet(session, in, out, "421", true); | |||
| if (res != 0) { | |||
| final_res |= res; | |||
| } | |||
| ASSERT_EQ(final_res, 0); | |||
| delete session; | |||
| delete context; | |||
| } | |||
| TEST_F(NetworkTest, mobileface_net) { | |||
| char *buf = nullptr; | |||
| size_t net_size = 0; | |||
| std::string net = "./test_data/nets/mobilefacenet0924.ms"; | |||
| ReadFile(net.c_str(), &net_size, &buf); | |||
| // auto model = lite::TrainModel::Import(buf, net_size); | |||
| auto model = lite::Model::Import(buf, net_size); | |||
| delete[] buf; | |||
| auto context = new lite::Context; | |||
| context->device_list_[0].device_info_.cpu_device_info_.cpu_bind_mode_ = lite::NO_BIND; | |||
| context->thread_num_ = 1; | |||
| // auto session = session::TrainSession::CreateSession(context); | |||
| auto session = session::LiteSession::CreateSession(context); | |||
| ASSERT_NE(session, nullptr); | |||
| auto ret = session->CompileGraph(model); | |||
| ASSERT_EQ(lite::RET_OK, ret); | |||
| // session->Eval(); | |||
| std::string in = "./test_data/nets/facenet_input.f32"; | |||
| std::string out = "./test_data/nets/facenet_output.f32"; | |||
| auto res = runNet(session, in, out, "354", true); | |||
| ASSERT_EQ(res, 0); | |||
| delete model; | |||
| delete session; | |||
| delete context; | |||
| } | |||
| } // namespace mindspore | |||
| @@ -1,619 +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 <iostream> | |||
| #include <memory> | |||
| #include "src/ops/primitive_c.h" | |||
| #include "mindspore/lite/include/context.h" | |||
| #include "src/common/log_adapter.h" | |||
| #include "common/common_test.h" | |||
| #include "src/common/utils.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/common/file_utils_ext.h" | |||
| #include "nnacl/fp32_grad/pooling_grad.h" | |||
| #include "src/runtime/kernel/arm/fp32_grad/pooling_grad.h" | |||
| #include "mindspore/lite/src/kernel_registry.h" | |||
| namespace mindspore { | |||
| class TestPoolingGradFp32 : public mindspore::CommonTest { | |||
| public: | |||
| TestPoolingGradFp32() {} | |||
| }; | |||
| void InitPoolingParamFP32(PoolingParameter *pooling_param) { | |||
| pooling_param->input_batch_ = 1; | |||
| pooling_param->input_h_ = 28; | |||
| pooling_param->input_w_ = 28; | |||
| pooling_param->input_channel_ = 3; | |||
| pooling_param->output_batch_ = 1; | |||
| pooling_param->output_h_ = 28; | |||
| pooling_param->output_w_ = 28; | |||
| pooling_param->output_channel_ = 32; | |||
| pooling_param->window_h_ = 3; | |||
| pooling_param->window_w_ = 3; | |||
| pooling_param->stride_h_ = 1; | |||
| pooling_param->stride_w_ = 1; | |||
| pooling_param->pad_u_ = 1; | |||
| pooling_param->pad_d_ = 1; | |||
| pooling_param->pad_l_ = 1; | |||
| pooling_param->pad_r_ = 1; | |||
| pooling_param->thread_num_ = 1; | |||
| pooling_param->global_ = false; | |||
| } | |||
| TEST_F(TestPoolingGradFp32, AvgPoolingGradFp32) { | |||
| // prepare stage | |||
| auto pooling_param = static_cast<PoolingParameter *>(malloc(sizeof(PoolingParameter))); | |||
| InitPoolingParamFP32(pooling_param); | |||
| pooling_param->output_channel_ = 3; | |||
| pooling_param->pool_mode_ = PoolMode_AvgPool; | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| pooling_param->output_batch_ * pooling_param->output_channel_ * pooling_param->output_h_ * pooling_param->output_w_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/pooling/avgpoolgradfp32_1_dy_1_28_28_3.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| auto output_data = new float[output_data_size]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| AvgPoolingGrad(input_data, output_data, pooling_param, 1); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| AvgPoolingGrad(input_data, output_data, pooling_param, 1); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 20; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/pooling/avgpoolgradfp32_1_dx_1_28_28_3.bin"; | |||
| auto res = lite::CompareOutput(output_data, output_data_size, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] output_data; | |||
| free(pooling_param); | |||
| MS_LOG(INFO) << "TestAvgPoolingGradFp32 passed"; | |||
| } | |||
| TEST_F(TestPoolingGradFp32, AvgPoolingKernelGradFp32) { | |||
| // prepare stage | |||
| auto pooling_param = static_cast<PoolingParameter *>(malloc(sizeof(PoolingParameter))); | |||
| InitPoolingParamFP32(pooling_param); | |||
| pooling_param->output_channel_ = 3; | |||
| pooling_param->pool_mode_ = PoolMode_AvgPool; | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| // uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| pooling_param->output_batch_ * pooling_param->output_channel_ * pooling_param->output_h_ * pooling_param->output_w_; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/pooling/avgpoolgradfp32_1_dy_1_28_28_3.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_dy({1, 28, 28, 3}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(input_data); | |||
| std::string input1_path = "./test_data/pooling/avgpoolgradfp32_1_x_1_28_28_3.bin"; | |||
| auto input1_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input1_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({1, 28, 28, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input1_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| auto output_data = new float[output_data_size]; | |||
| std::vector<int> dim_dx({1, 28, 28, 3}); | |||
| lite::Tensor dx_tensor(TypeId::kNumberTypeFloat32, dim_dx); | |||
| dx_tensor.set_data(output_data); | |||
| std::vector<lite::Tensor *> outputs = {&dx_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_PoolingGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(pooling_param), &context, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 20; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/pooling/avgpoolgradfp32_1_dx_1_28_28_3.bin"; | |||
| auto res = lite::CompareOutput(output_data, output_data_size, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] input1_data; | |||
| delete[] output_data; | |||
| dx_tensor.set_data(nullptr); | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| // delete pooling_param; | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestAvgPoolingGradFp32 passed"; | |||
| } | |||
| TEST_F(TestPoolingGradFp32, AvgPoolingBatchGradFp32) { | |||
| // prepare stage | |||
| auto pooling_param = static_cast<PoolingParameter *>(malloc(sizeof(PoolingParameter))); | |||
| InitPoolingParamFP32(pooling_param); | |||
| pooling_param->output_channel_ = 3; | |||
| pooling_param->input_batch_ = 3; | |||
| pooling_param->output_batch_ = 3; | |||
| pooling_param->pool_mode_ = PoolMode_AvgPool; | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| // uint64_t time_avg = 0; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/pooling/avgpoolgradfp32_1_dy_3_28_28_3.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_dy({3, 28, 28, 3}); | |||
| lite::Tensor dy_tensor(TypeId::kNumberTypeFloat32, dim_dy); | |||
| dy_tensor.set_data(input_data); | |||
| std::string input1_path = "./test_data/pooling/avgpoolgradfp32_1_x_3_28_28_3.bin"; | |||
| auto input1_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input1_path.c_str(), &input_size)); | |||
| std::vector<int> dim_x({3, 28, 28, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(input1_data); | |||
| std::vector<lite::Tensor *> inputs = {&dy_tensor, &x_tensor}; | |||
| std::vector<int> dim_dx({3, 28, 28, 3}); | |||
| lite::Tensor dx_tensor(TypeId::kNumberTypeFloat32, dim_dx); | |||
| ASSERT_EQ(dx_tensor.MallocData(), 0); | |||
| auto output_data = reinterpret_cast<float *>(dx_tensor.MutableData()); | |||
| std::vector<lite::Tensor *> outputs = {&dx_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_PoolingGrad}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(pooling_param), &context, desc, nullptr); | |||
| kernel_obj->Run(); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 20; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/pooling/avgpoolgradfp32_1_dx_3_28_28_3.bin"; | |||
| size_t output_data_size = dx_tensor.ElementsNum(); | |||
| auto res = lite::CompareOutput(output_data, output_data_size, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] input1_data; | |||
| x_tensor.set_data(nullptr); | |||
| dy_tensor.set_data(nullptr); | |||
| // delete pooling_param; | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "TestAvgPoolingGradBatchFp32 passed"; | |||
| } | |||
| TEST_F(TestPoolingGradFp32, AvgPoolGradStride2Fp32) { | |||
| // prepare stage | |||
| // input size will be equal to the original size of x, output size will be the output size as in forward | |||
| auto pool = static_cast<PoolingParameter *>(malloc(sizeof(PoolingParameter))); | |||
| InitPoolingParamFP32(pool); | |||
| pool->output_channel_ = 3; | |||
| pool->pool_mode_ = PoolMode_AvgPool; | |||
| pool->input_batch_ = 3; | |||
| pool->output_batch_ = 3; | |||
| pool->output_h_ = 14; | |||
| pool->output_w_ = 14; | |||
| pool->stride_h_ = 2; | |||
| pool->stride_w_ = 2; | |||
| size_t input_size; | |||
| auto x_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/avgpoolgradfp32_s2_x_3_28_28_3.bin", &input_size)); | |||
| std::vector<int> dim_x({pool->output_batch_, pool->input_h_, pool->input_w_, pool->input_channel_}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(x_data); | |||
| auto yt_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/avgpoolgradfp32_s2_dy_3_28_28_3.bin", &input_size)); | |||
| std::vector<int> dim_y({pool->output_batch_, pool->output_h_, pool->output_w_, pool->output_channel_}); | |||
| lite::Tensor yt_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| yt_tensor.set_data(yt_data); | |||
| lite::Tensor out_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| ASSERT_EQ(out_tensor.MallocData(), 0); | |||
| float *out_data = static_cast<float *>(out_tensor.MutableData()); | |||
| std::vector<lite::Tensor *> inputs = {&yt_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&out_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey pool_desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_PoolingGrad}; | |||
| auto pool_creator = lite::KernelRegistry::GetInstance()->GetCreator(pool_desc); | |||
| auto kernel = pool_creator(inputs, outputs, reinterpret_cast<OpParameter *>(pool), &context, pool_desc, nullptr); | |||
| kernel->Init(); | |||
| kernel->Run(); | |||
| std::string output_path = "./test_data/pooling/avgpoolgradfp32_s2_dx_3_28_28_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(out_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] x_data; | |||
| delete[] yt_data; | |||
| // delete[] out_data; | |||
| // delete conv_param; | |||
| x_tensor.set_data(nullptr); | |||
| yt_tensor.set_data(nullptr); | |||
| delete kernel; | |||
| MS_LOG(INFO) << "AvgPoolGradStride2Fp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestPoolingGradFp32, AvgPoolGradStride3Fp32) { | |||
| // prepare stage | |||
| // input size will be equal to the original size of x, output size will be the output size as in forward | |||
| auto pool = static_cast<PoolingParameter *>(malloc(sizeof(PoolingParameter))); | |||
| InitPoolingParamFP32(pool); | |||
| pool->output_channel_ = 3; | |||
| pool->pool_mode_ = PoolMode_AvgPool; | |||
| pool->input_batch_ = 3; | |||
| pool->output_batch_ = 3; | |||
| pool->output_h_ = 10; | |||
| pool->output_w_ = 10; | |||
| pool->stride_h_ = 3; | |||
| pool->stride_w_ = 3; | |||
| size_t input_size; | |||
| auto x_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/avgpoolgradfp32_s3_x_3_28_28_3.bin", &input_size)); | |||
| std::vector<int> dim_x({pool->output_batch_, pool->input_h_, pool->input_w_, pool->input_channel_}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(x_data); | |||
| auto yt_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/avgpoolgradfp32_s3_dy_3_28_28_3.bin", &input_size)); | |||
| std::vector<int> dim_y({pool->output_batch_, pool->output_h_, pool->output_w_, pool->output_channel_}); | |||
| lite::Tensor yt_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| yt_tensor.set_data(yt_data); | |||
| lite::Tensor out_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| ASSERT_EQ(out_tensor.MallocData(), 0); | |||
| auto out_data = static_cast<float *>(out_tensor.MutableData()); | |||
| std::vector<lite::Tensor *> inputs = {&yt_tensor, &x_tensor}; | |||
| std::vector<lite::Tensor *> outputs = {&out_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey pool_desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_PoolingGrad}; | |||
| auto pool_creator = lite::KernelRegistry::GetInstance()->GetCreator(pool_desc); | |||
| auto kernel = pool_creator(inputs, outputs, reinterpret_cast<OpParameter *>(pool), &context, pool_desc, nullptr); | |||
| kernel->Init(); | |||
| kernel->Run(); | |||
| std::string output_path = "./test_data/pooling/avgpoolgradfp32_s3_dx_3_28_28_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(out_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] x_data; | |||
| delete[] yt_data; | |||
| // delete[] out_data; | |||
| // delete conv_param; | |||
| x_tensor.set_data(nullptr); | |||
| yt_tensor.set_data(nullptr); | |||
| delete kernel; | |||
| MS_LOG(INFO) << "AvgPoolGradStride3Fp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestPoolingGradFp32, MaxPoolingGradFp32) { | |||
| // prepare stage | |||
| auto pooling_param = static_cast<PoolingParameter *>(malloc(sizeof(PoolingParameter))); | |||
| InitPoolingParamFP32(pooling_param); | |||
| pooling_param->output_channel_ = 3; | |||
| pooling_param->pool_mode_ = PoolMode_MaxPool; | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| size_t output_data_size = | |||
| pooling_param->output_batch_ * pooling_param->output_channel_ * pooling_param->output_h_ * pooling_param->output_w_; | |||
| size_t input_size; | |||
| std::string i_path = "./test_data/pooling/maxpoolgradfp32_1_x_1_28_28_3.bin"; | |||
| auto in_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(i_path.c_str(), &input_size)); | |||
| std::string dy_path = "./test_data/pooling/maxpoolgradfp32_1_dy_1_28_28_3.bin"; | |||
| auto dy_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dy_path.c_str(), &input_size)); | |||
| std::string dx_path = "./test_data/pooling/maxpoolgradfp32_1_dx_1_28_28_3.bin"; | |||
| auto dx_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(dx_path.c_str(), &input_size)); | |||
| auto output_data = new float[output_data_size]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| MaxPoolingGrad(in_data, dx_data, dy_data, output_data, pooling_param, 1); | |||
| } | |||
| int loop_count = 100; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| MaxPoolingGrad(in_data, dx_data, dy_data, output_data, pooling_param, 1); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 20; i++) { | |||
| std::cout << output_data[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string output_path = "./test_data/pooling/maxpoolgradfp32_1_xgrad_1_28_28_3.bin"; | |||
| auto res = lite::CompareOutput(output_data, output_data_size, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| free(pooling_param); | |||
| delete[] in_data; | |||
| delete[] dy_data; | |||
| delete[] dx_data; | |||
| delete[] output_data; | |||
| MS_LOG(INFO) << "TestMaxPoolingGradFp32 passed"; | |||
| } | |||
| TEST_F(TestPoolingGradFp32, MaxPoolGradBatchFp32) { | |||
| // prepare stage | |||
| // input size will be equal to the original size of x, output size will be the output size as in forward | |||
| auto maxpool = static_cast<PoolingParameter *>(malloc(sizeof(PoolingParameter))); | |||
| InitPoolingParamFP32(maxpool); | |||
| maxpool->output_channel_ = 3; | |||
| maxpool->pool_mode_ = PoolMode_MaxPool; | |||
| maxpool->input_batch_ = 3; | |||
| maxpool->output_batch_ = 3; | |||
| size_t input_size; | |||
| auto x_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/maxpoolgradfp32_1_x_3_28_28_3.bin", &input_size)); | |||
| std::vector<int> dim_x({3, 28, 28, 3}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(x_data); | |||
| auto y_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/maxpoolgradfp32_1_dx_3_28_28_3.bin", &input_size)); | |||
| std::vector<int> dim_y({3, 28, 28, 3}); | |||
| lite::Tensor y_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| y_tensor.set_data(y_data); | |||
| auto yt_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/maxpoolgradfp32_1_dy_3_28_28_3.bin", &input_size)); | |||
| lite::Tensor yt_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| yt_tensor.set_data(yt_data); | |||
| lite::Tensor out_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| ASSERT_EQ(out_tensor.MallocData(), 0); | |||
| auto out_data = static_cast<float *>(out_tensor.MutableData()); | |||
| std::vector<lite::Tensor *> maxpool_inputs = {&x_tensor, &y_tensor, &yt_tensor}; | |||
| std::vector<lite::Tensor *> maxpool_outputs = {&out_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey maxpool_desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_PoolingGrad}; | |||
| auto maxpool_creator = lite::KernelRegistry::GetInstance()->GetCreator(maxpool_desc); | |||
| auto kernel = maxpool_creator(maxpool_inputs, maxpool_outputs, reinterpret_cast<OpParameter *>(maxpool), &context, | |||
| maxpool_desc, nullptr); | |||
| kernel->Init(); | |||
| kernel->Run(); | |||
| std::string output_path = "./test_data/pooling/maxpoolgradfp32_1_xgrad_3_28_28_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(out_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] x_data; | |||
| delete[] y_data; | |||
| delete[] yt_data; | |||
| // delete[] out_data; | |||
| // delete conv_param; | |||
| x_tensor.set_data(nullptr); | |||
| y_tensor.set_data(nullptr); | |||
| yt_tensor.set_data(nullptr); | |||
| delete kernel; | |||
| MS_LOG(INFO) << "MaxPoolGradBatchFp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestPoolingGradFp32, MaxPoolGradStride2Fp32) { | |||
| // prepare stage | |||
| // input size will be equal to the original size of x, output size will be the output size as in forward | |||
| auto maxpool = static_cast<PoolingParameter *>(malloc(sizeof(PoolingParameter))); | |||
| InitPoolingParamFP32(maxpool); | |||
| maxpool->output_channel_ = 3; | |||
| maxpool->input_channel_ = 3; | |||
| maxpool->pool_mode_ = PoolMode_MaxPool; | |||
| maxpool->input_batch_ = 3; | |||
| maxpool->output_batch_ = 3; | |||
| maxpool->output_h_ = 14; | |||
| maxpool->output_w_ = 14; | |||
| maxpool->stride_h_ = 2; | |||
| maxpool->stride_w_ = 2; | |||
| size_t input_size; | |||
| auto x_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/maxpoolgradfp32_s2_x_3_28_28_3.bin", &input_size)); | |||
| std::vector<int> dim_x({maxpool->output_batch_, maxpool->input_h_, maxpool->input_w_, maxpool->input_channel_}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(x_data); | |||
| auto y_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/maxpoolgradfp32_s2_dx_3_28_28_3.bin", &input_size)); | |||
| std::vector<int> dim_y({maxpool->output_batch_, maxpool->output_h_, maxpool->output_w_, maxpool->output_channel_}); | |||
| lite::Tensor y_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| y_tensor.set_data(y_data); | |||
| auto yt_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/maxpoolgradfp32_s2_dy_3_28_28_3.bin", &input_size)); | |||
| lite::Tensor yt_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| yt_tensor.set_data(yt_data); | |||
| lite::Tensor out_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| ASSERT_EQ(out_tensor.MallocData(), 0); | |||
| auto out_data = static_cast<float *>(out_tensor.MutableData()); | |||
| std::vector<lite::Tensor *> maxpool_inputs = {&x_tensor, &y_tensor, &yt_tensor}; | |||
| std::vector<lite::Tensor *> maxpool_outputs = {&out_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey maxpool_desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_PoolingGrad}; | |||
| auto maxpool_creator = lite::KernelRegistry::GetInstance()->GetCreator(maxpool_desc); | |||
| auto kernel = maxpool_creator(maxpool_inputs, maxpool_outputs, reinterpret_cast<OpParameter *>(maxpool), &context, | |||
| maxpool_desc, nullptr); | |||
| kernel->Init(); | |||
| kernel->Run(); | |||
| std::string output_path = "./test_data/pooling/maxpoolgradfp32_s2_xgrad_3_28_28_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(out_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] x_data; | |||
| delete[] y_data; | |||
| delete[] yt_data; | |||
| // delete[] out_data; | |||
| // delete conv_param; | |||
| x_tensor.set_data(nullptr); | |||
| y_tensor.set_data(nullptr); | |||
| yt_tensor.set_data(nullptr); | |||
| delete kernel; | |||
| MS_LOG(INFO) << "MaxPoolGradStride2Fp32 Filter Grad passed"; | |||
| } | |||
| TEST_F(TestPoolingGradFp32, MaxPoolGradStride3Fp32) { | |||
| // prepare stage | |||
| // input size will be equal to the original size of x, output size will be the output size as in forward | |||
| auto maxpool = static_cast<PoolingParameter *>(malloc(sizeof(PoolingParameter))); | |||
| InitPoolingParamFP32(maxpool); | |||
| maxpool->output_channel_ = 3; | |||
| maxpool->input_channel_ = 3; | |||
| maxpool->pool_mode_ = PoolMode_MaxPool; | |||
| maxpool->input_batch_ = 3; | |||
| maxpool->output_batch_ = 3; | |||
| maxpool->output_h_ = 10; | |||
| maxpool->output_w_ = 10; | |||
| maxpool->stride_h_ = 3; | |||
| maxpool->stride_w_ = 3; | |||
| size_t input_size; | |||
| auto x_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/maxpoolgradfp32_s3_x_3_28_28_3.bin", &input_size)); | |||
| std::vector<int> dim_x({maxpool->output_batch_, maxpool->input_h_, maxpool->input_w_, maxpool->input_channel_}); | |||
| lite::Tensor x_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| x_tensor.set_data(x_data); | |||
| auto y_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/maxpoolgradfp32_s3_dx_3_28_28_3.bin", &input_size)); | |||
| std::vector<int> dim_y({maxpool->output_batch_, maxpool->output_h_, maxpool->output_w_, maxpool->output_channel_}); | |||
| lite::Tensor y_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| y_tensor.set_data(y_data); | |||
| auto yt_data = reinterpret_cast<float *>( | |||
| mindspore::lite::ReadFile("./test_data/pooling/maxpoolgradfp32_s3_dy_3_28_28_3.bin", &input_size)); | |||
| lite::Tensor yt_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| yt_tensor.set_data(yt_data); | |||
| lite::Tensor out_tensor(TypeId::kNumberTypeFloat32, dim_x); | |||
| ASSERT_EQ(out_tensor.MallocData(), 0); | |||
| auto out_data = static_cast<float *>(out_tensor.MutableData()); | |||
| std::vector<lite::Tensor *> maxpool_inputs = {&x_tensor, &y_tensor, &yt_tensor}; | |||
| std::vector<lite::Tensor *> maxpool_outputs = {&out_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey maxpool_desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_PoolingGrad}; | |||
| auto maxpool_creator = lite::KernelRegistry::GetInstance()->GetCreator(maxpool_desc); | |||
| auto kernel = maxpool_creator(maxpool_inputs, maxpool_outputs, reinterpret_cast<OpParameter *>(maxpool), &context, | |||
| maxpool_desc, nullptr); | |||
| kernel->Init(); | |||
| kernel->Run(); | |||
| std::string output_path = "./test_data/pooling/maxpoolgradfp32_s3_xgrad_3_28_28_3.bin"; | |||
| auto res = lite::CompareRelativeOutput(out_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] x_data; | |||
| delete[] y_data; | |||
| delete[] yt_data; | |||
| // delete[] out_data; | |||
| // delete conv_param; | |||
| x_tensor.set_data(nullptr); | |||
| y_tensor.set_data(nullptr); | |||
| yt_tensor.set_data(nullptr); | |||
| delete kernel; | |||
| MS_LOG(INFO) << "MaxPoolGradStride3Fp32 Filter Grad passed"; | |||
| } | |||
| } // namespace mindspore | |||
| @@ -1,106 +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 <iostream> | |||
| #include <memory> | |||
| #include "src/common/log_adapter.h" | |||
| #include "common/common_test.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/runtime/kernel/arm/fp32_grad/sparse_softmax_cross_entropy_with_logits.h" | |||
| #include "src/kernel_registry.h" | |||
| namespace mindspore { | |||
| class TestSoftmaxCrossEntropyFp32 : public mindspore::CommonTest { | |||
| public: | |||
| TestSoftmaxCrossEntropyFp32() {} | |||
| }; | |||
| TEST_F(TestSoftmaxCrossEntropyFp32, SoftmaxCrossEntropyFp32) { | |||
| // prepare stage | |||
| auto sce_param = reinterpret_cast<SoftmaxCrossEntropyParameter *>(malloc(sizeof(SoftmaxCrossEntropyParameter))); | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/operators/sce_fp32_1_y_6_4.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::vector<int> dim_y({6, 4}); | |||
| lite::Tensor y_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| y_tensor.set_data(input_data); | |||
| std::string label_path = "./test_data/operators/sce_fp32_1_l_6.bin"; | |||
| auto ll_labels = reinterpret_cast<int64_t *>(mindspore::lite::ReadFile(label_path.c_str(), &input_size)); | |||
| auto labels = new float[6 * 4]; | |||
| std::fill(labels, labels + 6 * 4, 0.f); | |||
| for (int i = 0; i < 6; i++) labels[i * 4 + ll_labels[i]] = 1.0; | |||
| std::vector<int> dim_l({6, 4}); | |||
| lite::Tensor l_tensor(TypeId::kNumberTypeInt32, dim_l); | |||
| l_tensor.set_data(labels); | |||
| std::vector<lite::Tensor *> inputs = {&y_tensor, &l_tensor}; | |||
| auto loss = new float[1]; | |||
| std::vector<int> dim_dw({1}); | |||
| lite::Tensor loss_tensor(TypeId::kNumberTypeFloat32, dim_dw); | |||
| loss_tensor.set_data(loss); | |||
| auto grad = new float[24]; | |||
| lite::Tensor grad_tensor(TypeId::kNumberTypeFloat32, dim_y); | |||
| grad_tensor.set_data(grad); | |||
| std::vector<lite::Tensor *> outputs = {&loss_tensor, &grad_tensor}; | |||
| lite::InnerContext context; | |||
| context.thread_num_ = 1; | |||
| ASSERT_EQ(lite::RET_OK, context.Init()); | |||
| kernel::KernelKey desc = {kernel::kCPU, TypeId::kNumberTypeFloat32, schema::PrimitiveType_SoftmaxCrossEntropy}; | |||
| auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc); | |||
| auto kernel_obj = creator(inputs, outputs, reinterpret_cast<OpParameter *>(sce_param), &context, desc, nullptr); | |||
| mindspore::kernel::LiteKernel::AllocWorkspace(kernel_obj->GetWorkspaceSize()); | |||
| kernel_obj->Run(); | |||
| printf("==================total loss=================\n"); | |||
| std::cout << loss[0] << " ," << std::endl; | |||
| printf("==================Testing Grad===============\n"); | |||
| std::string output_path = "./test_data/operators/sce_fp32_1_loss_1.bin"; | |||
| lite::CompareOutput(loss, 1, output_path); | |||
| ((mindspore::kernel::SparseSoftmaxCrossEntropyWithLogitsCPUKernel *)kernel_obj)->train(); | |||
| kernel_obj->Run(); | |||
| printf("==================output data=================\n"); | |||
| for (int i = 0; i < 12; i++) { | |||
| std::cout << grad[i] << " ,"; | |||
| } | |||
| std::cout << std::endl; | |||
| std::string grad_path = "./test_data/operators/sce_fp32_1_dy_6_4.bin"; | |||
| lite::CompareOutput(grad, 24, grad_path); | |||
| delete[] ll_labels; | |||
| delete[] labels; | |||
| delete[] input_data; | |||
| delete[] loss; | |||
| delete[] grad; | |||
| l_tensor.set_data(nullptr); | |||
| y_tensor.set_data(nullptr); | |||
| loss_tensor.set_data(nullptr); | |||
| grad_tensor.set_data(nullptr); | |||
| mindspore::kernel::LiteKernel::FreeWorkspace(); | |||
| delete kernel_obj; | |||
| MS_LOG(INFO) << "SoftmaxCrossEntropyFp32 passed"; | |||
| } | |||
| } // namespace mindspore | |||
| @@ -1,350 +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 <iostream> | |||
| #include <memory> | |||
| #include <vector> | |||
| #include "src/ops/primitive_c.h" | |||
| #include "mindspore/lite/include/context.h" | |||
| #include "src/common/log_adapter.h" | |||
| #include "common/common_test.h" | |||
| #include "src/common/utils.h" | |||
| #include "src/common/file_utils.h" | |||
| #include "src/common/file_utils_ext.h" | |||
| #include "mindspore/lite/src/runtime/kernel/arm/fp32_grad/softmax_grad.h" | |||
| #include "mindspore/lite/nnacl/fp32_grad/softmax_grad.h" | |||
| #include "mindspore/lite/src/kernel_registry.h" | |||
| namespace mindspore { | |||
| class TestSoftmaxGradFp32 : public mindspore::CommonTest { | |||
| public: | |||
| TestSoftmaxGradFp32() {} | |||
| }; | |||
| void InitSoftMaxParam(SoftmaxParameter *softmax_param, int axis) { | |||
| softmax_param->axis_ = axis; | |||
| softmax_param->element_size_ = 1188; | |||
| softmax_param->n_dim_ = 4; | |||
| softmax_param->input_shape_[0] = 1; | |||
| softmax_param->input_shape_[1] = 9; | |||
| softmax_param->input_shape_[2] = 11; | |||
| softmax_param->input_shape_[3] = 12; | |||
| } | |||
| void InitSoftMaxParam(SoftmaxParameter *softmax_param, int axis, int n, int c, int h, int w) { | |||
| softmax_param->axis_ = axis; | |||
| softmax_param->element_size_ = n * c * h * w; | |||
| softmax_param->n_dim_ = 4; | |||
| softmax_param->input_shape_[0] = n; | |||
| softmax_param->input_shape_[1] = c; | |||
| softmax_param->input_shape_[2] = h; | |||
| softmax_param->input_shape_[3] = w; | |||
| } | |||
| TEST_F(TestSoftmaxGradFp32, SoftmaxGradAxis0) { | |||
| auto softmax_param = new SoftmaxParameter(); | |||
| // set parameters | |||
| InitSoftMaxParam(softmax_param, 0); | |||
| int inner_size = 1; | |||
| if (softmax_param->axis_ == -1) softmax_param->axis_ = softmax_param->n_dim_ - 1; | |||
| for (int i = softmax_param->axis_ + 1; i < softmax_param->n_dim_; i++) { | |||
| inner_size *= softmax_param->input_shape_[i]; | |||
| } | |||
| float *sum_data = new (std::nothrow) float[inner_size]; | |||
| float *sum_mul = new (std::nothrow) float[inner_size * softmax_param->input_shape_[softmax_param->axis_]]; | |||
| std::vector<int> shape = {1, 9, 11, 12}; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/softmax/softmaxgrad_yinput.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::string yt_path = "./test_data/softmax/softmaxgrad_yt_input.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| auto out_data = new float[softmax_param->element_size_]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| SoftmaxGrad(input_data, yt_data, out_data, sum_data, sum_mul, softmax_param); | |||
| } | |||
| int loop_count = 3; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| SoftmaxGrad(input_data, yt_data, out_data, sum_data, sum_mul, softmax_param); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/softmax/softmaxgrad_out.bin"; | |||
| auto res = lite::CompareRelativeOutput(out_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] yt_data; | |||
| delete[] out_data; | |||
| delete[] sum_data; | |||
| delete[] sum_mul; | |||
| delete softmax_param; | |||
| MS_LOG(INFO) << "SoftmaxGradAxis0 passed"; | |||
| } | |||
| TEST_F(TestSoftmaxGradFp32, SoftmaxGradAxis1) { | |||
| auto softmax_param = new SoftmaxParameter(); | |||
| // set parameters | |||
| InitSoftMaxParam(softmax_param, 1); | |||
| int inner_size = 1; | |||
| if (softmax_param->axis_ == -1) softmax_param->axis_ = softmax_param->n_dim_ - 1; | |||
| for (int i = softmax_param->axis_ + 1; i < softmax_param->n_dim_; i++) { | |||
| inner_size *= softmax_param->input_shape_[i]; | |||
| } | |||
| float *sum_data = new (std::nothrow) float[inner_size]; | |||
| float *sum_mul = new (std::nothrow) float[inner_size * softmax_param->input_shape_[softmax_param->axis_]]; | |||
| std::vector<int> shape = {1, 9, 11, 12}; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/softmax/softmaxgrad_1_yinput.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::string yt_path = "./test_data/softmax/softmaxgrad_1_yt_input.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| auto out_data = new float[softmax_param->element_size_]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| SoftmaxGrad(input_data, yt_data, out_data, sum_data, sum_mul, softmax_param); | |||
| } | |||
| int loop_count = 3; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| SoftmaxGrad(input_data, yt_data, out_data, sum_data, sum_mul, softmax_param); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/softmax/softmaxgrad_1_out.bin"; | |||
| // auto output_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| auto res = lite::CompareRelativeOutput(out_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] yt_data; | |||
| delete[] out_data; | |||
| delete[] sum_data; | |||
| delete[] sum_mul; | |||
| delete softmax_param; | |||
| MS_LOG(INFO) << "SoftmaxGradAxis1 passed"; | |||
| } | |||
| TEST_F(TestSoftmaxGradFp32, SoftmaxGradAxis2) { | |||
| auto softmax_param = new SoftmaxParameter(); | |||
| // set parameters | |||
| InitSoftMaxParam(softmax_param, 2); | |||
| int inner_size = 1; | |||
| if (softmax_param->axis_ == -1) softmax_param->axis_ = softmax_param->n_dim_ - 1; | |||
| for (int i = softmax_param->axis_ + 1; i < softmax_param->n_dim_; i++) { | |||
| inner_size *= softmax_param->input_shape_[i]; | |||
| } | |||
| float *sum_data = new (std::nothrow) float[inner_size]; | |||
| float *sum_mul = new (std::nothrow) float[inner_size * softmax_param->input_shape_[softmax_param->axis_]]; | |||
| std::vector<int> shape = {1, 9, 11, 12}; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/softmax/softmaxgrad_2_yinput.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::string yt_path = "./test_data/softmax/softmaxgrad_2_yt_input.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| auto out_data = new float[softmax_param->element_size_]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| SoftmaxGrad(input_data, yt_data, out_data, sum_data, sum_mul, softmax_param); | |||
| } | |||
| int loop_count = 3; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| SoftmaxGrad(input_data, yt_data, out_data, sum_data, sum_mul, softmax_param); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/softmax/softmaxgrad_2_out.bin"; | |||
| // auto output_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| auto res = lite::CompareRelativeOutput(out_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] yt_data; | |||
| delete[] out_data; | |||
| delete[] sum_data; | |||
| delete[] sum_mul; | |||
| delete softmax_param; | |||
| MS_LOG(INFO) << "SoftmaxGradAxis2 passed"; | |||
| } | |||
| TEST_F(TestSoftmaxGradFp32, SoftmaxGradAxis3) { | |||
| auto softmax_param = new SoftmaxParameter(); | |||
| // set parameters | |||
| InitSoftMaxParam(softmax_param, 3); | |||
| int inner_size = 1; | |||
| if (softmax_param->axis_ == -1) softmax_param->axis_ = softmax_param->n_dim_ - 1; | |||
| for (int i = softmax_param->axis_ + 1; i < softmax_param->n_dim_; i++) { | |||
| inner_size *= softmax_param->input_shape_[i]; | |||
| } | |||
| float *sum_data = new (std::nothrow) float[inner_size]; | |||
| float *sum_mul = new (std::nothrow) float[inner_size * softmax_param->input_shape_[softmax_param->axis_]]; | |||
| std::vector<int> shape = {1, 9, 11, 12}; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/softmax/softmaxgrad_3_yinput.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::string yt_path = "./test_data/softmax/softmaxgrad_3_yt_input.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| auto out_data = new float[softmax_param->element_size_]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| SoftmaxGrad(input_data, yt_data, out_data, sum_data, sum_mul, softmax_param); | |||
| } | |||
| int loop_count = 3; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| SoftmaxGrad(input_data, yt_data, out_data, sum_data, sum_mul, softmax_param); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/softmax/softmaxgrad_3_out.bin"; | |||
| // auto output_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| auto res = lite::CompareRelativeOutput(out_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] yt_data; | |||
| delete[] out_data; | |||
| delete[] sum_data; | |||
| delete[] sum_mul; | |||
| delete softmax_param; | |||
| MS_LOG(INFO) << "SoftmaxGradAxis3 passed"; | |||
| } | |||
| TEST_F(TestSoftmaxGradFp32, SoftmaxGradAxisMinus1) { | |||
| auto softmax_param = new SoftmaxParameter(); | |||
| // set parameters | |||
| InitSoftMaxParam(softmax_param, -1); | |||
| int inner_size = 1; | |||
| if (softmax_param->axis_ == -1) softmax_param->axis_ = softmax_param->n_dim_ - 1; | |||
| for (int i = softmax_param->axis_ + 1; i < softmax_param->n_dim_; i++) { | |||
| inner_size *= softmax_param->input_shape_[i]; | |||
| } | |||
| float *sum_data = new (std::nothrow) float[inner_size]; | |||
| float *sum_mul = new (std::nothrow) float[inner_size * softmax_param->input_shape_[softmax_param->axis_]]; | |||
| std::vector<int> shape = {1, 9, 11, 12}; | |||
| size_t input_size; | |||
| std::string input_path = "./test_data/softmax/softmaxgrad_-1_yinput.bin"; | |||
| auto input_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| std::string yt_path = "./test_data/softmax/softmaxgrad_-1_yt_input.bin"; | |||
| auto yt_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(yt_path.c_str(), &input_size)); | |||
| // runtime part | |||
| printf("Calculating runtime cost...\n"); | |||
| uint64_t time_avg = 0; | |||
| auto out_data = new float[softmax_param->element_size_]; | |||
| // warm up loop | |||
| for (int i = 0; i < 3; i++) { | |||
| SoftmaxGrad(input_data, yt_data, out_data, sum_data, sum_mul, softmax_param); | |||
| } | |||
| int loop_count = 3; | |||
| auto time_start = mindspore::lite::GetTimeUs(); | |||
| for (int i = 0; i < loop_count; i++) { | |||
| SoftmaxGrad(input_data, yt_data, out_data, sum_data, sum_mul, softmax_param); | |||
| } | |||
| auto time_end = mindspore::lite::GetTimeUs(); | |||
| auto cost = time_end - time_start; | |||
| time_avg = cost / loop_count; | |||
| printf("single thread running time : %f ms\n", time_avg / 1000.0f); | |||
| std::string output_path = "./test_data/softmax/softmaxgrad_-1_out.bin"; | |||
| // auto output_data = reinterpret_cast<float *>(mindspore::lite::ReadFile(input_path.c_str(), &input_size)); | |||
| auto res = lite::CompareRelativeOutput(out_data, output_path); | |||
| EXPECT_EQ(res, 0); | |||
| delete[] input_data; | |||
| delete[] yt_data; | |||
| delete[] out_data; | |||
| delete[] sum_data; | |||
| delete[] sum_mul; | |||
| delete softmax_param; | |||
| MS_LOG(INFO) << "SoftmaxGradAxisMinus1 passed"; | |||
| } | |||
| } // namespace mindspore | |||