tvm
Loading...
Searching...
No Matches
softmax.h
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
24#ifndef TVM_TOPI_NN_SOFTMAX_H_
25#define TVM_TOPI_NN_SOFTMAX_H_
26
27#include <tvm/te/operation.h>
28#include <tvm/topi/reduction.h>
29#include <tvm/topi/tags.h>
30
31#include <algorithm>
32#include <string>
33
34namespace tvm {
35namespace topi {
36namespace nn {
37
38using namespace tvm::te;
39
50inline Tensor softmax(const Tensor& x, int axis = -1, std::string name = "tensor",
51 std::string tag = "softmax_output") {
52 using namespace tvm::prim;
53 auto input_shape = x->shape;
54 auto ndim = input_shape.size();
55 if (axis < 0) {
56 axis = ndim + axis;
57 }
58 TVM_FFI_ICHECK_LT(axis, ndim) << "axis parameter should be less than input dim";
59
60 auto k1 = tvm::te::reduce_axis(Range(0, input_shape[axis]), "k1");
61 auto k2 = tvm::te::reduce_axis(Range(0, input_shape[axis]), "k2");
62 auto reduced_shape = MakeReduceTargetShape({axis}, x, false, false);
63
64 tvm::ffi::Map<ffi::String, ffi::Any> attrs;
65 attrs.Set(tvm::topi::attr::kAxis, IntImm::Int32(axis));
66
67 auto insert_reduce_index = [axis, ndim](const ffi::Array<PrimVar>& indices,
68 const IterVar& reduce_index) {
69 ffi::Array<PrimExpr> eval_range;
70 int arg_counter = 0;
71 for (size_t i = 0; i < ndim; ++i) {
72 if (static_cast<int>(i) == axis) {
73 eval_range.push_back(reduce_index);
74 } else {
75 eval_range.push_back(indices[arg_counter++]);
76 }
77 }
78 return eval_range;
79 };
80
81 auto get_non_reduce_indices = [axis, ndim](const ffi::Array<PrimVar>& indices) {
82 ffi::Array<PrimExpr> non_reduce_indices;
83 for (size_t i = 0; i < ndim; ++i) {
84 if (static_cast<int>(i) != axis) non_reduce_indices.push_back(indices[i]);
85 }
86 return non_reduce_indices;
87 };
88
89 auto _compute_max = [&](const ffi::Array<PrimVar>& indices) {
90 auto eval_range = insert_reduce_index(indices, k1);
91 return topi::MaxOp(x(eval_range), {k1});
92 };
93
94 auto _compute_exp = [&](const Tensor& max_elem, const ffi::Array<PrimVar>& indices) {
95 auto non_reduce_indices = get_non_reduce_indices(indices);
96 return tvm::prim::exp(x(indices) - max_elem(non_reduce_indices));
97 };
98
99 auto _compute_expsum = [&](const Tensor& exp, const ffi::Array<PrimVar>& indices) {
100 auto eval_range = insert_reduce_index(indices, k2);
101 return tvm::prim::sum(exp(eval_range), {k2});
102 };
103
104 auto _normalize = [&](const Tensor& exp, const Tensor& expsum,
105 const ffi::Array<PrimVar>& indices) {
106 auto non_reduce_indices = get_non_reduce_indices(indices);
107 return exp(indices) / expsum(non_reduce_indices);
108 };
109
110 auto max_elem = tvm::te::compute(reduced_shape, _compute_max);
111 auto exp = tvm::te::compute(input_shape, [&](const ffi::Array<PrimVar>& indices) {
112 return _compute_exp(max_elem, indices);
113 });
114 auto expsum = tvm::te::compute(reduced_shape, [&](const ffi::Array<PrimVar>& indices) {
115 return _compute_expsum(exp, indices);
116 });
117 return tvm::te::compute(
118 input_shape,
119 [&](const ffi::Array<PrimVar>& indices) { return _normalize(exp, expsum, indices); }, name,
120 tag, attrs);
121}
122
132inline Tensor log_softmax(const Tensor& x, std::string name = "tensor",
133 std::string tag = "log_softmax_output") {
134 TVM_FFI_ICHECK_EQ(x->shape.size(), 2) << "Log softmax requires 2-D input";
135
136 PrimExpr m = x->shape[0];
137 PrimExpr n = x->shape[1];
138
139 auto k = tvm::te::reduce_axis(Range(0, n), "k");
140 auto max_elem =
141 tvm::te::compute({m}, [&](PrimVar i) { return tvm::max(x(i, k), ffi::Array<IterVar>{k}); });
142 k = tvm::te::reduce_axis(Range(0, n), "k");
143
144 auto expsum = tvm::te::compute(
145 {m}, [&](PrimVar i) { return tvm::prim::sum(tvm::prim::exp(x(i, k) - max_elem(i)), {k}); });
146
147 return tvm::te::compute(
148 x->shape,
149 [&](PrimVar i, PrimVar j) { return x(i, j) - max_elem(i) - tvm::prim::log(expsum(i)); }, name,
150 tag);
151}
152
153} // namespace nn
154} // namespace topi
155} // namespace tvm
156#endif // TVM_TOPI_NN_SOFTMAX_H_
static IntImm Int32(ffi::BigInt value, Location loc=UnknownLoc())
Construct a scalar int32 constant.
Definition expr.h:181
Typed reference/view over any Expr whose ExprNode::ty is PrimType.
Definition base_expr.h:447
Checked scalar view over a VarNode.
Definition expr.h:742
Range container
Definition expr.h:1025
Iteration Variable, represents an iteration over an integer interval.
Definition iter_var.h:147
Tensor structure representing a possible input, or intermediate computation result.
Definition tensor.h:111
Definition expr.h:47
PrimExpr sum(PrimExpr source, ffi::Array< s_tir::IterVar > axis, ffi::Array< PrimExpr > init={}, Location loc=UnknownLoc())
sum of source expression over axis
PrimExpr exp(PrimExpr x, Location loc=UnknownLoc())
Definition op.h:1003
Tensor expression language DSL.
Definition extracted_task.h:33
IterVar reduce_axis(Range dom, std::string name="rv")
Create a new IterVar for reduction operations.
Tensor compute(ffi::Array< PrimExpr > shape, FCompute fcompute, std::string name="tensor", std::string tag="", ffi::Map< ffi::String, ffi::Any > attrs={})
Construct a new tensor by computing over shape, using the computation rule: result_tensor[axis] = fco...
constexpr const char * kAxis
Definition tags.h:65
Tensor softmax(const Tensor &x, int axis=-1, std::string name="tensor", std::string tag="softmax_output")
Softmax activation.
Definition softmax.h:50
Tensor log_softmax(const Tensor &x, std::string name="tensor", std::string tag="log_softmax_output")
Log softmax activation.
Definition softmax.h:132
ffi::Array< PrimExpr > MakeReduceTargetShape(const std::vector< int > &real_axis, const Tensor &data, bool keepdims, bool atleast1d)
Calculate the target shape for a reduce op.
Definition reduction.h:98
Tensor exp(const Tensor &x, std::string name="T_" "exp", std::string tag=kElementWise)
Definition elemwise.h:50
PrimExpr MaxOp(PrimExpr source, ffi::Array< IterVar > axis, ffi::Array< PrimExpr > init={}, Location loc=UnknownLoc())
Wrap tvm::max to ensure we get the correct overload.
Definition reduction.h:312
An object that builds and maintains block scope and StmtSref mapping for Dependence analysis.
Definition attr.h:23
TVM_TIRX_DLL PrimExpr max(PrimExpr a, PrimExpr b, Location loc=UnknownLoc())
take maximum of two values
Operation node can generate one or multiple Tensors.
Tag definitions.
Reduction op constructors.