Browse Source

remove train on icsl

pull/8523/head
xutianchun 5 years ago
parent
commit
754bb016ba
61 changed files with 2 additions and 8995 deletions
  1. +0
    -3
      mindspore/lite/src/CMakeLists.txt
  2. +0
    -131
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/activation_grad.cc
  3. +0
    -46
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/activation_grad.h
  4. +0
    -112
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/adam.cc
  5. +0
    -44
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/adam.h
  6. +0
    -103
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/apply_momentum.cc
  7. +0
    -44
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/apply_momentum.h
  8. +0
    -243
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/arithmetic_grad.cc
  9. +0
    -90
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/arithmetic_grad.h
  10. +0
    -108
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/arithmetic_self_grad.cc
  11. +0
    -46
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/arithmetic_self_grad.h
  12. +0
    -85
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/assign.cc
  13. +0
    -39
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/assign.h
  14. +0
    -111
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/bias_grad.cc
  15. +0
    -45
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/bias_grad.h
  16. +0
    -122
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/bn_grad.cc
  17. +0
    -38
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/bn_grad.h
  18. +0
    -150
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution.cc
  19. +0
    -44
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution.h
  20. +0
    -154
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution_grad_filter.cc
  21. +0
    -41
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution_grad_filter.h
  22. +0
    -155
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution_grad_input.cc
  23. +0
    -39
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution_grad_input.h
  24. +0
    -150
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/deconvolution_grad_filter.cc
  25. +0
    -40
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/deconvolution_grad_filter.h
  26. +0
    -46
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/make_tuple.h
  27. +0
    -95
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/neg_grad.cc
  28. +0
    -43
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/neg_grad.h
  29. +0
    -131
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/pooling_grad.cc
  30. +0
    -47
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/pooling_grad.h
  31. +0
    -104
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/power_grad.cc
  32. +0
    -51
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/power_grad.h
  33. +0
    -119
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/sgd.cc
  34. +0
    -44
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/sgd.h
  35. +0
    -153
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/softmax_cross_entropy_with_logits.cc
  36. +0
    -53
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/softmax_cross_entropy_with_logits.h
  37. +0
    -112
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/softmax_grad.cc
  38. +0
    -46
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/softmax_grad.h
  39. +0
    -176
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/sparse_softmax_cross_entropy_with_logits.cc
  40. +0
    -55
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/sparse_softmax_cross_entropy_with_logits.h
  41. +0
    -98
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/tuple_getitem.cc
  42. +0
    -45
      mindspore/lite/src/runtime/kernel/arm/fp32_grad/tuple_getitem.h
  43. +0
    -33
      mindspore/lite/src/train/loss_kernel.h
  44. +0
    -126
      mindspore/lite/src/train/train_model.cc
  45. +0
    -435
      mindspore/lite/src/train/train_populate_parameter.cc
  46. +0
    -27
      mindspore/lite/src/train/train_populate_parameter.h
  47. +0
    -292
      mindspore/lite/src/train/train_session.cc
  48. +0
    -100
      mindspore/lite/src/train/train_session.h
  49. +0
    -4
      mindspore/lite/test/CMakeLists.txt
  50. +1
    -1
      mindspore/lite/test/models_tflite.cfg
  51. +1
    -5
      mindspore/lite/test/run_train_ut.sh
  52. +0
    -316
      mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/activation_grad_fp32_tests.cc
  53. +0
    -636
      mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/arithmetic_grad_fp32_tests.cc
  54. +0
    -75
      mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/bias_grad_fp32_tests.cc
  55. +0
    -205
      mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/bn_grad_fp32_test.cc
  56. +0
    -777
      mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/convolution_grad_fp32_tests.cc
  57. +0
    -628
      mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/deconvolution_grad_fp32_tests.cc
  58. +0
    -659
      mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/network_test.cc
  59. +0
    -619
      mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/pooling_grad_fp32_tests.cc
  60. +0
    -106
      mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/softmax_crossentropy_fp32_tests.cc
  61. +0
    -350
      mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/softmax_grad_fp32_tests.cc

+ 0
- 3
mindspore/lite/src/CMakeLists.txt View File

