Files
SDK_SG200x_V2/cviruntime/custom_op/example/runtime/SoftmaxOpRuntime.cpp
carbon e25f20f7a3 add cviruntime
commit 3f4938648950a7f3bf9a19c320ca9fae7c52de20
Author: sophgo-forum-service <forum_service@sophgo.com>
Date:   Mon May 13 13:44:23 2024 +0800

    [feat] cviruntime opensource for cv18xx soc.

    - a4b6a3, add cumsum and gatherelements_pt.
2024-05-31 11:51:34 +08:00

74 lines
1.9 KiB
C++

/*
* Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
*/
#include <cmath>
#include <string.h>
#include "SoftmaxOpRuntime.hpp"
SoftmaxOpRuntime::~SoftmaxOpRuntime() {
if (_max)
delete[] _max;
if (_sum)
delete[] _sum;
}
void SoftmaxOpRuntime::setup(std::vector<std::shared_ptr<cvi::runtime::Neuron>> &inputs,
std::vector<std::shared_ptr<cvi::runtime::Neuron>> &outputs,
cvi::OpParam &param) {
_bottom = inputs[0];
_top = outputs[0];
_axis = param.get<int32_t>("axis");
assert(_axis >= 0);
auto shape = _bottom->shape;
_axis = _axis % shape.size();
_n = 1;
for(int i = 0; i < _axis; ++i) {
_n *= shape[i];
}
_inner_dim = 1;
for(size_t i = _axis+1; i < shape.size(); ++i) {
_inner_dim *= shape[i];
}
_c = shape[_axis];
_dim = _c * _inner_dim;
_max = new float[_inner_dim];
_sum = new float[_inner_dim];
}
void SoftmaxOpRuntime::run() {
auto bottom_data = _bottom->cpu_data<float>();
auto top_data = _top->cpu_data<float>();
for (int i = 0; i < _n; ++i) {
memcpy(_max, bottom_data, _inner_dim * sizeof(float));
memset(_sum, 0, _inner_dim * sizeof(float));
// find max value accross channel
int c_offset = i * _dim;
for (int j = 0; j < _c; ++j, c_offset += _inner_dim) {
for (int k = 0; k < _inner_dim; k++) {
if (_max[k] < bottom_data[c_offset + k])
_max[k] = bottom_data[c_offset + k];
}
}
// calculate exp(x)
c_offset = i * _dim;
for (int j = 0; j < _c; ++j, c_offset += _inner_dim) {
for (int k = 0; k < _inner_dim; k++) {
top_data[c_offset + k] = std::exp(bottom_data[c_offset + k] - _max[k]);
_sum[k] += top_data[c_offset + k];
}
}
c_offset = i * _dim;
for (int j = 0; j < _c; ++j, c_offset += _inner_dim) {
for (int k = 0; k < _inner_dim; k++) {
top_data[c_offset + k] /= _sum[k];
}
}
}
}