Skip to content

Commit

Permalink
修改激活函数的实现
Browse files Browse the repository at this point in the history
  • Loading branch information
zjhellofss committed Dec 14, 2023
1 parent 625edf2 commit a425a0a
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 250 deletions.
86 changes: 86 additions & 0 deletions source/layer/details/activation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//
// Created by fss on 23-12-14.
//
#include "activation.hpp"
#include "activation_sse.hpp"
namespace kuiper_infer {
namespace activation {
StatusCode ActivationForward(ActivationType type,
const std::vector<std::shared_ptr<Tensor<float>>>& inputs,
std::vector<std::shared_ptr<Tensor<float>>>& outputs) {
const std::string& activation_type = ActivationTypeToString(type);
if (inputs.empty()) {
LOG(ERROR) << "The input tensor array in the " + activation_type + " layer is empty";
return StatusCode::kInferInputsEmpty;
}

if (outputs.empty()) {
LOG(ERROR) << "The output tensor array in the " + activation_type + " layer is empty";
return StatusCode::kInferOutputsEmpty;
}

if (inputs.size() != outputs.size()) {
LOG(ERROR) << "The input and output tensor array size of the " + activation_type +
" layer do not match";
return StatusCode::kInferInOutShapeMismatch;
}

const uint32_t batch_size = inputs.size();
ActivationFunc activation_function = ApplySSEActivation(type);
#pragma omp parallel for num_threads(batch_size)
for (uint32_t i = 0; i < batch_size; ++i) {
const std::shared_ptr<Tensor<float>>& input = inputs.at(i);
CHECK(input != nullptr && !input->empty())
<< "The input tensor array in the " + activation_type + " layer has an empty tensor " << i
<< " th";

std::shared_ptr<Tensor<float>> output = outputs.at(i);
if (output == nullptr || output->empty()) {
output = std::make_shared<Tensor<float>>(input->shapes());
outputs.at(i) = output;
}
CHECK(output != nullptr && output->shapes() == input->shapes())
<< "The input and output tensor shapes of the " + activation_type + " layer do not match "
<< i << " th";
activation_function(input, output);
}
return StatusCode::kSuccess;
}

std::string ActivationTypeToString(ActivationType type) {
std::string activate_type;
switch (type) {
case ActivationType::kActivationRelu: {
activate_type = "Relu";
break;
}
case ActivationType::kActivationSilu: {
activate_type = "Silu";
break;
}
case ActivationType::kActivationRelu6: {
activate_type = "Relu6";
break;
}
case ActivationType::kActivationSigmoid: {
activate_type = "Sigmoid";
break;
}
case ActivationType::kActivationHardSigmoid: {
activate_type = "HardSigmoid";
break;
}
case ActivationType::kActivationHardSwish: {
activate_type = "HardSwish";
break;
}
default: {
activate_type = "Unknown";
break;
}
}
return activate_type;
}

} // namespace activation
} // namespace kuiper_infer
30 changes: 30 additions & 0 deletions source/layer/details/activation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// Created by fss on 23-12-14.
//

