| 176 | } |
| 177 | |
| 178 | void CpuSoftmaxKernel::configure( |
| 179 | const ITensorInfo *src, ITensorInfo *dst, float beta, bool is_log, int axis, ITensorInfo *tmp) |
| 180 | { |
| 181 | ARM_COMPUTE_TRACE_EVENT(ARM_COMPUTE_PROF_CAT_CPU, ARM_COMPUTE_PROF_LVL_CPU, "CpuSoftmaxKernel::configure"); |
| 182 | _axis = axis; |
| 183 | |
| 184 | ARM_COMPUTE_ERROR_ON_NULLPTR(src, dst, tmp); |
| 185 | ARM_COMPUTE_ERROR_THROW_ON(validate_arguments_softmax(*src, *dst, beta, axis, *tmp, is_log)); |
| 186 | |
| 187 | // Configure kernel window |
| 188 | const bool is_quantized_asymmetric = is_data_type_quantized_asymmetric(src->data_type()); |
| 189 | |
| 190 | // Output auto initialization if not yet initialized |
| 191 | const QuantizationInfo output_quantization = |
| 192 | is_quantized_asymmetric ? arm_compute::get_softmax_output_quantization_info(src->data_type(), is_log) |
| 193 | : dst->quantization_info(); |
| 194 | auto_init_if_empty(*dst, TensorInfo(*src).set_quantization_info(output_quantization).reset_padding()); |
| 195 | |
| 196 | // Tmp auto initialization if not yet initialized and src is quantized |
| 197 | if (is_quantized_asymmetric) |
| 198 | { |
| 199 | auto_init_if_empty(*tmp, TensorInfo(*src).set_data_type(DataType::F32).reset_padding()); |
| 200 | } |
| 201 | |
| 202 | const auto *uk = CpuSoftmaxKernel::get_implementation(SoftmaxKernelDataTypeISASelectorData{ |
| 203 | src->data_type(), CPUInfo::get().get_isa(), is_log, axis, CPUInfo::get().get_sme2_vector_length_in_bits()}); |
| 204 | ARM_COMPUTE_ERROR_ON(uk == nullptr || uk->ukernel == nullptr); |
| 205 | |
| 206 | std::string kernel_name = is_log ? std::string("CpuLogSoftmaxKernel") : std::string("CpuSoftmaxKernel"); |
| 207 | |
| 208 | _beta = beta; |
| 209 | _run_method = uk->ukernel; |
| 210 | _name = kernel_name.append("/").append(uk->name); |
| 211 | |
| 212 | Window win; |
| 213 | |
| 214 | int vec_size = 16 / dst->element_size(); |
| 215 | |
| 216 | if (_axis == 0) |
| 217 | { |
| 218 | win = calculate_max_window(*dst, Steps()); |
| 219 | |
| 220 | /// TODO:Check dimensions > 0 for holes only. For this, we need |
| 221 | /// a utility function checking if there are holes after some dimension. |
| 222 | if (!has_holes(*dst, dst->num_dimensions() - 1)) |
| 223 | { |
| 224 | win = win.collapse(win, Window::DimY); |
| 225 | } |
| 226 | } |
| 227 | else if (_axis > 0 && _axis <= 3) |
| 228 | { |
| 229 | win = calculate_max_window(*dst, Steps(vec_size)); |
| 230 | } |
| 231 | else |
| 232 | { |
| 233 | ARM_COMPUTE_ERROR("Invalid axis"); |
| 234 | } |
| 235 |
nothing calls this directly
no test coverage detected