| 100 | } |
| 101 | |
| 102 | Status validate_arguments(const ITensorInfo *src, |
| 103 | const ITensorInfo *weights, |
| 104 | const ITensorInfo *biases, |
| 105 | const ITensorInfo *dst, |
| 106 | const PadStrideInfo &conv_info, |
| 107 | const ActivationLayerInfo &act_info, |
| 108 | bool enable_fast_math) |
| 109 | { |
| 110 | // Get indeces for the width and height |
| 111 | const size_t idx_width = get_data_layout_dimension_index(src->data_layout(), DataLayoutDimension::WIDTH); |
| 112 | const size_t idx_height = get_data_layout_dimension_index(src->data_layout(), DataLayoutDimension::HEIGHT); |
| 113 | |
| 114 | // Input shape, kernel size and output tile |
| 115 | const Size2D input_dims = Size2D(src->tensor_shape()[idx_width], src->tensor_shape()[idx_height]); |
| 116 | const Size2D kernel_size = Size2D(weights->tensor_shape()[idx_width], weights->tensor_shape()[idx_height]); |
| 117 | const Size2D output_tile = winograd_output_tile(input_dims, kernel_size, src->data_layout()); |
| 118 | |
| 119 | ARM_COMPUTE_RETURN_ERROR_ON_MSG( |
| 120 | ((conv_info.pad_left() > (kernel_size.x() / 2u)) || (conv_info.pad_right() > (kernel_size.x() / 2u))), |
| 121 | "Winograd only supports padding up to half kernel size"); |
| 122 | ARM_COMPUTE_RETURN_ERROR_ON_MSG( |
| 123 | ((conv_info.pad_top() > (kernel_size.y() / 2u)) || (conv_info.pad_bottom() > (kernel_size.y() / 2u))), |
| 124 | "Winograd only supports padding up to half kernel size"); |
| 125 | |
| 126 | // Check if the Winograd configuration requires fast math |
| 127 | if (!enable_fast_math) |
| 128 | { |
| 129 | ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN( |
| 130 | src, 1, DataType::F32); //disable winograd for fp16 if fast math is false. |
| 131 | ARM_COMPUTE_RETURN_ERROR_ON_MSG(check_support_fast_math(output_tile, kernel_size), |
| 132 | "This Winograd configuration requires enable_fast_math=true"); |
| 133 | } |
| 134 | |
| 135 | const WinogradInfo winograd_info = |
| 136 | WinogradInfo(output_tile, kernel_size, input_dims, conv_info, src->data_layout()); |
| 137 | |
| 138 | // Validate input transform |
| 139 | const TensorShape input0_shape = |
| 140 | misc::shape_calculator::compute_winograd_input_transform_shape(*src, winograd_info); |
| 141 | const TensorInfo input0 = src->clone()->set_tensor_shape(input0_shape); |
| 142 | ARM_COMPUTE_RETURN_ON_ERROR(kernels::ClWinogradInputTransformKernel::validate(src, &input0, winograd_info)); |
| 143 | |
| 144 | // Validate filter transform |
| 145 | const TensorShape input1_shape = |
| 146 | misc::shape_calculator::compute_winograd_filter_transform_shape(*weights, winograd_info); |
| 147 | const TensorInfo input1 = weights->clone()->set_tensor_shape(input1_shape); |
| 148 | ARM_COMPUTE_RETURN_ON_ERROR(kernels::ClWinogradFilterTransformKernel::validate(weights, &input1, winograd_info)); |
| 149 | |
| 150 | // Validate batched matrix multiply |
| 151 | TensorShape batched_mm_output_shape = input0.tensor_shape(); |
| 152 | batched_mm_output_shape[0] = input1.tensor_shape()[0]; |
| 153 | const TensorInfo batched_mm_output = input0.clone()->set_tensor_shape(batched_mm_output_shape); |
| 154 | ARM_COMPUTE_RETURN_ON_ERROR( |
| 155 | ClGemm::validate(&input0, &input1, nullptr, &batched_mm_output, 1.0f, 0.0f, |
| 156 | GEMMInfo(false, false, true /* Reshape weights only for the first run*/, 0, false, false, |
| 157 | GEMMLowpOutputStageInfo(), (src->data_type() == DataType::F16)))); |
| 158 | |
| 159 | // Configure output transform |
no test coverage detected