From: @probiotics_53 Reviewed-by: @zhang_xue_tong,@zhanghaibo5 Signed-off-by: @zhang_xue_tongpull/14652/MERGE
| @@ -0,0 +1,62 @@ | |||
| /** | |||
| * 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 "ops/log_softmax.h" | |||
| #include <string> | |||
| #include <algorithm> | |||
| #include <memory> | |||
| #include <set> | |||
| #include <vector> | |||
| #include "ops/op_utils.h" | |||
| #include "utils/check_convert_utils.h" | |||
| #include "abstract/primitive_infer_map.h" | |||
| namespace mindspore { | |||
| namespace ops { | |||
| void LogSoftmax::set_axis(const int64_t axis) { this->AddAttr(kAxis, MakeValue(axis)); } | |||
| int64_t LogSoftmax::get_axis() const { return GetValue<int64_t>(GetAttr(kAxis)); } | |||
| void LogSoftmax::Init(const int64_t axis) { this->set_axis(axis); } | |||
| abstract::ShapePtr LogSoftmaxInferShape(const PrimitivePtr &primitive, const std::vector<AbstractBasePtr> &input_args) { | |||
| MS_EXCEPTION_IF_NULL(primitive); | |||
| auto LogSoftmax_prim = primitive->cast<PrimLogSoftmaxPtr>(); | |||
| MS_EXCEPTION_IF_NULL(LogSoftmax_prim); | |||
| auto op_name = LogSoftmax_prim->name(); | |||
| auto axis = LogSoftmax_prim->get_axis(); | |||
| auto in_shape = CheckAndConvertUtils::ConvertShapePtrToShape("input_shape", input_args[0]->GetShapeTrack(), op_name); | |||
| auto rank = SizeToLong(in_shape.size()); | |||
| CheckAndConvertUtils::CheckInRange<int64_t>("axis", axis, kIncludeLeft, {-rank, rank}, op_name); | |||
| return std::make_shared<abstract::Shape>(in_shape); | |||
| } | |||
| TypePtr LogSoftmaxInferType(const PrimitivePtr &prim, const std::vector<AbstractBasePtr> &input_args) { | |||
| if (std::any_of(input_args.begin(), input_args.end(), [](const AbstractBasePtr &a) { return a == nullptr; })) { | |||
| MS_LOG(EXCEPTION) << "nullptr"; | |||
| } | |||
| const std::set<TypePtr> valid_types = {kFloat16, kFloat32}; | |||
| return CheckAndConvertUtils::CheckTensorTypeValid("x", input_args[0]->BuildType(), valid_types, prim->name()); | |||
| } | |||
| AbstractBasePtr LogSoftmaxInfer(const abstract::AnalysisEnginePtr &, const PrimitivePtr &primitive, | |||
| const std::vector<AbstractBasePtr> &input_args) { | |||
| return std::make_shared<abstract::AbstractTensor>(LogSoftmaxInferType(primitive, input_args), | |||
| LogSoftmaxInferShape(primitive, input_args)->shape()); | |||
| } | |||
| REGISTER_PRIMITIVE_C(kNameLogSoftmax, LogSoftmax); | |||
| } // namespace ops | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,47 @@ | |||
| /** | |||
| * 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_CORE_OPS_LOG_SOFTMAX_H_ | |||
| #define MINDSPORE_CORE_OPS_LOG_SOFTMAX_H_ | |||
| #include <map> | |||
| #include <vector> | |||
| #include <string> | |||
| #include <memory> | |||
| #include "ops/primitive_c.h" | |||
| #include "abstract/abstract_value.h" | |||
| #include "utils/check_convert_utils.h" | |||
| namespace mindspore { | |||
| namespace ops { | |||
| constexpr auto kNameLogSoftmax = "LogSoftmax"; | |||
| class LogSoftmax : public PrimitiveC { | |||
| public: | |||
| LogSoftmax() : PrimitiveC(kNameLogSoftmax) { InitIOName({"x"}, {"output"}); } | |||
| ~LogSoftmax() = default; | |||
| MS_DECLARE_PARENT(LogSoftmax, PrimitiveC); | |||
| void Init(const int64_t axis = -1); | |||
| void set_axis(const int64_t axis); | |||
| int64_t get_axis() const; | |||
| }; | |||
| AbstractBasePtr LogSoftmaxInfer(const abstract::AnalysisEnginePtr &, const PrimitivePtr &primitive, | |||
| const std::vector<AbstractBasePtr> &input_args); | |||
| using PrimLogSoftmaxPtr = std::shared_ptr<LogSoftmax>; | |||
| } // namespace ops | |||
| } // namespace mindspore | |||
| #endif // MINDSPORE_CORE_OPS_LOG_SOFTMAX_H_ | |||
| @@ -0,0 +1,91 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #include "nnacl/fp16/log_softmax_fp16.h" | |||
| #include <math.h> | |||
| #include <float.h> | |||
| #include "nnacl/fp16/softmax_fp16.h" | |||
| #include "nnacl/fp16/exp_fp16.h" | |||
| void LogSoftmaxLastAxisFp16(const float16_t *src, float16_t *dst, float16_t *exp_data, int batch, int channel) { | |||
| SoftmaxNormFp16(src, dst, batch, channel); | |||
| ExpFp16(dst, exp_data, batch * channel); | |||
| int cur_batch_offset = 0; | |||
| for (int i = 0; i < batch; i++, cur_batch_offset += channel) { | |||
| float16_t sum = 0; | |||
| int j = 0; | |||
| #ifdef ENABLE_NEON | |||
| float16x8_t sum8 = vdupq_n_f16(0); | |||
| int count = (channel / C8NUM) * C8NUM; | |||
| for (; j < count; j += C8NUM) { | |||
| sum8 = vaddq_f16(sum8, vld1q_f16(exp_data + cur_batch_offset + j)); | |||
| } | |||
| sum = sum8[0] + sum8[1] + sum8[2] + sum8[3] + sum8[4] + sum8[5] + sum8[6] + sum8[7]; | |||
| #endif | |||
| for (; j < channel; j++) { | |||
| sum += exp_data[cur_batch_offset + j]; | |||
| } | |||
| for (int k = 0; k < channel; k++) { | |||
| dst[cur_batch_offset + k] = dst[cur_batch_offset + k] - log(sum); | |||
| } | |||
| } | |||
| } | |||
| // output = (input - reduce_max(input, axis)) - log(reduce_sum(exp(input - reduce_max(input, axis)), axis)) | |||
| void LogSoftmaxFp16(const float16_t *input_ptr, float16_t *output_ptr, float16_t *sum_data, | |||
| SoftmaxParameter *parameter) { | |||
| int axis = parameter->axis_; | |||
| int n_dim = parameter->n_dim_; | |||
| int *input_shape = parameter->input_shape_; | |||
| int inner_size = 1; | |||
| int outter_size = 1; | |||
| for (int i = 0; i < axis; i++) { | |||
| outter_size *= input_shape[i]; | |||
| } | |||
| for (int i = axis + 1; i < n_dim; i++) { | |||
| inner_size *= input_shape[i]; | |||
| } | |||
| for (int i = 0; i < outter_size; i++) { | |||
| int outter_offset = i * input_shape[axis] * inner_size; | |||
| int sum_outter_offset = i * inner_size; | |||
| for (int k = 0; k < inner_size; k++) { | |||
| int inner_offset = outter_offset + k; | |||
| float16_t max_data = input_ptr[inner_offset]; | |||
| sum_data[k + sum_outter_offset] = 0; | |||
| for (int j = 0; j < input_shape[axis]; j++) { | |||
| int axis_offset = inner_offset + j * inner_size; | |||
| max_data = max_data > input_ptr[axis_offset] ? max_data : input_ptr[axis_offset]; | |||
| } | |||
| for (int j = 0; j < input_shape[axis]; j++) { | |||
| int axis_offset = inner_offset + j * inner_size; | |||
| output_ptr[axis_offset] = input_ptr[axis_offset] - max_data; | |||
| sum_data[k + sum_outter_offset] += exp(output_ptr[axis_offset]); | |||
| } | |||
| } | |||
| } | |||
| for (int i = 0; i < outter_size; i++) { | |||
| int outter_offset = i * input_shape[axis] * inner_size; | |||
| int sum_outter_offset = i * inner_size; | |||
| for (int j = 0; j < input_shape[axis]; j++) { | |||
| int axis_offset = outter_offset + j * inner_size; | |||
| for (int k = 0; k < inner_size; k++) { | |||
| int inner_offset = axis_offset + k; | |||
| output_ptr[inner_offset] = output_ptr[inner_offset] - log(sum_data[k + sum_outter_offset]); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,35 @@ | |||
| /** | |||
| * Copyright 2021 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_NNACL_FP16_LOG_SOFTMAX_FP16_H_ | |||
| #define MINDSPORE_LITE_NNACL_FP16_LOG_SOFTMAX_FP16_H_ | |||
| #include "nnacl/op_base.h" | |||
| #include "nnacl/softmax_parameter.h" | |||
| #ifdef ENABLE_NEON | |||
| #include <arm_neon.h> | |||
| #endif | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| void LogSoftmaxLastAxisFp16(const float16_t *src, float16_t *dst, float16_t *exp_data, int batch, int channel); | |||
| void LogSoftmaxFp16(const float16_t *input_ptr, float16_t *output_ptr, float16_t *sum_data, | |||
| SoftmaxParameter *parameter); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif // MINDSPORE_LITE_NNACL_FP16_SOFTMAX_FP16_H_ | |||
| @@ -110,6 +110,7 @@ void SoftmaxFp16(const float16_t *input_ptr, float16_t *output_ptr, float16_t *s | |||
| for (int k = 0; k < inner_size; k++) { | |||
| int inner_offset = outter_offset + k; | |||
| float16_t max_data = input_ptr[inner_offset]; | |||
| sum_data[k + sum_outter_offset] = 0; | |||
| for (int j = 0; j < input_shape[axis]; j++) { | |||
| int axis_offset = inner_offset + j * inner_size; | |||
| max_data = max_data > input_ptr[axis_offset] ? max_data : input_ptr[axis_offset]; | |||
| @@ -25,6 +25,7 @@ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| void SoftmaxNormFp16(const float16_t *src, float16_t *dst, int batch, int channel); | |||
| void SoftmaxFp16(const float16_t *input_ptr, float16_t *output_ptr, float16_t *sum_data, SoftmaxParameter *parameter); | |||
| void SoftmaxLastAxisFp16(const float16_t *src, float16_t *dst, int batch, int channel); | |||
| #ifdef __cplusplus | |||
| @@ -0,0 +1,89 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #include "nnacl/fp32/log_softmax_fp32.h" | |||
| #include <math.h> | |||
| #include <float.h> | |||
| #include "nnacl/fp32/softmax_fp32.h" | |||
| #include "nnacl/fp32/exp_fp32.h" | |||
| void LogSoftmaxLastAxis(const float *src, float *dst, float *exp_data, int batch, int channel) { | |||
| SoftmaxNorm(src, dst, batch, channel); | |||
| ExpFp32(dst, exp_data, batch * channel); | |||
| int cur_batch_offset = 0; | |||
| for (int i = 0; i < batch; i++, cur_batch_offset += channel) { | |||
| float sum = 0; | |||
| int j = 0; | |||
| #ifdef ENABLE_NEON | |||
| float32x4_t sum4 = vdupq_n_f32(0); | |||
| int count = (channel / C4NUM) * C4NUM; | |||
| for (; j < count; j += C4NUM) { | |||
| sum4 = vaddq_f32(sum4, vld1q_f32(exp_data + cur_batch_offset + j)); | |||
| } | |||
| sum = sum4[0] + sum4[1] + sum4[2] + sum4[3]; | |||
| #endif | |||
| for (; j < channel; j++) { | |||
| sum += exp_data[cur_batch_offset + j]; | |||
| } | |||
| for (int k = 0; k < channel; k++) { | |||
| dst[cur_batch_offset + k] = dst[cur_batch_offset + k] - log(sum); | |||
| } | |||
| } | |||
| } | |||
| // output = (input - reduce_max(input, axis)) - log(reduce_sum(exp(input - reduce_max(input, axis)), axis)) | |||
| void LogSoftmax(const float *input_ptr, float *output_ptr, float *sum_data, const SoftmaxParameter *parameter) { | |||
| int axis = parameter->axis_; | |||
| int n_dim = parameter->n_dim_; | |||
| const int *input_shape = parameter->input_shape_; | |||
| int inner_size = 1; | |||
| int outter_size = 1; | |||
| for (int i = 0; i < axis; i++) { | |||
| outter_size *= input_shape[i]; | |||
| } | |||
| for (int i = axis + 1; i < n_dim; i++) { | |||
| inner_size *= input_shape[i]; | |||
| } | |||
| for (int i = 0; i < outter_size; i++) { | |||
| int outter_offset = i * input_shape[axis] * inner_size; | |||
| int sum_outter_offset = i * inner_size; | |||
| for (int k = 0; k < inner_size; k++) { | |||
| int inner_offset = outter_offset + k; | |||
| float max_data = input_ptr[inner_offset]; | |||
| sum_data[k + sum_outter_offset] = 0; | |||
| for (int j = 0; j < input_shape[axis]; j++) { | |||
| int axis_offset = inner_offset + j * inner_size; | |||
| max_data = max_data > input_ptr[axis_offset] ? max_data : input_ptr[axis_offset]; | |||
| } | |||
| for (int j = 0; j < input_shape[axis]; j++) { | |||
| int axis_offset = inner_offset + j * inner_size; | |||
| output_ptr[axis_offset] = input_ptr[axis_offset] - max_data; | |||
| sum_data[k + sum_outter_offset] += exp(output_ptr[axis_offset]); | |||
| } | |||
| } | |||
| } | |||
| for (int i = 0; i < outter_size; i++) { | |||
| int outter_offset = i * input_shape[axis] * inner_size; | |||
| int sum_outter_offset = i * inner_size; | |||
| for (int j = 0; j < input_shape[axis]; j++) { | |||
| int axis_offset = outter_offset + j * inner_size; | |||
| for (int k = 0; k < inner_size; k++) { | |||
| int inner_offset = axis_offset + k; | |||
| output_ptr[inner_offset] = output_ptr[inner_offset] - log(sum_data[k + sum_outter_offset]); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,31 @@ | |||
| /** | |||
| * Copyright 2021 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_NNACL_FP32_LOG_SOFTMAX_H_ | |||
| #define MINDSPORE_LITE_NNACL_FP32_LOG_SOFTMAX_H_ | |||
| #include "nnacl/op_base.h" | |||
| #include "nnacl/softmax_parameter.h" | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| void LogSoftmax(const float *input_ptr, float *output_ptr, float *sum_data, const SoftmaxParameter *parameter); | |||
| void LogSoftmaxLastAxis(const float *src, float *dst, float *exp_data, int batch, int channel); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif // MINDSPORE_LITE_NNACL_FP32_LOG_SOFTMAX_H_ | |||
| @@ -121,6 +121,7 @@ void Softmax(const float *input_ptr, float *output_ptr, float *sum_data, const S | |||
| for (int k = 0; k < inner_size; k++) { | |||
| int inner_offset = outter_offset + k; | |||
| float max_data = input_ptr[inner_offset]; | |||
| sum_data[k + sum_outter_offset] = 0; | |||
| for (int j = 0; j < input_shape[axis]; j++) { | |||
| int axis_offset = inner_offset + j * inner_size; | |||
| max_data = max_data > input_ptr[axis_offset] ? max_data : input_ptr[axis_offset]; | |||
| @@ -24,6 +24,7 @@ extern "C" { | |||
| #endif | |||
| void Softmax(const float *input_ptr, float *output_ptr, float *sum_data, const SoftmaxParameter *parameter); | |||
| void SoftmaxLastAxis(const float *src, float *dst, int batch, int channel); | |||
| void SoftmaxNorm(const float *src, float *dst, int batch, int channel); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| @@ -213,8 +213,9 @@ enum PrimType { | |||
| PrimType_LayerNormGrad = 186, | |||
| PrimType_ResizeGrad = 187, | |||
| PrimType_Splice = 188, | |||
| PrimType_LogSoftmax = 189, | |||
| PrimType_MIN = PrimType_NONE, | |||
| PrimType_MAX = PrimType_Splice + 1 | |||
| PrimType_MAX = PrimType_LogSoftmax + 1 | |||
| }; | |||
| void RegInfer(int prim_type, InferShape func); | |||
| @@ -0,0 +1,44 @@ | |||
| /** | |||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| #include "nnacl/infer/log_softmax_infer.h" | |||
| #include "nnacl/infer/infer_register.h" | |||
| int LogSoftmaxInferShape(const TensorC *const *inputs, size_t inputs_size, TensorC **outputs, size_t outputs_size, | |||
| OpParameter *parameter) { | |||
| #ifdef Debug | |||
| int check_ret = CheckAugmentNull(inputs, inputs_size, outputs, outputs_size, parameter); | |||
| if (check_ret != NNACL_OK) { | |||
| return check_ret; | |||
| } | |||
| #endif | |||
| const TensorC *input = inputs[0]; | |||
| TensorC *output = outputs[0]; | |||
| output->data_type_ = input->data_type_; | |||
| output->format_ = input->format_; | |||
| if (!parameter->infer_flag_) { | |||
| return NNACL_INFER_INVALID; | |||
| } | |||
| if (input->shape_size_ > 5) { | |||
| return NNACL_ERR; | |||
| } | |||
| SetShapeTensor(output, input); | |||
| return NNACL_OK; | |||
| } | |||
| REG_INFER(LogSoftmax, PrimType_LogSoftmax, LogSoftmaxInferShape) | |||
| @@ -0,0 +1,32 @@ | |||
| /** | |||
| * Copyright 2021 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_NNACL_LOG_SOFTMAX_INFER_H | |||
| #define MINDSPORE_LITE_NNACL_LOG_SOFTMAX_INFER_H | |||
| #include "nnacl/infer/common_infer.h" | |||
| #include "nnacl/softmax_parameter.h" | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| int LogSoftMaxInferShape(const TensorC *const *inputs, size_t inputs_size, TensorC **outputs, size_t outputs_size, | |||
| OpParameter *parameter); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif // MINDSPORE_LITE_NNACL_LOG_SOFTMAX_INFER_H | |||
| @@ -206,6 +206,7 @@ union PrimitiveType { | |||
| LayerNormGrad, | |||
| ResizeGrad, | |||
| Splice, | |||
| LogSoftmax, | |||
| } | |||
| table Abs { | |||
| @@ -1094,3 +1095,7 @@ table Splice { | |||
| forward_indexes: [long]; | |||
| output_dim: long; | |||
| } | |||
| table LogSoftmax { | |||
| axis: long; | |||
| } | |||
| @@ -205,6 +205,7 @@ OP_TYPE(SqrtGrad) | |||
| OP_TYPE(LayerNormGrad) | |||
| OP_TYPE(ResizeGrad) | |||
| OP_TYPE(Splice) | |||
| OP_TYPE(LogSoftmax) | |||
| OP_TYPE_DEF_END(PrimitiveType) | |||
| OP_SCHEMA_DEF(Abs) | |||
| @@ -1093,3 +1094,7 @@ OP_ATTR(context, [long]) | |||
| OP_ATTR(forward_indexes, [long]) | |||
| OP_ATTR(output_dim, long) | |||
| OP_SCHEMA_DEF_END(Splice) | |||
| OP_SCHEMA_DEF(LogSoftmax) | |||
| OP_ATTR(axis, long) | |||
| OP_SCHEMA_DEF_END(LogSoftmax) | |||
| @@ -243,6 +243,7 @@ | |||
| #include "ops/uniform_real.h" | |||
| #include "ops/grad/abs_grad.h" | |||
| #include "ops/splice.h" | |||
| #include "ops/log_softmax.h" | |||
| #define FUNC_MSOP2SCHEMAOP_DECLARE(OP) \ | |||
| namespace mindspore::lite::ops { \ | |||
| @@ -455,5 +456,6 @@ FUNC_MSOP2SCHEMAOP_DECLARE(SqrtGrad); | |||
| FUNC_MSOP2SCHEMAOP_DECLARE(LayerNormGrad); | |||
| FUNC_MSOP2SCHEMAOP_DECLARE(ResizeGrad); | |||
| FUNC_MSOP2SCHEMAOP_DECLARE(Splice); | |||
| FUNC_MSOP2SCHEMAOP_DECLARE(LogSoftmax); | |||
| #endif | |||
| #endif // MINDSPORE_LITE_SRC_OPS_OPS_FUNC_DECLARE_H_ | |||
| @@ -750,6 +750,11 @@ schema::PrimitiveT *SplicePrimitiveCreator(const AnfNodePtr &node) { | |||
| return ms_primc != nullptr ? ops::MSOp2SchemaOp(ms_primc.get()) : nullptr; | |||
| } | |||
| schema::PrimitiveT *LogSoftmaxPrimitiveCreator(const AnfNodePtr &node) { | |||
| auto ms_primc = GetValueNode<std::shared_ptr<mindspore::ops::LogSoftmax>>(node); | |||
| return ms_primc != nullptr ? ops::MSOp2SchemaOp(ms_primc.get()) : nullptr; | |||
| } | |||
| RegistryMSOps g_absPrimitiveCreatorRegistry("Abs", AbsPrimitiveCreator); | |||
| RegistryMSOps g_absGradPrimitiveCreatorRegistry("AbsGrad", AbsGradPrimitiveCreator); | |||
| RegistryMSOps g_activationPrimitiveCreatorRegistry("Activation", ActivationPrimitiveCreator); | |||
| @@ -960,6 +965,7 @@ RegistryMSOps g_wherePrimitiveCreatorRegistry("Where", WherePrimitiveCreator); | |||
| RegistryMSOps g_zerosLikePrimitiveCreatorRegistry("ZerosLike", ZerosLikePrimitiveCreator); | |||
| RegistryMSOps g_erfPrimitiveCreatorRegistry("Erf", ErfPrimitiveCreator); | |||
| RegistryMSOps g_SplicePrimitiveCreatorRegistry("Splice", SplicePrimitiveCreator); | |||
| RegistryMSOps g_LogSoftmaxPrimitiveCreatorRegistry("LogSoftmax", LogSoftmaxPrimitiveCreator); | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,40 @@ | |||
| /** | |||
| * Copyright 2021 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/populate/populate_register.h" | |||
| #include "nnacl/softmax_parameter.h" | |||
| using mindspore::schema::PrimitiveType_LogSoftmax; | |||
| namespace mindspore { | |||
| namespace lite { | |||
| namespace { | |||
| OpParameter *PopulateLogSoftmaxParameter(const void *prim) { | |||
| SoftmaxParameter *log_softmax_param = reinterpret_cast<SoftmaxParameter *>(malloc(sizeof(SoftmaxParameter))); | |||
| if (log_softmax_param == nullptr) { | |||
| MS_LOG(ERROR) << "malloc LogSoftmaxParameter failed."; | |||
| return nullptr; | |||
| } | |||
| memset(log_softmax_param, 0, sizeof(SoftmaxParameter)); | |||
| auto primitive = static_cast<const schema::Primitive *>(prim); | |||
| log_softmax_param->op_parameter_.type_ = primitive->value_type(); | |||
| auto prim_log_softmax = primitive->value_as_LogSoftmax(); | |||
| log_softmax_param->axis_ = prim_log_softmax->axis(); | |||
| return reinterpret_cast<OpParameter *>(log_softmax_param); | |||
| } | |||
| } // namespace | |||
| REG_POPULATE(PrimitiveType_LogSoftmax, PopulateLogSoftmaxParameter, SCHEMA_CUR); | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,119 @@ | |||
| /** | |||
| * 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 <string.h> | |||
| #include <vector> | |||
| #include "src/runtime/kernel/arm/fp16/log_softmax_fp16.h" | |||
| #include "src/runtime/kernel/arm/fp16/common_fp16.h" | |||
| #include "nnacl/fp16/log_softmax_fp16.h" | |||
| #include "nnacl/fp16/cast_fp16.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.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_LogSoftmax; | |||
| namespace mindspore::kernel { | |||
| int LogSoftmaxFp16CPUKernel::Init() { | |||
| auto ret = SoftmaxBaseCPUKernel::Init(); | |||
| if (ret != RET_OK) { | |||
| return ret; | |||
| } | |||
| if (!InferShapeDone()) { | |||
| return RET_OK; | |||
| } | |||
| return ReSize(); | |||
| } | |||
| int LogSoftmaxFp16CPUKernel::ReSize() { | |||
| auto ret = SoftmaxBaseCPUKernel::ReSize(); | |||
| if (ret != RET_OK) { | |||
| return ret; | |||
| } | |||
| auto n_dim = softmax_param_->n_dim_; | |||
| auto axis = softmax_param_->axis_; | |||
| auto in_shape = in_tensors_.front()->shape(); | |||
| out_plane_size_ = 1; | |||
| for (int i = 0; i < axis; ++i) { | |||
| out_plane_size_ *= in_shape[i]; | |||
| } | |||
| in_plane_size_ = 1; | |||
| for (int i = axis + 1; i < n_dim; i++) { | |||
| in_plane_size_ *= in_shape[i]; | |||
| } | |||
| auto tmp_data_size = | |||
| in_plane_size_ == 1 ? out_plane_size_ * in_plane_size_ * in_shape.at(axis) : out_plane_size_ * in_plane_size_; | |||
| if (tmp_data_ != nullptr) { | |||
| free(tmp_data_); | |||
| } | |||
| tmp_data_ = reinterpret_cast<float16_t *>(malloc(tmp_data_size * sizeof(float16_t))); | |||
| if (tmp_data_ == nullptr) { | |||
| MS_LOG(ERROR) << "malloc data for softmax fail!"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int LogSoftmaxFp16CPUKernel::DoLogSoftmaxLastAxis(int task_id) { | |||
| int unit = UP_DIV(out_plane_size_, context_->thread_num_); | |||
| int begin = task_id * unit; | |||
| int end = MSMIN(begin + unit, out_plane_size_); | |||
| int channel = softmax_param_->input_shape_[softmax_param_->axis_]; | |||
| int offset = begin * channel; | |||
| auto input_ptr = reinterpret_cast<float16_t *>(in_tensors_.at(kInputIndex)->MutableData()); | |||
| auto output_ptr = reinterpret_cast<float16_t *>(out_tensors_.at(kOutputIndex)->MutableData()); | |||
| LogSoftmaxLastAxisFp16(input_ptr + offset, output_ptr + offset, tmp_data_ + offset, end - begin, channel); | |||
| return RET_OK; | |||
| } | |||
| int LogSoftmaxLastAxisFp16Run(void *cdata, int task_id) { | |||
| auto kernel = reinterpret_cast<LogSoftmaxFp16CPUKernel *>(cdata); | |||
| auto ret = kernel->DoLogSoftmaxLastAxis(task_id); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "DoLogSoftmaxLastAxisFp16 error task_id: " << task_id << ", ret: " << ret; | |||
| } | |||
| return ret; | |||
| } | |||
| int LogSoftmaxFp16CPUKernel::Run() { | |||
| if (in_plane_size_ == 1) { | |||
| auto ret = ParallelLaunch(this->context_->thread_pool_, LogSoftmaxLastAxisFp16Run, this, context_->thread_num_); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "LogSoftmaxFp16CPUKernel ParallelLaunch failed, ret: " << ret; | |||
| } | |||
| return ret; | |||
| } else { | |||
| auto input_tensor = in_tensors_.at(0); | |||
| MS_ASSERT(input_tensor); | |||
| auto output_tensor = out_tensors_.at(0); | |||
| MS_ASSERT(output_tensor); | |||
| input_fp16_ = reinterpret_cast<float16_t *>(input_tensor->data_c()); | |||
| MS_ASSERT(input_fp16_); | |||
| output_fp16_ = reinterpret_cast<float16_t *>(output_tensor->data_c()); | |||
| MS_ASSERT(output_fp16_); | |||
| MS_ASSERT(tmp_data_); | |||
| LogSoftmaxFp16(input_fp16_, output_fp16_, tmp_data_, softmax_param_); | |||
| } | |||
| return RET_OK; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat16, PrimitiveType_LogSoftmax, LiteKernelCreator<LogSoftmaxFp16CPUKernel>) | |||
| } // namespace mindspore::kernel | |||
| @@ -0,0 +1,53 @@ | |||
| /** | |||
| * 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_FP16_LOG_SOFTMAX_FP16_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP16_LOG_SOFTMAX_FP16_H_ | |||
| #include <arm_neon.h> | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "src/runtime/kernel/arm/base/softmax_base.h" | |||
| namespace mindspore::kernel { | |||
| class LogSoftmaxFp16CPUKernel : public SoftmaxBaseCPUKernel { | |||
| public: | |||
| LogSoftmaxFp16CPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx) | |||
| : SoftmaxBaseCPUKernel(parameter, inputs, outputs, ctx), tmp_data_(nullptr) {} | |||
| ~LogSoftmaxFp16CPUKernel() override { | |||
| if (tmp_data_ != nullptr) { | |||
| free(tmp_data_); | |||
| } | |||
| } | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int MallocTmpBuffer(); | |||
| void FreeTmpBuffer(); | |||
| int DoLogSoftmaxLastAxis(int task_id); | |||
| private: | |||
| float16_t *tmp_data_ = nullptr; | |||
| float16_t *input_fp16_ = nullptr; | |||
| float16_t *output_fp16_ = nullptr; | |||
| int in_plane_size_ = 0; | |||
| int out_plane_size_ = 0; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP16_LOG_SOFTMAX_FP16_H_ | |||
| @@ -59,13 +59,15 @@ int SoftmaxFp16CPUKernel::ReSize() { | |||
| for (int i = axis + 1; i < n_dim; i++) { | |||
| in_plane_size_ *= in_shape[i]; | |||
| } | |||
| if (sum_data_ != nullptr) { | |||
| free(sum_data_); | |||
| } | |||
| sum_data_ = reinterpret_cast<float16_t *>(malloc(out_plane_size_ * in_plane_size_ * sizeof(float16_t))); | |||
| if (sum_data_ == nullptr) { | |||
| MS_LOG(ERROR) << "malloc data for softmax fail!"; | |||
| return RET_ERROR; | |||
| if (in_plane_size_ > 1) { | |||
| if (sum_data_ != nullptr) { | |||
| free(sum_data_); | |||
| } | |||
| sum_data_ = reinterpret_cast<float16_t *>(malloc(out_plane_size_ * in_plane_size_ * sizeof(float16_t))); | |||
| if (sum_data_ == nullptr) { | |||
| MS_LOG(ERROR) << "malloc data for softmax fail!"; | |||
| return RET_ERROR; | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| @@ -92,14 +94,6 @@ int SoftmaxLastAxisFp16Run(void *cdata, int task_id) { | |||
| } | |||
| int SoftmaxFp16CPUKernel::Run() { | |||
| auto input_tensor = in_tensors_.at(0); | |||
| MS_ASSERT(input_tensor); | |||
| auto output_tensor = out_tensors_.at(0); | |||
| MS_ASSERT(output_tensor); | |||
| input_fp16_ = reinterpret_cast<float16_t *>(input_tensor->data_c()); | |||
| MS_ASSERT(input_fp16_); | |||
| output_fp16_ = reinterpret_cast<float16_t *>(output_tensor->data_c()); | |||
| MS_ASSERT(output_fp16_); | |||
| if (in_plane_size_ == 1) { | |||
| auto ret = ParallelLaunch(this->context_->thread_pool_, SoftmaxLastAxisFp16Run, this, context_->thread_num_); | |||
| if (ret != RET_OK) { | |||
| @@ -107,8 +101,15 @@ int SoftmaxFp16CPUKernel::Run() { | |||
| } | |||
| return ret; | |||
| } else { | |||
| auto input_tensor = in_tensors_.at(0); | |||
| MS_ASSERT(input_tensor); | |||
| auto output_tensor = out_tensors_.at(0); | |||
| MS_ASSERT(output_tensor); | |||
| input_fp16_ = reinterpret_cast<float16_t *>(input_tensor->data_c()); | |||
| MS_ASSERT(input_fp16_); | |||
| output_fp16_ = reinterpret_cast<float16_t *>(output_tensor->data_c()); | |||
| MS_ASSERT(output_fp16_); | |||
| MS_ASSERT(sum_data_); | |||
| memset(sum_data_, 0, out_plane_size_ * in_plane_size_ * sizeof(float16_t)); | |||
| SoftmaxFp16(input_fp16_, output_fp16_, sum_data_, softmax_param_); | |||
| } | |||
| return RET_OK; | |||
| @@ -0,0 +1,116 @@ | |||
| /** | |||
| * Copyright 2021 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/log_softmax_fp32.h" | |||
| #include <string.h> | |||
| #include <vector> | |||
| #include "nnacl/fp32/log_softmax_fp32.h" | |||
| #include "schema/model_generated.h" | |||
| #include "src/kernel_registry.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_LogSoftmax; | |||
| namespace mindspore::kernel { | |||
| int LogSoftmaxCPUKernel::Init() { | |||
| auto ret = SoftmaxBaseCPUKernel::Init(); | |||
| if (ret != RET_OK) { | |||
| return ret; | |||
| } | |||
| if (!InferShapeDone()) { | |||
| return RET_OK; | |||
| } | |||
| return ReSize(); | |||
| } | |||
| int LogSoftmaxCPUKernel::ReSize() { | |||
| auto ret = SoftmaxBaseCPUKernel::ReSize(); | |||
| if (ret != RET_OK) { | |||
| return ret; | |||
| } | |||
| auto n_dim = softmax_param_->n_dim_; | |||
| auto axis = softmax_param_->axis_; | |||
| auto in_shape = in_tensors_.front()->shape(); | |||
| int out_plane_size = 1; | |||
| for (int i = 0; i < axis; ++i) { | |||
| out_plane_size *= in_shape.at(i); | |||
| } | |||
| int in_plane_size = 1; | |||
| for (int i = axis + 1; i < n_dim; i++) { | |||
| in_plane_size *= in_shape.at(i); | |||
| } | |||
| in_plane_size_ = in_plane_size; | |||
| out_plane_size_ = out_plane_size; | |||
| auto tmp_data_size = | |||
| in_plane_size == 1 ? out_plane_size * in_plane_size * in_shape.at(axis) : out_plane_size * in_plane_size; | |||
| if (tmp_data_ != nullptr) { | |||
| free(tmp_data_); | |||
| } | |||
| tmp_data_ = reinterpret_cast<float *>(malloc(tmp_data_size * sizeof(float))); | |||
| if (tmp_data_ == nullptr) { | |||
| MS_LOG(ERROR) << "malloc data for log_softmax fail!"; | |||
| return RET_ERROR; | |||
| } | |||
| return RET_OK; | |||
| } | |||
| int LogSoftmaxCPUKernel::DoLogSoftmaxLastAxis(int task_id) { | |||
| int unit = UP_DIV(out_plane_size_, context_->thread_num_); | |||
| int begin = task_id * unit; | |||
| int end = MSMIN(begin + unit, out_plane_size_); | |||
| int channel = softmax_param_->input_shape_[softmax_param_->axis_]; | |||
| int offset = begin * channel; | |||
| auto input_ptr = reinterpret_cast<float *>(in_tensors_.at(kInputIndex)->MutableData()); | |||
| auto output_ptr = reinterpret_cast<float *>(out_tensors_.at(kOutputIndex)->MutableData()); | |||
| LogSoftmaxLastAxis(input_ptr + offset, output_ptr + offset, tmp_data_ + offset, end - begin, channel); | |||
| return RET_OK; | |||
| } | |||
| int LogSoftmaxLastAxisRun(void *cdata, int task_id) { | |||
| auto kernel = reinterpret_cast<LogSoftmaxCPUKernel *>(cdata); | |||
| auto ret = kernel->DoLogSoftmaxLastAxis(task_id); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "DoLogSoftmaxLastAxis error task_id: " << task_id << ", ret: " << ret; | |||
| } | |||
| return ret; | |||
| } | |||
| int LogSoftmaxCPUKernel::Run() { | |||
| int ret = RET_OK; | |||
| if (in_plane_size_ == 1) { | |||
| ret = ParallelLaunch(this->context_->thread_pool_, LogSoftmaxLastAxisRun, this, context_->thread_num_); | |||
| if (ret != RET_OK) { | |||
| MS_LOG(ERROR) << "LogSoftmaxCPUKernel ParallelLaunch failed, ret: " << ret; | |||
| } | |||
| } else { | |||
| auto input_ptr = reinterpret_cast<float *>(in_tensors_.at(kInputIndex)->data_c()); | |||
| MS_ASSERT(input_ptr); | |||
| auto output_ptr = reinterpret_cast<float *>(out_tensors_.at(kOutputIndex)->data_c()); | |||
| MS_ASSERT(output_ptr); | |||
| MS_ASSERT(tmp_data_); | |||
| MS_ASSERT(softmax_param_); | |||
| LogSoftmax(input_ptr, output_ptr, tmp_data_, softmax_param_); | |||
| } | |||
| return ret; | |||
| } | |||
| REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_LogSoftmax, LiteKernelCreator<LogSoftmaxCPUKernel>) | |||
| } // namespace mindspore::kernel | |||
| @@ -0,0 +1,48 @@ | |||
| /** | |||
| * Copyright 2021 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_LOG_SOFTMAX_H_ | |||
| #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_LOG_SOFTMAX_H_ | |||
| #include <vector> | |||
| #include "src/lite_kernel.h" | |||
| #include "src/runtime/kernel/arm/base/softmax_base.h" | |||
| namespace mindspore::kernel { | |||
| class LogSoftmaxCPUKernel : public SoftmaxBaseCPUKernel { | |||
| public: | |||
| LogSoftmaxCPUKernel(OpParameter *parameter, const std::vector<lite::Tensor *> &inputs, | |||
| const std::vector<lite::Tensor *> &outputs, const lite::InnerContext *ctx) | |||
| : SoftmaxBaseCPUKernel(parameter, inputs, outputs, ctx), tmp_data_(nullptr) {} | |||
| ~LogSoftmaxCPUKernel() override { | |||
| if (tmp_data_ != nullptr) { | |||
| free(tmp_data_); | |||
| } | |||
| }; | |||
| int Init() override; | |||
| int ReSize() override; | |||
| int Run() override; | |||
| int DoLogSoftmaxLastAxis(int task_id); | |||
| private: | |||
| float *tmp_data_ = nullptr; | |||
| int in_plane_size_ = 0; | |||
| int out_plane_size_ = 0; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| #endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_LOG_SOFTMAX_H_ | |||
| @@ -59,13 +59,15 @@ int SoftmaxCPUKernel::ReSize() { | |||
| } | |||
| in_plane_size_ = in_plane_size; | |||
| out_plane_size_ = out_plane_size; | |||
| if (sum_data_ != nullptr) { | |||
| free(sum_data_); | |||
| } | |||
| sum_data_ = reinterpret_cast<float *>(malloc(out_plane_size * in_plane_size * sizeof(float))); | |||
| if (sum_data_ == nullptr) { | |||
| MS_LOG(ERROR) << "malloc data for softmax fail!"; | |||
| return RET_ERROR; | |||
| if (in_plane_size_ > 1) { | |||
| if (sum_data_ != nullptr) { | |||
| free(sum_data_); | |||
| } | |||
| sum_data_ = reinterpret_cast<float *>(malloc(out_plane_size * in_plane_size * sizeof(float))); | |||
| if (sum_data_ == nullptr) { | |||
| MS_LOG(ERROR) << "malloc data for softmax fail!"; | |||
| return RET_ERROR; | |||
| } | |||
| } | |||
| return RET_OK; | |||
| } | |||
| @@ -92,10 +94,6 @@ int SoftmaxLastAxisRun(void *cdata, int task_id) { | |||
| } | |||
| int SoftmaxCPUKernel::Run() { | |||
| auto input_ptr = reinterpret_cast<float *>(in_tensors_.at(kInputIndex)->MutableData()); | |||
| MS_ASSERT(input_ptr); | |||
| auto output_ptr = reinterpret_cast<float *>(out_tensors_.at(kOutputIndex)->MutableData()); | |||
| MS_ASSERT(output_ptr); | |||
| int ret = RET_OK; | |||
| if (in_plane_size_ == 1) { | |||
| ret = ParallelLaunch(this->context_->thread_pool_, SoftmaxLastAxisRun, this, context_->thread_num_); | |||
| @@ -104,8 +102,11 @@ int SoftmaxCPUKernel::Run() { | |||
| } | |||
| } else { | |||
| MS_ASSERT(sum_data_); | |||
| memset(sum_data_, 0, in_plane_size_ * out_plane_size_ * sizeof(float)); | |||
| MS_ASSERT(softmax_param_); | |||
| auto input_ptr = reinterpret_cast<float *>(in_tensors_.at(kInputIndex)->data_c()); | |||
| MS_ASSERT(input_ptr); | |||
| auto output_ptr = reinterpret_cast<float *>(out_tensors_.at(kOutputIndex)->data_c()); | |||
| MS_ASSERT(output_ptr); | |||
| Softmax(input_ptr, output_ptr, sum_data_, softmax_param_); | |||
| } | |||
| return ret; | |||
| @@ -0,0 +1,45 @@ | |||
| /** | |||
| * Copyright 2021 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 "tools/converter/parser/onnx/onnx_log_softmax_parser.h" | |||
| #include <memory> | |||
| #include "ops/log_softmax.h" | |||
| namespace mindspore { | |||
| namespace lite { | |||
| ops::PrimitiveC *OnnxLogSoftmaxParser::Parse(const onnx::GraphProto &onnx_graph, const onnx::NodeProto &onnx_node) { | |||
| auto prim = std::make_unique<ops::LogSoftmax>(); | |||
| int64_t axis; | |||
| bool axis_is_def = true; | |||
| for (const auto &onnx_node_attr : onnx_node.attribute()) { | |||
| const auto &attribute_name = onnx_node_attr.name(); | |||
| if (attribute_name == "axis") { | |||
| axis = onnx_node_attr.i(); | |||
| axis_is_def = false; | |||
| } | |||
| } | |||
| if (axis_is_def) { | |||
| axis = OnnxNodeParser::opset_version() >= 13 ? -1 : 1; | |||
| } | |||
| prim->set_axis({axis}); | |||
| return prim.release(); | |||
| } | |||
| OnnxNodeRegistrar g_onnxLogSoftmaxParser("LogSoftmax", new OnnxLogSoftmaxParser()); | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| @@ -0,0 +1,34 @@ | |||
| /** | |||
| * Copyright 2021 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_TOOLS_CONVERTER_PARSER_ONNX_LOG_SOFTMAX_PARSER_H | |||
| #define MINDSPORE_LITE_TOOLS_CONVERTER_PARSER_ONNX_LOG_SOFTMAX_PARSER_H | |||
| #include "tools/converter/parser/onnx/onnx_node_parser.h" | |||
| #include "tools/converter/parser/onnx/onnx_node_parser_registry.h" | |||
| namespace mindspore { | |||
| namespace lite { | |||
| class OnnxLogSoftmaxParser : public OnnxNodeParser { | |||
| public: | |||
| OnnxLogSoftmaxParser() : OnnxNodeParser("LogSoftmax") {} | |||
| ~OnnxLogSoftmaxParser() override = default; | |||
| ops::PrimitiveC *Parse(const onnx::GraphProto &onnx_graph, const onnx::NodeProto &onnx_node) override; | |||
| }; | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| #endif // MINDSPORE_LITE_TOOLS_CONVERTER_PARSER_ONNX_LOG_SOFTMAX_PARSER_H | |||