1 /**
2 * Copyright 2020 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/runtime/kernel/arm/fp32/convolution_depthwise_fp32.h"
18 #include "include/errorcode.h"
19
20 using mindspore::lite::RET_ERROR;
21 using mindspore::lite::RET_INFER_INVALID;
22 using mindspore::lite::RET_OK;
23
24 namespace mindspore::kernel {
Init()25 int ConvolutionDepthwiseCPUKernel::Init() {
26 CHECK_LESS_RETURN(in_tensors_.size(), C2NUM);
27 CHECK_LESS_RETURN(out_tensors_.size(), 1);
28 if (op_parameter_->is_train_session_) {
29 auto weight_tensor = in_tensors_.at(kWeightIndex);
30 CHECK_NULL_RETURN(weight_tensor);
31 int pack_weight_size = weight_tensor->Batch() * weight_tensor->Height() * weight_tensor->Width();
32 if (pack_weight_size >= std::numeric_limits<int>::max() / static_cast<int>(sizeof(float))) {
33 MS_LOG(ERROR) << "pack_weight_size is invalid, pack_weight_size: " << pack_weight_size;
34 return RET_ERROR;
35 }
36 set_workspace_size(pack_weight_size * sizeof(float));
37 }
38 auto ret = InitConvWeightBias();
39 if (ret != RET_OK) {
40 MS_LOG(ERROR) << "Convolution depthwise fp32 InitConvWeightBias failed.";
41 return RET_ERROR;
42 }
43 if (!InferShapeDone()) {
44 return RET_OK;
45 }
46 return ReSize();
47 }
48
ReSize()49 int ConvolutionDepthwiseCPUKernel::ReSize() {
50 auto ret = ConvolutionBaseCPUKernel::Init();
51 if (ret != RET_OK) {
52 MS_LOG(ERROR) << "ConvolutionBaseCPUKernel::Init() return is:" << ret;
53 return ret;
54 }
55 conv_param_->thread_num_ = MSMIN(thread_count_, conv_param_->output_h_);
56 if (conv_param_->thread_num_ <= 0) {
57 MS_LOG(ERROR) << "conv_param_->thread_num_ must be greater than 0!";
58 return RET_ERROR;
59 }
60 return RET_OK;
61 }
62
DoExecute(int task_id)63 int ConvolutionDepthwiseCPUKernel::DoExecute(int task_id) {
64 auto ret = ConvDw(output_ptr_, input_ptr_, reinterpret_cast<float *>(packed_weight_),
65 reinterpret_cast<float *>(bias_data_), conv_param_, task_id);
66 return ret;
67 }
68
ConvDwRun(void * cdata,int task_id,float lhs_scale,float rhs_scale)69 int ConvDwRun(void *cdata, int task_id, float lhs_scale, float rhs_scale) {
70 auto conv_dw = reinterpret_cast<ConvolutionDepthwiseCPUKernel *>(cdata);
71 auto ret = conv_dw->DoExecute(task_id);
72 if (ret != RET_OK) {
73 MS_LOG(ERROR) << "ConvolutionDepthwiseRun error task_id[" << task_id << "] error_code[" << ret << "]";
74 return RET_ERROR;
75 }
76 return RET_OK;
77 }
78
Run()79 int ConvolutionDepthwiseCPUKernel::Run() {
80 if (RepackWeight() != RET_OK) {
81 MS_LOG(ERROR) << "Repack weight failed.";
82 return RET_ERROR;
83 }
84
85 auto input_tensor = in_tensors_.at(kInputIndex);
86 input_ptr_ = reinterpret_cast<float *>(input_tensor->data());
87 MS_CHECK_FALSE(input_ptr_ == nullptr, RET_ERROR);
88 auto output_tensor = out_tensors_.at(kOutputIndex);
89 output_ptr_ = reinterpret_cast<float *>(output_tensor->data());
90 MS_CHECK_FALSE(output_ptr_ == nullptr, RET_ERROR);
91
92 auto ret = ParallelLaunch(this->ms_context_, ConvDwRun, this, conv_param_->thread_num_);
93 if (ret != RET_OK) {
94 MS_LOG(ERROR) << "ConvDwRun error: error_code[" << ret << "]";
95 return RET_ERROR;
96 }
97 return RET_OK;
98 }
99
PackWeight()100 void ConvolutionDepthwiseCPUKernel::PackWeight() {
101 auto weight_tensor = in_tensors_.at(kWeightIndex);
102 void *origin_weight = (op_parameter_->is_train_session_) ? weight_tensor->data() : origin_weight_;
103 MS_ASSERT(origin_weight != nullptr);
104 PackWeightKHWToHWKFp32(reinterpret_cast<float *>(origin_weight), reinterpret_cast<float *>(packed_weight_),
105 weight_tensor->Height() * weight_tensor->Width(), weight_tensor->Batch());
106 }
107
MallocWeightBiasData()108 int ConvolutionDepthwiseCPUKernel::MallocWeightBiasData() {
109 auto weight_tensor = in_tensors_.at(kWeightIndex);
110 int channel = weight_tensor->Batch();
111 int pack_weight_size = weight_tensor->Batch() * weight_tensor->Height() * weight_tensor->Width();
112 if (pack_weight_size >= std::numeric_limits<int>::max() / static_cast<int>(sizeof(float))) {
113 MS_LOG(ERROR) << "pack_weight_size is invalid, pack_weight_size: " << pack_weight_size;
114 return RET_ERROR;
115 }
116 if (!op_parameter_->is_train_session_) {
117 packed_weight_ = malloc(pack_weight_size * sizeof(float));
118 if (packed_weight_ == nullptr) {
119 MS_LOG(ERROR) << "Malloc buffer failed.";
120 return RET_ERROR;
121 }
122 }
123
124 bias_data_ = malloc(channel * sizeof(float));
125 if (bias_data_ == nullptr) {
126 MS_LOG(ERROR) << "Malloc buffer failed.";
127 return RET_ERROR;
128 }
129 memset(bias_data_, 0, channel * sizeof(float));
130 return RET_OK;
131 }
132 } // namespace mindspore::kernel
133