!14652 [MS][LITE]add LogSoftmax op and optimize Softmax op

From: @probiotics_53
Reviewed-by: @zhang_xue_tong,@zhanghaibo5
Signed-off-by: @zhang_xue_tong
This commit is contained in:
mindspore-ci-bot 2021-04-08 09:26:59 +08:00 committed by Gitee
commit caa474caca
26 changed files with 940 additions and 29 deletions

View File

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

View File

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

View File

@ -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]);
}
}
}
}

View File

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

View File

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

View File

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

View File

@ -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]);
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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