From 09d3451b4caf8d5e0e7cf2c6097e50a1f815d027 Mon Sep 17 00:00:00 2001 From: Georgios Pinitas Date: Thu, 30 Aug 2018 16:02:11 +0100 Subject: COMPMID-1548: NEON FP16 mismatches on CannyEdge and HarrisCorners. Removes FP16 from HarrisCorners and CannyEdge. Change-Id: I5e4f9205fdbe4de85f04f55ecf1568c837e56cc0 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/146247 Tested-by: Jenkins Reviewed-by: Michele DiGiorgio --- src/core/NEON/kernels/NEHarrisCornersKernel.cpp | 324 ------------------------ 1 file changed, 324 deletions(-) (limited to 'src/core/NEON/kernels/NEHarrisCornersKernel.cpp') diff --git a/src/core/NEON/kernels/NEHarrisCornersKernel.cpp b/src/core/NEON/kernels/NEHarrisCornersKernel.cpp index 5e1c216b65..61221c1070 100644 --- a/src/core/NEON/kernels/NEHarrisCornersKernel.cpp +++ b/src/core/NEON/kernels/NEHarrisCornersKernel.cpp @@ -39,330 +39,6 @@ using namespace arm_compute; -#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC - -namespace fp16 -{ -inline float16x8_t harris_score(float16x8_t gx2, float16x8_t gy2, float16x8_t gxgy, float sensitivity, float strength_thresh) -{ - static const float16x8_t zero = vdupq_n_f16(0.f); - - // Trace^2 - float16x8_t trace2 = vaddq_f16(gx2, gy2); - trace2 = vmulq_f16(trace2, trace2); - - // Det(A) - float16x8_t det = vmulq_f16(gx2, gy2); - det = vfmsq_f16(det, gxgy, gxgy); - - // Det(A) - sensitivity * trace^2 - const float16x8_t mc = vfmsq_f16(det, vdupq_n_f16(sensitivity), trace2); - - // mc > strength_thresh - const uint16x8_t mask = vcgtq_f16(mc, vdupq_n_f16(strength_thresh)); - - return vbslq_f16(mask, mc, zero); -} - -template -inline void harris_score1xN_FLOAT_FLOAT_FLOAT(float16x8_t low_gx, float16x8_t low_gy, float16x8_t high_gx, float16x8_t high_gy, float16x8_t &gx2, float16x8_t &gy2, float16x8_t &gxgy, - float norm_factor) -{ - const float16x8_t norm_factor_fp16 = vdupq_n_f16(norm_factor); - - // Normalize - low_gx = vmulq_f16(low_gx, norm_factor_fp16); - low_gy = vmulq_f16(low_gy, norm_factor_fp16); - high_gx = vmulq_f16(high_gx, norm_factor_fp16); - high_gy = vmulq_f16(high_gy, norm_factor_fp16); - - float16x8_t gx = vextq_f16(low_gx, high_gx, 0); - float16x8_t gy = vextq_f16(low_gy, high_gy, 0); - - gx2 = vfmaq_f16(gx2, gx, gx); - gy2 = vfmaq_f16(gy2, gy, gy); - gxgy = vfmaq_f16(gxgy, gx, gy); - - gx = vextq_f16(low_gx, high_gx, 1); - gy = vextq_f16(low_gy, high_gy, 1); - - gx2 = vfmaq_f16(gx2, gx, gx); - gy2 = vfmaq_f16(gy2, gy, gy); - gxgy = vfmaq_f16(gxgy, gx, gy); - - gx = vextq_f16(low_gx, high_gx, 2); - gy = vextq_f16(low_gy, high_gy, 2); - - gx2 = vfmaq_f16(gx2, gx, gx); - gy2 = vfmaq_f16(gy2, gy, gy); - gxgy = vfmaq_f16(gxgy, gx, gy); - - if(block_size > 3) - { - gx = vextq_f16(low_gx, high_gx, 3); - gy = vextq_f16(low_gy, high_gy, 3); - - gx2 = vfmaq_f16(gx2, gx, gx); - gy2 = vfmaq_f16(gy2, gy, gy); - gxgy = vfmaq_f16(gxgy, gx, gy); - - gx = vextq_f16(low_gx, high_gx, 4); - gy = vextq_f16(low_gy, high_gy, 4); - - gx2 = vfmaq_f16(gx2, gx, gx); - gy2 = vfmaq_f16(gy2, gy, gy); - gxgy = vfmaq_f16(gxgy, gx, gy); - } - - if(block_size == 7) - { - gx = vextq_f16(low_gx, high_gx, 5); - gy = vextq_f16(low_gy, high_gy, 5); - - gx2 = vfmaq_f16(gx2, gx, gx); - gy2 = vfmaq_f16(gy2, gy, gy); - gxgy = vfmaq_f16(gxgy, gx, gy); - - gx = vextq_f16(low_gx, high_gx, 6); - gy = vextq_f16(low_gy, high_gy, 6); - - gx2 = vfmaq_f16(gx2, gx, gx); - gy2 = vfmaq_f16(gy2, gy, gy); - gxgy = vfmaq_f16(gxgy, gx, gy); - } -} - -template -inline void harris_score_S16_S16_FLOAT(const void *__restrict in1_ptr, const void *__restrict in2_ptr, void *__restrict out_ptr, int32_t in_stride, float norm_factor, float sensitivity, - float strength_thresh) -{ - auto gx_ptr_0 = static_cast(in1_ptr) - (block_size / 2) * (in_stride + 1); - auto gy_ptr_0 = static_cast(in2_ptr) - (block_size / 2) * (in_stride + 1); - const int16_t *gx_ptr_1 = gx_ptr_0 + 8; - const int16_t *gy_ptr_1 = gy_ptr_0 + 8; - const auto output = static_cast(out_ptr); - - // Gx^2, Gy^2 and Gx*Gy - float16x8_t gx2 = vdupq_n_f16(0.0f); - float16x8_t gy2 = vdupq_n_f16(0.0f); - float16x8_t gxgy = vdupq_n_f16(0.0f); - - for(size_t i = 0; i < block_size; ++i) - { - const float16x8_t low_gx = vcvtq_f16_s16(vld1q_s16(gx_ptr_0)); - const float16x8_t high_gx = vcvtq_f16_s16(vld1q_s16(gx_ptr_1)); - const float16x8_t low_gy = vcvtq_f16_s16(vld1q_s16(gy_ptr_0)); - const float16x8_t high_gy = vcvtq_f16_s16(vld1q_s16(gy_ptr_1)); - harris_score1xN_FLOAT_FLOAT_FLOAT(low_gx, low_gy, high_gx, high_gy, gx2, gy2, gxgy, norm_factor); - - // Update gx and gy pointer - gx_ptr_0 += in_stride; - gy_ptr_0 += in_stride; - gx_ptr_1 += in_stride; - gy_ptr_1 += in_stride; - } - - // Calculate harris score - const float16x8_t mc = harris_score(gx2, gy2, gxgy, sensitivity, strength_thresh); - - // Store score - vst1q_f32(output + 0, vcvt_f32_f16(vget_low_f16(mc))); - vst1q_f32(output + 4, vcvt_f32_f16(vget_high_f16(mc))); -} - -template -inline void harris_score_S32_S32_FLOAT(const void *__restrict in1_ptr, const void *__restrict in2_ptr, void *__restrict out_ptr, int32_t in_stride, float norm_factor, float sensitivity, - float strength_thresh) -{ - static const float16x8_t zero = vdupq_n_f16(0.0f); - - auto gx_ptr_0 = static_cast(in1_ptr) - (block_size / 2) * (in_stride + 1); - auto gy_ptr_0 = static_cast(in2_ptr) - (block_size / 2) * (in_stride + 1); - const int32_t *gx_ptr_1 = gx_ptr_0 + 4; - const int32_t *gy_ptr_1 = gy_ptr_0 + 4; - const int32_t *gx_ptr_2 = gx_ptr_0 + 8; - const int32_t *gy_ptr_2 = gy_ptr_0 + 8; - const auto output = static_cast(out_ptr); - - // Gx^2, Gy^2 and Gx*Gy - float16x8_t gx2 = zero; - float16x8_t gy2 = zero; - float16x8_t gxgy = zero; - - for(size_t i = 0; i < block_size; ++i) - { - const float16x8_t low_gx = vcombine_f16(vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gx_ptr_0))), - vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gx_ptr_1)))); - const float16x8_t high_gx = vcombine_f16(vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gx_ptr_2))), - vget_low_f16(zero)); - const float16x8_t low_gy = vcombine_f16(vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gy_ptr_0))), - vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gy_ptr_1)))); - const float16x8_t high_gy = vcombine_f16(vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gy_ptr_2))), - vget_low_f16(zero)); - harris_score1xN_FLOAT_FLOAT_FLOAT(low_gx, low_gy, high_gx, high_gy, gx2, gy2, gxgy, norm_factor); - - // Update gx and gy pointer - gx_ptr_0 += in_stride; - gy_ptr_0 += in_stride; - gx_ptr_1 += in_stride; - gy_ptr_1 += in_stride; - gx_ptr_2 += in_stride; - gy_ptr_2 += in_stride; - } - - // Calculate harris score - const float16x8_t mc = harris_score(gx2, gy2, gxgy, sensitivity, strength_thresh); - - // Store score - vst1q_f32(output + 0, vcvt_f32_f16(vget_low_f16(mc))); - vst1q_f32(output + 4, vcvt_f32_f16(vget_high_f16(mc))); -} - -template <> -inline void harris_score_S32_S32_FLOAT<7>(const void *__restrict in1_ptr, const void *__restrict in2_ptr, void *__restrict out_ptr, int32_t in_stride, float norm_factor, float sensitivity, - float strength_thresh) -{ - static const float16x8_t zero = vdupq_n_f16(0.0f); - - auto gx_ptr_0 = static_cast(in1_ptr) - 3 * (in_stride + 1); - auto gy_ptr_0 = static_cast(in2_ptr) - 3 * (in_stride + 1); - const int32_t *gx_ptr_1 = gx_ptr_0 + 4; - const int32_t *gy_ptr_1 = gy_ptr_0 + 4; - const int32_t *gx_ptr_2 = gx_ptr_0 + 8; - const int32_t *gy_ptr_2 = gy_ptr_0 + 8; - const int32_t *gx_ptr_3 = gx_ptr_0 + 12; - const int32_t *gy_ptr_3 = gy_ptr_0 + 12; - const auto output = static_cast(out_ptr); - - // Gx^2, Gy^2 and Gx*Gy - float16x8_t gx2 = zero; - float16x8_t gy2 = zero; - float16x8_t gxgy = zero; - - for(size_t i = 0; i < 7; ++i) - { - const float16x8_t low_gx = vcombine_f16(vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gx_ptr_0))), - vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gx_ptr_1)))); - const float16x8_t high_gx = vcombine_f16(vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gx_ptr_2))), - vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gx_ptr_3)))); - const float16x8_t low_gy = vcombine_f16(vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gy_ptr_0))), - vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gy_ptr_1)))); - const float16x8_t high_gy = vcombine_f16(vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gy_ptr_2))), - vcvt_f16_f32(vcvtq_f32_s32(vld1q_s32(gy_ptr_3)))); - harris_score1xN_FLOAT_FLOAT_FLOAT<7>(low_gx, low_gy, high_gx, high_gy, gx2, gy2, gxgy, norm_factor); - - // Update gx and gy pointer - gx_ptr_0 += in_stride; - gy_ptr_0 += in_stride; - gx_ptr_1 += in_stride; - gy_ptr_1 += in_stride; - gx_ptr_2 += in_stride; - gy_ptr_2 += in_stride; - } - - // Calculate harris score - const float16x8_t mc = harris_score(gx2, gy2, gxgy, sensitivity, strength_thresh); - - // Store score - vst1q_f32(output + 0, vcvt_f32_f16(vget_low_f16(mc))); - vst1q_f32(output + 4, vcvt_f32_f16(vget_high_f16(mc))); -} - -} // namespace fp16 - -template -BorderSize NEHarrisScoreFP16Kernel::border_size() const -{ - return _border_size; -} - -template -NEHarrisScoreFP16Kernel::NEHarrisScoreFP16Kernel() - : INEHarrisScoreKernel(), _func(nullptr) -{ -} - -template -void NEHarrisScoreFP16Kernel::run(const Window &window, const ThreadInfo &info) -{ - ARM_COMPUTE_UNUSED(info); - ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this); - ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(INEKernel::window(), window); - ARM_COMPUTE_ERROR_ON(_func == nullptr); - - Iterator input1(_input1, window); - Iterator input2(_input2, window); - Iterator output(_output, window); - - const size_t input_stride = _input1->info()->strides_in_bytes()[1] / element_size_from_data_type(_input1->info()->data_type()); - - execute_window_loop(window, [&](const Coordinates & id) - { - (*_func)(input1.ptr(), input2.ptr(), output.ptr(), input_stride, _norm_factor, _sensitivity, _strength_thresh); - }, - input1, input2, output); -} - -template -void NEHarrisScoreFP16Kernel::configure(const IImage *input1, const IImage *input2, IImage *output, float norm_factor, float strength_thresh, float sensitivity, - bool border_undefined) -{ - ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(input1); - ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(input2); - ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(output); - ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input1, 1, DataType::S16, DataType::S32); - ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input2, 1, DataType::S16, DataType::S32); - ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(output, 1, DataType::F32); - ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(input1, input2); - ARM_COMPUTE_ERROR_ON(0.0f == norm_factor); - - _input1 = input1; - _input2 = input2; - _output = output; - _sensitivity = sensitivity; - _strength_thresh = strength_thresh; - _norm_factor = norm_factor; - _border_size = BorderSize(block_size / 2); - - if(input1->info()->data_type() == DataType::S16) - { - _func = &fp16::harris_score_S16_S16_FLOAT; - } - else - { - _func = &fp16::harris_score_S32_S32_FLOAT; - } - - ARM_COMPUTE_ERROR_ON(nullptr == _func); - - constexpr unsigned int num_elems_processed_per_iteration = 8; - constexpr unsigned int num_elems_read_per_iteration = 16; - constexpr unsigned int num_elems_written_per_iteration = 8; - constexpr unsigned int num_rows_read_per_iteration = block_size; - - // Configure kernel window - Window win = calculate_max_window(*input1->info(), Steps(num_elems_processed_per_iteration), border_undefined, border_size()); - AccessWindowHorizontal output_access(output->info(), 0, num_elems_written_per_iteration); - - update_window_and_padding(win, - AccessWindowRectangle(input1->info(), -_border_size.left, -_border_size.top, num_elems_read_per_iteration, num_rows_read_per_iteration), - AccessWindowRectangle(input2->info(), -_border_size.left, -_border_size.top, num_elems_read_per_iteration, num_rows_read_per_iteration), - output_access); - - ValidRegion valid_region = intersect_valid_regions(input1->info()->valid_region(), - input2->info()->valid_region()); - - output_access.set_valid_region(win, valid_region, border_undefined, border_size()); - - INEKernel::configure(win); -} - -template class arm_compute::NEHarrisScoreFP16Kernel<3>; -template class arm_compute::NEHarrisScoreFP16Kernel<5>; -template class arm_compute::NEHarrisScoreFP16Kernel<7>; - -#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */ - template class arm_compute::NEHarrisScoreKernel<3>; template class arm_compute::NEHarrisScoreKernel<5>; template class arm_compute::NEHarrisScoreKernel<7>; -- cgit v1.2.1