| #include "caffe2/operators/softmax_utils.h" | |
| #include "caffe2/core/context.h" | |
| #include "caffe2/utils/eigen_utils.h" | |
| #include "caffe2/utils/math.h" | |
| namespace caffe2 { | |
| namespace softmax_utils { | |
| #define CAFFE2_SPECIALIZED_SOFTMAX_CPU(T) \ | |
| template <> \ | |
| void SoftmaxCPU<T>( \ | |
| const int N, \ | |
| const int D, \ | |
| const bool logarithmic, \ | |
| const T* X, \ | |
| T* Y, \ | |
| T* scratch, \ | |
| CPUContext* context) { \ | |
| ConstEigenArrayMap<T> X_arr(X, D, N); \ | |
| EigenArrayMap<T> Y_arr(Y, D, N); \ | |
| EigenVectorArrayMap<T> scratch_arr(scratch, N); \ | |
| scratch_arr = X_arr.colwise().maxCoeff().transpose(); \ | |
| Y_arr = X_arr.rowwise() - scratch_arr.transpose(); \ | |
| math::Exp<T, CPUContext>(N * D, Y, Y, context); \ | |
| if (logarithmic) { \ | |
| scratch_arr += Y_arr.colwise().sum().log().transpose(); \ | |
| Y_arr = X_arr.rowwise() - scratch_arr.transpose(); \ | |
| } else { \ | |
| scratch_arr = Y_arr.colwise().sum().inverse().transpose(); \ | |
| Y_arr = Y_arr.rowwise() * scratch_arr.transpose(); \ | |
| } \ | |
| } | |
| CAFFE2_SPECIALIZED_SOFTMAX_CPU(float) | |
| #undef CAFFE2_SPECIALIZED_SOFTMAX_CPU | |
| } // namespace softmax_utils | |
| } // namespace caffe2 |