@@ -58,9 +58,6 @@ if (SUPPORT_TRAIN)
set(LITE_SRC set(LITE_SRC
${LITE_SRC} ${LITE_SRC}
${ANF_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 ${CMAKE_CURRENT_SOURCE_DIR}/lite_session.cc
) )
endif () endif ()


+ 0
- 131
mindspore/lite/src/runtime/kernel/arm/fp32_grad/activation_grad.cc View File

@@ -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

+ 0
- 46
mindspore/lite/src/runtime/kernel/arm/fp32_grad/activation_grad.h View File

@@ -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_

+ 0
- 112
mindspore/lite/src/runtime/kernel/arm/fp32_grad/adam.cc View File

@@ -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

+ 0
- 44
mindspore/lite/src/runtime/kernel/arm/fp32_grad/adam.h View File

@@ -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_

+ 0
- 103
mindspore/lite/src/runtime/kernel/arm/fp32_grad/apply_momentum.cc View File

@@ -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

+ 0
- 44
mindspore/lite/src/runtime/kernel/arm/fp32_grad/apply_momentum.h View File

@@ -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_

+ 0
- 243
mindspore/lite/src/runtime/kernel/arm/fp32_grad/arithmetic_grad.cc View File

@@ -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

+ 0
- 90
mindspore/lite/src/runtime/kernel/arm/fp32_grad/arithmetic_grad.h View File

@@ -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_

+ 0
- 108
mindspore/lite/src/runtime/kernel/arm/fp32_grad/arithmetic_self_grad.cc View File

@@ -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

+ 0
- 46
mindspore/lite/src/runtime/kernel/arm/fp32_grad/arithmetic_self_grad.h View File

@@ -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_

+ 0
- 85
mindspore/lite/src/runtime/kernel/arm/fp32_grad/assign.cc View File

@@ -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

+ 0
- 39
mindspore/lite/src/runtime/kernel/arm/fp32_grad/assign.h View File

@@ -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_

+ 0
- 111
mindspore/lite/src/runtime/kernel/arm/fp32_grad/bias_grad.cc View File

@@ -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

+ 0
- 45
mindspore/lite/src/runtime/kernel/arm/fp32_grad/bias_grad.h View File

@@ -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_

+ 0
- 122
mindspore/lite/src/runtime/kernel/arm/fp32_grad/bn_grad.cc View File

@@ -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

+ 0
- 38
mindspore/lite/src/runtime/kernel/arm/fp32_grad/bn_grad.h View File

@@ -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_

+ 0
- 150
mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution.cc View File

@@ -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

+ 0
- 44
mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution.h View File

@@ -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_

+ 0
- 154
mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution_grad_filter.cc View File

@@ -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

+ 0
- 41
mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution_grad_filter.h View File

@@ -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_

+ 0
- 155
mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution_grad_input.cc View File

@@ -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

+ 0
- 39
mindspore/lite/src/runtime/kernel/arm/fp32_grad/convolution_grad_input.h View File

@@ -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_

+ 0
- 150
mindspore/lite/src/runtime/kernel/arm/fp32_grad/deconvolution_grad_filter.cc View File

@@ -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

+ 0
- 40
mindspore/lite/src/runtime/kernel/arm/fp32_grad/deconvolution_grad_filter.h View File

@@ -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_

+ 0
- 46
mindspore/lite/src/runtime/kernel/arm/fp32_grad/make_tuple.h View File

@@ -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_

+ 0
- 95
mindspore/lite/src/runtime/kernel/arm/fp32_grad/neg_grad.cc View File

@@ -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

+ 0
- 43
mindspore/lite/src/runtime/kernel/arm/fp32_grad/neg_grad.h View File

@@ -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_

+ 0
- 131
mindspore/lite/src/runtime/kernel/arm/fp32_grad/pooling_grad.cc View File

@@ -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

+ 0
- 47
mindspore/lite/src/runtime/kernel/arm/fp32_grad/pooling_grad.h View File

@@ -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_

+ 0
- 104
mindspore/lite/src/runtime/kernel/arm/fp32_grad/power_grad.cc View File

@@ -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

+ 0
- 51
mindspore/lite/src/runtime/kernel/arm/fp32_grad/power_grad.h View File

@@ -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_

+ 0
- 119
mindspore/lite/src/runtime/kernel/arm/fp32_grad/sgd.cc View File

@@ -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

+ 0
- 44
mindspore/lite/src/runtime/kernel/arm/fp32_grad/sgd.h View File

@@ -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_

+ 0
- 153
mindspore/lite/src/runtime/kernel/arm/fp32_grad/softmax_cross_entropy_with_logits.cc View File

@@ -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

+ 0
- 53
mindspore/lite/src/runtime/kernel/arm/fp32_grad/softmax_cross_entropy_with_logits.h View File

@@ -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_

+ 0
- 112
mindspore/lite/src/runtime/kernel/arm/fp32_grad/softmax_grad.cc View File

@@ -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

+ 0
- 46
mindspore/lite/src/runtime/kernel/arm/fp32_grad/softmax_grad.h View File

@@ -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_

+ 0
- 176
mindspore/lite/src/runtime/kernel/arm/fp32_grad/sparse_softmax_cross_entropy_with_logits.cc View File

@@ -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

+ 0
- 55
mindspore/lite/src/runtime/kernel/arm/fp32_grad/sparse_softmax_cross_entropy_with_logits.h View File

@@ -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_

+ 0
- 98
mindspore/lite/src/runtime/kernel/arm/fp32_grad/tuple_getitem.cc View File

@@ -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

+ 0
- 45
mindspore/lite/src/runtime/kernel/arm/fp32_grad/tuple_getitem.h View File

@@ -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_

+ 0
- 33
mindspore/lite/src/train/loss_kernel.h View File

@@ -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_

+ 0
- 126
mindspore/lite/src/train/train_model.cc View File

@@ -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

+ 0
- 435
mindspore/lite/src/train/train_populate_parameter.cc View File

@@ -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

+ 0
- 27
mindspore/lite/src/train/train_populate_parameter.h View File

@@ -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_

+ 0
- 292
mindspore/lite/src/train/train_session.cc View File

@@ -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

+ 0
- 100
mindspore/lite/src/train/train_session.h View File

@@ -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_

+ 0
- 4
mindspore/lite/test/CMakeLists.txt View File

@@ -214,10 +214,6 @@ endif()
if (SUPPORT_TRAIN) if (SUPPORT_TRAIN)
set(TEST_LITE_SRC set(TEST_LITE_SRC
${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 ${LITE_DIR}/src/lite_session.cc
) )
else() else()


+ 1
- 1
mindspore/lite/test/models_tflite.cfg View File

@@ -58,7 +58,7 @@ inception_resnet_v2.tflite
ml_ocr_latin.tflite ml_ocr_latin.tflite
hiai_PoseEstimation_Pcm.tflite hiai_PoseEstimation_Pcm.tflite
hiai_ssd_mobilenetv2_object.tflite hiai_ssd_mobilenetv2_object.tflite
hiai_cv_focusShootOCRModel_02.tflite
#hiai_cv_focusShootOCRModel_02.tflite
hiai_cv_poseEstimation.tflite hiai_cv_poseEstimation.tflite
inception_v4.tflite inception_v4.tflite
mtk_model_normalize_object_scene_ps_20200519_f16.tflite mtk_model_normalize_object_scene_ps_20200519_f16.tflite


+ 1
- 5
mindspore/lite/test/run_train_ut.sh View File

@@ -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

+ 0
- 316
mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/activation_grad_fp32_tests.cc View File

@@ -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

+ 0
- 636
mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/arithmetic_grad_fp32_tests.cc View File

@@ -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

+ 0
- 75
mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/bias_grad_fp32_tests.cc View File

@@ -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

+ 0
- 205
mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/bn_grad_fp32_test.cc View File

@@ -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

+ 0
- 777
mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/convolution_grad_fp32_tests.cc View File

@@ -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

+ 0
- 628
mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/deconvolution_grad_fp32_tests.cc View File

@@ -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

+ 0
- 659
mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/network_test.cc View File

@@ -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

+ 0
- 619
mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/pooling_grad_fp32_tests.cc View File

@@ -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

+ 0
- 106
mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/softmax_crossentropy_fp32_tests.cc View File

@@ -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

+ 0
- 350
mindspore/lite/test/ut/src/runtime/kernel/arm/fp32_grad/softmax_grad_fp32_tests.cc View File

@@ -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

Loading…
Cancel
Save