diff --git a/mindspore/core/ops/log_softmax.cc b/mindspore/core/ops/log_softmax.cc new file mode 100644 index 0000000000..eb31b486f9 --- /dev/null +++ b/mindspore/core/ops/log_softmax.cc @@ -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 +#include +#include +#include +#include +#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(GetAttr(kAxis)); } + +void LogSoftmax::Init(const int64_t axis) { this->set_axis(axis); } + +abstract::ShapePtr LogSoftmaxInferShape(const PrimitivePtr &primitive, const std::vector &input_args) { + MS_EXCEPTION_IF_NULL(primitive); + auto LogSoftmax_prim = primitive->cast(); + 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("axis", axis, kIncludeLeft, {-rank, rank}, op_name); + return std::make_shared(in_shape); +} + +TypePtr LogSoftmaxInferType(const PrimitivePtr &prim, const std::vector &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 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 &input_args) { + return std::make_shared(LogSoftmaxInferType(primitive, input_args), + LogSoftmaxInferShape(primitive, input_args)->shape()); +} +REGISTER_PRIMITIVE_C(kNameLogSoftmax, LogSoftmax); +} // namespace ops +} // namespace mindspore diff --git a/mindspore/core/ops/log_softmax.h b/mindspore/core/ops/log_softmax.h new file mode 100644 index 0000000000..ad6bef4417 --- /dev/null +++ b/mindspore/core/ops/log_softmax.h @@ -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 +#include +#include +#include +#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 &input_args); +using PrimLogSoftmaxPtr = std::shared_ptr; +} // namespace ops +} // namespace mindspore + +#endif // MINDSPORE_CORE_OPS_LOG_SOFTMAX_H_ diff --git a/mindspore/lite/nnacl/fp16/log_softmax_fp16.c b/mindspore/lite/nnacl/fp16/log_softmax_fp16.c new file mode 100644 index 0000000000..c75362a331 --- /dev/null +++ b/mindspore/lite/nnacl/fp16/log_softmax_fp16.c @@ -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 +#include +#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]); + } + } + } +} diff --git a/mindspore/lite/nnacl/fp16/log_softmax_fp16.h b/mindspore/lite/nnacl/fp16/log_softmax_fp16.h new file mode 100644 index 0000000000..5485ca7f6a --- /dev/null +++ b/mindspore/lite/nnacl/fp16/log_softmax_fp16.h @@ -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 +#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_ diff --git a/mindspore/lite/nnacl/fp16/softmax_fp16.c b/mindspore/lite/nnacl/fp16/softmax_fp16.c index b62bdd7f9f..31c44ad268 100644 --- a/mindspore/lite/nnacl/fp16/softmax_fp16.c +++ b/mindspore/lite/nnacl/fp16/softmax_fp16.c @@ -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]; diff --git a/mindspore/lite/nnacl/fp16/softmax_fp16.h b/mindspore/lite/nnacl/fp16/softmax_fp16.h index 5ff3a1c02c..2c2b575d92 100644 --- a/mindspore/lite/nnacl/fp16/softmax_fp16.h +++ b/mindspore/lite/nnacl/fp16/softmax_fp16.h @@ -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 diff --git a/mindspore/lite/nnacl/fp32/log_softmax_fp32.c b/mindspore/lite/nnacl/fp32/log_softmax_fp32.c new file mode 100644 index 0000000000..8d46d1557a --- /dev/null +++ b/mindspore/lite/nnacl/fp32/log_softmax_fp32.c @@ -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 +#include +#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]); + } + } + } +} diff --git a/mindspore/lite/nnacl/fp32/log_softmax_fp32.h b/mindspore/lite/nnacl/fp32/log_softmax_fp32.h new file mode 100644 index 0000000000..46fa76062c --- /dev/null +++ b/mindspore/lite/nnacl/fp32/log_softmax_fp32.h @@ -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_ diff --git a/mindspore/lite/nnacl/fp32/softmax_fp32.c b/mindspore/lite/nnacl/fp32/softmax_fp32.c index 943eaa15e2..5d616a97f3 100644 --- a/mindspore/lite/nnacl/fp32/softmax_fp32.c +++ b/mindspore/lite/nnacl/fp32/softmax_fp32.c @@ -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]; diff --git a/mindspore/lite/nnacl/fp32/softmax_fp32.h b/mindspore/lite/nnacl/fp32/softmax_fp32.h index 553b79ba6d..f8ec5ffeb3 100644 --- a/mindspore/lite/nnacl/fp32/softmax_fp32.h +++ b/mindspore/lite/nnacl/fp32/softmax_fp32.h @@ -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 diff --git a/mindspore/lite/nnacl/infer/infer_register.h b/mindspore/lite/nnacl/infer/infer_register.h index 35f9ba047e..8d66b12b28 100644 --- a/mindspore/lite/nnacl/infer/infer_register.h +++ b/mindspore/lite/nnacl/infer/infer_register.h @@ -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); diff --git a/mindspore/lite/nnacl/infer/log_softmax_infer.c b/mindspore/lite/nnacl/infer/log_softmax_infer.c new file mode 100644 index 0000000000..a8a16a6f5c --- /dev/null +++ b/mindspore/lite/nnacl/infer/log_softmax_infer.c @@ -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) diff --git a/mindspore/lite/nnacl/infer/log_softmax_infer.h b/mindspore/lite/nnacl/infer/log_softmax_infer.h new file mode 100644 index 0000000000..9f25e256d8 --- /dev/null +++ b/mindspore/lite/nnacl/infer/log_softmax_infer.h @@ -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 diff --git a/mindspore/lite/schema/ops.fbs b/mindspore/lite/schema/ops.fbs index f49b5912c2..2af4e527cd 100644 --- a/mindspore/lite/schema/ops.fbs +++ b/mindspore/lite/schema/ops.fbs @@ -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; +} diff --git a/mindspore/lite/src/ops/ops_def.cc b/mindspore/lite/src/ops/ops_def.cc index 679ee21920..e5fd9335d7 100644 --- a/mindspore/lite/src/ops/ops_def.cc +++ b/mindspore/lite/src/ops/ops_def.cc @@ -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) diff --git a/mindspore/lite/src/ops/ops_func_declare.h b/mindspore/lite/src/ops/ops_func_declare.h index fa150d92c3..dba2a7d9b9 100644 --- a/mindspore/lite/src/ops/ops_func_declare.h +++ b/mindspore/lite/src/ops/ops_func_declare.h @@ -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_ diff --git a/mindspore/lite/src/ops/ops_utils.cc b/mindspore/lite/src/ops/ops_utils.cc index a7a73f5432..fad6c45fe6 100644 --- a/mindspore/lite/src/ops/ops_utils.cc +++ b/mindspore/lite/src/ops/ops_utils.cc @@ -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>(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 diff --git a/mindspore/lite/src/ops/populate/log_softmax_populate.cc b/mindspore/lite/src/ops/populate/log_softmax_populate.cc new file mode 100644 index 0000000000..9a28d31c03 --- /dev/null +++ b/mindspore/lite/src/ops/populate/log_softmax_populate.cc @@ -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(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(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(log_softmax_param); +} +} // namespace + +REG_POPULATE(PrimitiveType_LogSoftmax, PopulateLogSoftmaxParameter, SCHEMA_CUR); +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/src/runtime/kernel/arm/fp16/log_softmax_fp16.cc b/mindspore/lite/src/runtime/kernel/arm/fp16/log_softmax_fp16.cc new file mode 100644 index 0000000000..379f61694f --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp16/log_softmax_fp16.cc @@ -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 +#include +#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(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(in_tensors_.at(kInputIndex)->MutableData()); + auto output_ptr = reinterpret_cast(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(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(input_tensor->data_c()); + MS_ASSERT(input_fp16_); + output_fp16_ = reinterpret_cast(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) +} // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/fp16/log_softmax_fp16.h b/mindspore/lite/src/runtime/kernel/arm/fp16/log_softmax_fp16.h new file mode 100644 index 0000000000..59afaa35a9 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp16/log_softmax_fp16.h @@ -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 +#include +#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 &inputs, + const std::vector &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_ diff --git a/mindspore/lite/src/runtime/kernel/arm/fp16/softmax_fp16.cc b/mindspore/lite/src/runtime/kernel/arm/fp16/softmax_fp16.cc index 3a3cce72e6..275861deaa 100644 --- a/mindspore/lite/src/runtime/kernel/arm/fp16/softmax_fp16.cc +++ b/mindspore/lite/src/runtime/kernel/arm/fp16/softmax_fp16.cc @@ -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(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(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(input_tensor->data_c()); - MS_ASSERT(input_fp16_); - output_fp16_ = reinterpret_cast(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(input_tensor->data_c()); + MS_ASSERT(input_fp16_); + output_fp16_ = reinterpret_cast(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; diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/log_softmax_fp32.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/log_softmax_fp32.cc new file mode 100644 index 0000000000..e9f5eac957 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/log_softmax_fp32.cc @@ -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 +#include +#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(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(in_tensors_.at(kInputIndex)->MutableData()); + auto output_ptr = reinterpret_cast(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(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(in_tensors_.at(kInputIndex)->data_c()); + MS_ASSERT(input_ptr); + auto output_ptr = reinterpret_cast(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) +} // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/log_softmax_fp32.h b/mindspore/lite/src/runtime/kernel/arm/fp32/log_softmax_fp32.h new file mode 100644 index 0000000000..00689c866c --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/log_softmax_fp32.h @@ -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 +#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 &inputs, + const std::vector &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_ diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/softmax_fp32.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/softmax_fp32.cc index adedc54d90..619d5ceae4 100644 --- a/mindspore/lite/src/runtime/kernel/arm/fp32/softmax_fp32.cc +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/softmax_fp32.cc @@ -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(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(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(in_tensors_.at(kInputIndex)->MutableData()); - MS_ASSERT(input_ptr); - auto output_ptr = reinterpret_cast(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(in_tensors_.at(kInputIndex)->data_c()); + MS_ASSERT(input_ptr); + auto output_ptr = reinterpret_cast(out_tensors_.at(kOutputIndex)->data_c()); + MS_ASSERT(output_ptr); Softmax(input_ptr, output_ptr, sum_data_, softmax_param_); } return ret; diff --git a/mindspore/lite/tools/converter/parser/onnx/onnx_log_softmax_parser.cc b/mindspore/lite/tools/converter/parser/onnx/onnx_log_softmax_parser.cc new file mode 100644 index 0000000000..da4d8ce519 --- /dev/null +++ b/mindspore/lite/tools/converter/parser/onnx/onnx_log_softmax_parser.cc @@ -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 +#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(); + + 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 diff --git a/mindspore/lite/tools/converter/parser/onnx/onnx_log_softmax_parser.h b/mindspore/lite/tools/converter/parser/onnx/onnx_log_softmax_parser.h new file mode 100644 index 0000000000..18569cb00b --- /dev/null +++ b/mindspore/lite/tools/converter/parser/onnx/onnx_log_softmax_parser.h @@ -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