mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
Merge pull request #15510 from seiko2plus:issue15506
* core: rework and optimize SIMD implementation of dotProd
- add new universal intrinsics v_dotprod[int32], v_dotprod_expand[u&int8, u&int16, int32], v_cvt_f64(int64)
- add a boolean param for all v_dotprod&_expand intrinsics that change the behavior of addition order between
pairs in some platforms in order to reach the maximum optimization when the sum among all lanes is what only matters
- fix clang build on ppc64le
- support wide universal intrinsics for dotProd_32s
- remove raw SIMD and activate universal intrinsics for dotProd_8
- implement SIMD optimization for dotProd_s16&u16
- extend performance test data types of dotprod
- fix GCC VSX workaround of vec_mule and vec_mulo (in little-endian it must be swapped)
- optimize v_mul_expand(int32) on VSX
* core: remove boolean param from v_dotprod&_expand and implement v_dotprod_fast&v_dotprod_expand_fast
this changes made depend on "terfendail" review
This commit is contained in:
committed by
Alexander Alekhin
parent
7837ae0e19
commit
f2fe6f40c2
@@ -603,12 +603,14 @@ template<typename R> struct TheTest
|
||||
return *this;
|
||||
}
|
||||
|
||||
TheTest & test_dot_prod()
|
||||
TheTest & test_dotprod()
|
||||
{
|
||||
typedef typename V_RegTraits<R>::w_reg Rx2;
|
||||
typedef typename Rx2::lane_type w_type;
|
||||
|
||||
Data<R> dataA, dataB(2);
|
||||
Data<R> dataA, dataB;
|
||||
dataA += std::numeric_limits<LaneType>::max() - R::nlanes;
|
||||
dataB += std::numeric_limits<LaneType>::min() + R::nlanes;
|
||||
R a = dataA, b = dataB;
|
||||
|
||||
Data<Rx2> dataC;
|
||||
@@ -621,12 +623,95 @@ template<typename R> struct TheTest
|
||||
resE = v_dotprod(a, b, c);
|
||||
|
||||
const int n = R::nlanes / 2;
|
||||
w_type sumAB = 0, sumABC = 0, tmp_sum;
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("i=%d", i));
|
||||
EXPECT_EQ(dataA[i*2] * dataB[i*2] + dataA[i*2 + 1] * dataB[i*2 + 1], resD[i]);
|
||||
EXPECT_EQ(dataA[i*2] * dataB[i*2] + dataA[i*2 + 1] * dataB[i*2 + 1] + dataC[i], resE[i]);
|
||||
|
||||
tmp_sum = (w_type)dataA[i*2] * (w_type)dataB[i*2] +
|
||||
(w_type)dataA[i*2 + 1] * (w_type)dataB[i*2 + 1];
|
||||
sumAB += tmp_sum;
|
||||
EXPECT_EQ(tmp_sum, resD[i]);
|
||||
|
||||
tmp_sum = tmp_sum + dataC[i];
|
||||
sumABC += tmp_sum;
|
||||
EXPECT_EQ(tmp_sum, resE[i]);
|
||||
}
|
||||
|
||||
w_type resF = v_reduce_sum(v_dotprod_fast(a, b)),
|
||||
resG = v_reduce_sum(v_dotprod_fast(a, b, c));
|
||||
EXPECT_EQ(sumAB, resF);
|
||||
EXPECT_EQ(sumABC, resG);
|
||||
return *this;
|
||||
}
|
||||
|
||||
TheTest & test_dotprod_expand()
|
||||
{
|
||||
typedef typename V_RegTraits<R>::q_reg Rx4;
|
||||
typedef typename Rx4::lane_type l4_type;
|
||||
|
||||
Data<R> dataA, dataB;
|
||||
dataA += std::numeric_limits<LaneType>::max() - R::nlanes;
|
||||
dataB += std::numeric_limits<LaneType>::min() + R::nlanes;
|
||||
R a = dataA, b = dataB;
|
||||
|
||||
Data<Rx4> dataC;
|
||||
Rx4 c = dataC;
|
||||
|
||||
Data<Rx4> resD = v_dotprod_expand(a, b),
|
||||
resE = v_dotprod_expand(a, b, c);
|
||||
|
||||
l4_type sumAB = 0, sumABC = 0, tmp_sum;
|
||||
for (int i = 0; i < Rx4::nlanes; ++i)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("i=%d", i));
|
||||
tmp_sum = (l4_type)dataA[i*4] * (l4_type)dataB[i*4] +
|
||||
(l4_type)dataA[i*4 + 1] * (l4_type)dataB[i*4 + 1] +
|
||||
(l4_type)dataA[i*4 + 2] * (l4_type)dataB[i*4 + 2] +
|
||||
(l4_type)dataA[i*4 + 3] * (l4_type)dataB[i*4 + 3];
|
||||
sumAB += tmp_sum;
|
||||
EXPECT_EQ(tmp_sum, resD[i]);
|
||||
|
||||
tmp_sum = tmp_sum + dataC[i];
|
||||
sumABC += tmp_sum;
|
||||
EXPECT_EQ(tmp_sum, resE[i]);
|
||||
}
|
||||
|
||||
l4_type resF = v_reduce_sum(v_dotprod_expand_fast(a, b)),
|
||||
resG = v_reduce_sum(v_dotprod_expand_fast(a, b, c));
|
||||
EXPECT_EQ(sumAB, resF);
|
||||
EXPECT_EQ(sumABC, resG);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TheTest & test_dotprod_expand_f64()
|
||||
{
|
||||
#if CV_SIMD_64F
|
||||
Data<R> dataA, dataB;
|
||||
dataA += std::numeric_limits<LaneType>::max() - R::nlanes;
|
||||
dataB += std::numeric_limits<LaneType>::min();
|
||||
R a = dataA, b = dataB;
|
||||
|
||||
Data<v_float64> dataC;
|
||||
v_float64 c = dataC;
|
||||
|
||||
Data<v_float64> resA = v_dotprod_expand(a, a),
|
||||
resB = v_dotprod_expand(b, b),
|
||||
resC = v_dotprod_expand(a, b, c);
|
||||
|
||||
const int n = R::nlanes / 2;
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("i=%d", i));
|
||||
EXPECT_EQ((double)dataA[i*2] * (double)dataA[i*2] +
|
||||
(double)dataA[i*2 + 1] * (double)dataA[i*2 + 1], resA[i]);
|
||||
EXPECT_EQ((double)dataB[i*2] * (double)dataB[i*2] +
|
||||
(double)dataB[i*2 + 1] * (double)dataB[i*2 + 1], resB[i]);
|
||||
EXPECT_EQ((double)dataA[i*2] * (double)dataB[i*2] +
|
||||
(double)dataA[i*2 + 1] * (double)dataB[i*2 + 1] + dataC[i], resC[i]);
|
||||
}
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1165,6 +1250,29 @@ template<typename R> struct TheTest
|
||||
return *this;
|
||||
}
|
||||
|
||||
TheTest & test_cvt64_double()
|
||||
{
|
||||
#if CV_SIMD_64F
|
||||
Data<R> dataA(std::numeric_limits<LaneType>::max()),
|
||||
dataB(std::numeric_limits<LaneType>::min());
|
||||
dataB += R::nlanes;
|
||||
|
||||
R a = dataA, b = dataB;
|
||||
v_float64 c = v_cvt_f64(a), d = v_cvt_f64(b);
|
||||
|
||||
Data<v_float64> resC = c;
|
||||
Data<v_float64> resD = d;
|
||||
|
||||
for (int i = 0; i < R::nlanes; ++i)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("i=%d", i));
|
||||
EXPECT_EQ((double)dataA[i], resC[i]);
|
||||
EXPECT_EQ((double)dataB[i], resD[i]);
|
||||
}
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
TheTest & test_matmul()
|
||||
{
|
||||
Data<R> dataV, dataA, dataB, dataC, dataD;
|
||||
@@ -1341,6 +1449,7 @@ void test_hal_intrin_uint8()
|
||||
.test_mul_expand()
|
||||
.test_cmp()
|
||||
.test_logic()
|
||||
.test_dotprod_expand()
|
||||
.test_min_max()
|
||||
.test_absdiff()
|
||||
.test_reduce_sad()
|
||||
@@ -1378,6 +1487,7 @@ void test_hal_intrin_int8()
|
||||
.test_mul_expand()
|
||||
.test_cmp()
|
||||
.test_logic()
|
||||
.test_dotprod_expand()
|
||||
.test_min_max()
|
||||
.test_absdiff()
|
||||
.test_absdiffs()
|
||||
@@ -1408,6 +1518,7 @@ void test_hal_intrin_uint16()
|
||||
.test_cmp()
|
||||
.test_shift<1>()
|
||||
.test_shift<8>()
|
||||
.test_dotprod_expand()
|
||||
.test_logic()
|
||||
.test_min_max()
|
||||
.test_absdiff()
|
||||
@@ -1437,7 +1548,8 @@ void test_hal_intrin_int16()
|
||||
.test_cmp()
|
||||
.test_shift<1>()
|
||||
.test_shift<8>()
|
||||
.test_dot_prod()
|
||||
.test_dotprod()
|
||||
.test_dotprod_expand()
|
||||
.test_logic()
|
||||
.test_min_max()
|
||||
.test_absdiff()
|
||||
@@ -1497,6 +1609,8 @@ void test_hal_intrin_int32()
|
||||
.test_cmp()
|
||||
.test_popcount()
|
||||
.test_shift<1>().test_shift<8>()
|
||||
.test_dotprod()
|
||||
.test_dotprod_expand_f64()
|
||||
.test_logic()
|
||||
.test_min_max()
|
||||
.test_absdiff()
|
||||
@@ -1538,6 +1652,7 @@ void test_hal_intrin_int64()
|
||||
.test_logic()
|
||||
.test_extract<0>().test_extract<1>()
|
||||
.test_rotate<0>().test_rotate<1>()
|
||||
.test_cvt64_double()
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user