forked from mindspore-Ecosystem/mindspore
!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:
commit
caa474caca
|
@ -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
|
Loading…
Reference in New Issue