#ifndef KUIPER_INFER_SOURCE_LAYER_DETAILS_ACTIVATION_HPP
#define KUIPER_INFER_SOURCE_LAYER_DETAILS_ACTIVATION_HPP
#include "data/tensor.hpp"
#include "status_code.hpp"
namespace kuiper_infer {
namespace activation {
using ActivationFunc = std::function<void(sftensor, sftensor)>;

enum class ActivationType {
kActivatetionUnknown = -1,
kActivationRelu = 0,
kActivationSilu = 1,
kActivationSigmoid = 2,
kActivationHardSwish = 3,
kActivationHardSigmoid = 4,
kActivationRelu6 = 5,
};

std::string ActivationTypeToString(ActivationType type);

StatusCode ActivationForward(ActivationType type,
const std::vector<std::shared_ptr<Tensor<float>>>& inputs,
std::vector<std::shared_ptr<Tensor<float>>>& outputs);
} // namespace activation
} // namespace kuiper_infer
#endif // KUIPER_INFER_SOURCE_LAYER_DETAILS_ACTIVATION_HPP
13 changes: 1 addition & 12 deletions source/layer/details/activation_sse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,11 @@
#ifndef KUIPER_INFER_INCLUDE_MATH_ARMA_SSE
#define KUIPER_INFER_INCLUDE_MATH_ARMA_SSE
#include <armadillo>
#include "activation.hpp"
#include "data/tensor.hpp"
#include "utils/math/fmath.hpp"
namespace kuiper_infer {
namespace activation {
enum class ActivationType {
kActivatetionUnknown = -1,
kActivationRelu = 0,
kActivationSilu = 1,
kActivationSigmoid = 2,
kActivationHardSwish = 3,
kActivationHardSigmoid = 4,
kActivationRelu6 = 6,
};

using ActivationFunc = std::function<void(sftensor, sftensor)>;

ActivationFunc ApplySSEActivation(ActivationType act_type);

} // namespace activation
Expand Down
23 changes: 11 additions & 12 deletions source/layer/details/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@ StatusCode ExpressionLayer::Forward(const std::vector<std::shared_ptr<Tensor<flo
} else if (TokenIsOperator(current_token)) {
// process operation
CHECK(op_stack.size() >= 2) << "The number of operand is less than two";
std::vector<std::shared_ptr<Tensor<float>>> input_node1 = op_stack.top();
std::shared_ptr<Tensor<float>> (*function)(const std::shared_ptr<Tensor<float>>& tensor1,
const std::shared_ptr<Tensor<float>>& tensor2);
std::vector<std::shared_ptr<Tensor<float>>> input_node1(std::move(op_stack.top()));
CHECK(input_node1.size() == batch_size)
<< "The first operand doesn't have appropriate number of tensors, "
"which need "
<< batch_size;
op_stack.pop();
std::vector<std::shared_ptr<Tensor<float>>> input_node2 = op_stack.top();
std::vector<std::shared_ptr<Tensor<float>>> input_node2(std::move(op_stack.top()));
CHECK(input_node2.size() == batch_size)
<< "The second operand doesn't have appropriate number of tensors, "
"which need "
Expand All @@ -92,21 +94,18 @@ StatusCode ExpressionLayer::Forward(const std::vector<std::shared_ptr<Tensor<flo

std::vector<std::shared_ptr<Tensor<float>>> output_token_nodes(batch_size);
if (current_token.token_type == TokenType::TokenAdd) {
#pragma omp parallel for num_threads(batch_size)
for (uint32_t i = 0; i < batch_size; ++i) {
output_token_nodes.at(i) = TensorElementAdd(input_node1.at(i), input_node2.at(i));
}
op_stack.push(output_token_nodes);
function = TensorElementAdd;
} else if (current_token.token_type == TokenType::TokenMul) {
#pragma omp parallel for num_threads(batch_size)
for (uint32_t i = 0; i < batch_size; ++i) {
output_token_nodes.at(i) = TensorElementMultiply(input_node1.at(i), input_node2.at(i));
}
op_stack.push(output_token_nodes);
function = TensorElementMultiply;
} else {
LOG(FATAL) << "Unsupported operator type in the expression layer: "
<< int(current_token.token_type);
}
#pragma omp parallel for num_threads(batch_size)
for (uint32_t i = 0; i < batch_size; ++i) {
output_token_nodes.at(i) = function(input_node1.at(i), input_node2.at(i));
}
op_stack.push(output_token_nodes);
}
}
CHECK(op_stack.size() == 1) << "The expression has more than one output operand!";
Expand Down
41 changes: 1 addition & 40 deletions source/layer/details/hardsigmoid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,47 +29,8 @@ HardSigmoid::HardSigmoid() : NonParamLayer("HardSigmoid") {}

StatusCode HardSigmoid::Forward(const std::vector<std::shared_ptr<Tensor<float>>>& inputs,
std::vector<std::shared_ptr<Tensor<float>>>& outputs) {
if (inputs.empty()) {
LOG(ERROR) << "The input tensor array in the hardsigmoid layer is empty";
return StatusCode::kInferInputsEmpty;
}

if (outputs.empty()) {
LOG(ERROR) << "The output tensor array in the hardsigmoid layer is empty";
return StatusCode::kInferOutputsEmpty;
}

if (inputs.size() != outputs.size()) {
LOG(ERROR) << "The input and output tensor array size of the hardsigmoid "
"layer do not match";
return StatusCode::kInferInOutShapeMismatch;
}

using namespace activation;
ActivationFunc hardsigmoid_function = ApplySSEActivation(ActivationType::kActivationHardSigmoid);

const uint32_t batch = inputs.size();
#pragma omp parallel for num_threads(batch)
for (uint32_t i = 0; i < batch; ++i) {
const std::shared_ptr<Tensor<float>>& input = inputs.at(i);
CHECK(input != nullptr && !input->empty())
<< "The input tensor array in the hardsigmoid layer has an "
"empty tensor "
<< i << " th";

std::shared_ptr<Tensor<float>> output = outputs.at(i);
if (output == nullptr || output->empty()) {
output = std::make_shared<Tensor<float>>(input->channels(), input->rows(), input->cols());
outputs.at(i) = output;
}

CHECK(output->shapes() == input->shapes())
<< "The output and input shapes of the hardsigmoid layer do "
"not match "
<< i << " th";
hardsigmoid_function(input, output);
}
return StatusCode::kSuccess;
return ActivationForward(ActivationType::kActivationHardSigmoid, inputs, outputs);
}

StatusCode HardSigmoid::CreateInstance(const std::shared_ptr<RuntimeOperator>& op,
Expand Down
40 changes: 1 addition & 39 deletions source/layer/details/hardswish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,46 +29,8 @@ HardSwishLayer::HardSwishLayer() : NonParamLayer("HardSwish") {}

StatusCode HardSwishLayer::Forward(const std::vector<std::shared_ptr<Tensor<float>>>& inputs,
std::vector<std::shared_ptr<Tensor<float>>>& outputs) {
if (inputs.empty()) {
LOG(ERROR) << "The input tensor array in the hardswish layer is empty";
return StatusCode::kInferInputsEmpty;
}

if (outputs.empty()) {
LOG(ERROR) << "The output tensor array in the hardswish layer is empty";
return StatusCode::kInferOutputsEmpty;
}

if (inputs.size() != outputs.size()) {
LOG(ERROR) << "The input and output tensor array size of the hardswish "
"layer do not match";
return StatusCode::kInferInOutShapeMismatch;
}

using namespace activation;
ActivationFunc hardswish_function = ApplySSEActivation(ActivationType::kActivationHardSwish);

const uint32_t batch = inputs.size();
#pragma omp parallel for num_threads(batch)
for (uint32_t i = 0; i < batch; ++i) {
const std::shared_ptr<Tensor<float>>& input = inputs.at(i);
CHECK(input != nullptr && !input->empty())
<< "The input tensor array in the hardswish layer has an empty tensor " << i << " th";

std::shared_ptr<Tensor<float>> output = outputs.at(i);
if (output == nullptr || output->empty()) {
output = std::make_shared<Tensor<float>>(input->channels(), input->rows(), input->cols());
outputs.at(i) = output;
}

CHECK(output->shapes() == input->shapes())
<< "The input and output tensor shapes of the hardswish layer do not "
"match "
<< i << " th";

hardswish_function(input, output);
}
return StatusCode::kSuccess;
return ActivationForward(ActivationType::kActivationHardSwish, inputs, outputs);
}

StatusCode HardSwishLayer::CreateInstance(const std::shared_ptr<RuntimeOperator>& op,
Expand Down
37 changes: 2 additions & 35 deletions source/layer/details/relu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,43 +27,10 @@
namespace kuiper_infer {
StatusCode ReluLayer::Forward(const std::vector<std::shared_ptr<Tensor<float>>>& inputs,
std::vector<std::shared_ptr<Tensor<float>>>& outputs) {
if (inputs.empty()) {
LOG(ERROR) << "The input tensor array in the relu layer is empty";
return StatusCode::kInferInputsEmpty;
}

if (outputs.empty()) {
LOG(ERROR) << "The output tensor array in the relu layer is empty";
return StatusCode::kInferOutputsEmpty;
}

if (inputs.size() != outputs.size()) {
LOG(ERROR) << "The input and output tensor array size of the relu "
"layer do not match";
return StatusCode::kInferInOutShapeMismatch;
}

using namespace activation;
ActivationFunc relu_function = ApplySSEActivation(ActivationType::kActivationRelu);

const uint32_t batch_size = inputs.size();
#pragma omp parallel for num_threads(batch_size)
for (uint32_t i = 0; i < batch_size; ++i) {
const std::shared_ptr<Tensor<float>>& input = inputs.at(i);
CHECK(input != nullptr && !input->empty())
<< "The input tensor array in the relu layer has an empty tensor " << i << " th";

std::shared_ptr<Tensor<float>> output = outputs.at(i);
if (output == nullptr || output->empty()) {
output = std::make_shared<Tensor<float>>(input->shapes());
outputs.at(i) = output;
}
CHECK(output != nullptr && output->shapes() == input->shapes())
<< "The input and output tensor shapes of the relu layer do not match " << i << " th";
relu_function(input, output);
}
return StatusCode::kSuccess;
return ActivationForward(ActivationType::kActivationRelu, inputs, outputs);
}

StatusCode ReluLayer::CreateInstance(const std::shared_ptr<RuntimeOperator>& op,
std::shared_ptr<Layer<float>>& relu_layer) {
if (!op) {
Expand Down
40 changes: 3 additions & 37 deletions source/layer/details/relu6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,46 +26,12 @@

namespace kuiper_infer {
StatusCode Relu6Layer::Forward(const std::vector<std::shared_ptr<Tensor<float>>>& inputs,
std::vector<std::shared_ptr<Tensor<float>>>& outputs) {
if (inputs.empty()) {
LOG(ERROR) << "The input tensor array in the relu6 layer is empty";
return StatusCode::kInferInputsEmpty;
}

if (outputs.empty()) {
LOG(ERROR) << "The output tensor array in the relu6 layer is empty";
return StatusCode::kInferOutputsEmpty;
}

if (inputs.size() != outputs.size()) {
LOG(ERROR) << "The input and output tensor array size of the relu6 "
"layer do not match";
return StatusCode::kInferInOutShapeMismatch;
}

std::vector<std::shared_ptr<Tensor<float>>>& outputs) {
using namespace activation;
ActivationFunc relu6_function = ApplySSEActivation(ActivationType::kActivationRelu6);

const uint32_t batch_size = inputs.size();
#pragma omp parallel for num_threads(batch_size)
for (uint32_t i = 0; i < batch_size; ++i) {
const std::shared_ptr<Tensor<float>>& input = inputs.at(i);
CHECK(input != nullptr && !input->empty())
<< "The input tensor array in the relu6 layer has an empty tensor " << i << " th";

std::shared_ptr<Tensor<float>> output = outputs.at(i);
if (output == nullptr || output->empty()) {
output = std::make_shared<Tensor<float>>(input->shapes());
outputs.at(i) = output;
}
CHECK(output != nullptr && output->shapes() == input->shapes())
<< "The input and output tensor shapes of the relu6 layer do not match " << i << " th";
relu6_function(input, output);
}
return StatusCode::kSuccess;
return ActivationForward(ActivationType::kActivationRelu6, inputs, outputs);
}
StatusCode Relu6Layer::CreateInstance(const std::shared_ptr<RuntimeOperator>& op,
std::shared_ptr<Layer<float>>& relu_layer) {
std::shared_ptr<Layer<float>>& relu_layer) {
if (!op) {
LOG(ERROR) << "The relu6 operator parameter in the layer is null pointer.";
return StatusCode::kParseOperatorNullParam;
Expand Down
Loading

0 comments on commit a425a0a

Please sign in to comment.