mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Merge pull request #25796 from hanliutong:hfloat
Use hfloat instead of __fp16. #25796 Related: #25743 Currently, the type for the half-precision floating point data in the OpenCV source code is `__fp16`, which is a unique(?) type supported by the ARM compiler. Other compilers have very limited support for `__fp16`, so in order to introduce more backends that support FP16 (such as RISC-V), we may need a the more general FP16 type. In this patch, we use `hfloat` instead of `__fp16` in non-ARM code blocks, mainly affected parts are: - `core/hal/intrin.hpp`: Type Traits, REG Traits and `vx_` interface. - `core/hal/intrin_neon.hpp`: Universal Intrinsic API for FP16 type. - `core/test/test_intrin_utils.hpp`: Usage of Univseral Intrinsic - `core/include/opencv2/core/cvdef.h`: Definition of class `hfloat` If I understand correctly, class `hfloat` acts as a wrapper around FP16 types in different platform (`__fp16` for ARM and `_Float16` for RISC-V). Any OpenCV generic interface/source code should use `hfloat`, while platform-specific FP16 types only used in macro-guarded code blocks. /cc @fengyuentau @mshabunin ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [ ] I agree to contribute to the project under Apache 2 License. - [ ] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -55,13 +55,13 @@ template <typename R> struct Data
|
||||
template <typename T> Data<R> & operator*=(T m)
|
||||
{
|
||||
for (int i = 0; i < VTraits<R>::vlanes(); ++i)
|
||||
d[i] *= (LaneType)m;
|
||||
d[i] = (LaneType)(d[i] * m);
|
||||
return *this;
|
||||
}
|
||||
template <typename T> Data<R> & operator+=(T m)
|
||||
{
|
||||
for (int i = 0; i < VTraits<R>::vlanes(); ++i)
|
||||
d[i] += (LaneType)m;
|
||||
d[i] = (LaneType)(d[i] + m);
|
||||
return *this;
|
||||
}
|
||||
void fill(LaneType val, int s, int c = VTraits<R>::vlanes())
|
||||
@@ -113,9 +113,9 @@ template <typename R> struct Data
|
||||
}
|
||||
LaneType sum(int s, int c)
|
||||
{
|
||||
LaneType res = 0;
|
||||
LaneType res = (LaneType)0;
|
||||
for (int i = s; i < s + c; ++i)
|
||||
res += d[i];
|
||||
res = (LaneType)(res + d[i]);
|
||||
return res;
|
||||
}
|
||||
LaneType sum()
|
||||
@@ -131,7 +131,7 @@ template <typename R> struct Data
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
fill(0);
|
||||
fill((LaneType)0);
|
||||
}
|
||||
bool isZero() const
|
||||
{
|
||||
@@ -183,7 +183,7 @@ template<> inline void EXPECT_COMPARE_EQ_<double>(const double a, const double b
|
||||
}
|
||||
|
||||
#if CV_SIMD_FP16
|
||||
template<> inline void EXPECT_COMPARE_EQ_<__fp16>(const __fp16 a, const __fp16 b)
|
||||
template<> inline void EXPECT_COMPARE_EQ_<hfloat>(const hfloat a, const hfloat b)
|
||||
{
|
||||
EXPECT_LT(std::abs(float(a - b)), 0.126);
|
||||
}
|
||||
@@ -352,9 +352,9 @@ template<typename R> struct TheTest
|
||||
TheTest & test_interleave()
|
||||
{
|
||||
Data<R> data1, data2, data3, data4;
|
||||
data2 += 20;
|
||||
data3 += 40;
|
||||
data4 += 60;
|
||||
data2 += (LaneType)20;
|
||||
data3 += (LaneType)40;
|
||||
data4 += (LaneType)60;
|
||||
|
||||
|
||||
R a = data1, b = data2, c = data3;
|
||||
@@ -366,7 +366,7 @@ template<typename R> struct TheTest
|
||||
v_store_interleave(buf3, a, b, c);
|
||||
v_store_interleave(buf4, d, e, f, g);
|
||||
|
||||
Data<R> z(0);
|
||||
Data<R> z((LaneType)0);
|
||||
a = b = c = d = e = f = g = z;
|
||||
|
||||
v_load_deinterleave(buf3, a, b, c);
|
||||
@@ -647,9 +647,9 @@ template<typename R> struct TheTest
|
||||
TheTest & test_abs_fp16()
|
||||
{
|
||||
typedef typename V_RegTraits<R>::u_reg Ru; // v_float16x8
|
||||
typedef typename VTraits<Ru>::lane_type u_type; // __fp16
|
||||
typedef typename VTraits<R>::lane_type R_type; // __fp16
|
||||
Data<R> dataA, dataB(10);
|
||||
typedef typename VTraits<Ru>::lane_type u_type; // hfloat
|
||||
typedef typename VTraits<R>::lane_type R_type; // hfloat
|
||||
Data<R> dataA, dataB((LaneType)10);
|
||||
R a = dataA, b = dataB;
|
||||
a = v_sub(a, b);
|
||||
|
||||
@@ -659,7 +659,7 @@ template<typename R> struct TheTest
|
||||
for (int i = 0; i < VTraits<Ru>::vlanes(); ++i)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("i=%d", i));
|
||||
R_type ssub = (dataA[i] - dataB[i]) < R_type_lowest ? R_type_lowest : dataA[i] - dataB[i];
|
||||
R_type ssub = (R_type)((dataA[i] - dataB[i]) < R_type_lowest ? R_type_lowest : dataA[i] - dataB[i]);
|
||||
EXPECT_EQ((u_type)std::abs(ssub), resC[i]);
|
||||
}
|
||||
|
||||
@@ -930,10 +930,10 @@ template<typename R> struct TheTest
|
||||
{
|
||||
Data<R> dataA(std::numeric_limits<LaneType>::max()),
|
||||
dataB(std::numeric_limits<LaneType>::min());
|
||||
dataA[0] = -1;
|
||||
dataB[0] = 1;
|
||||
dataA[1] = 2;
|
||||
dataB[1] = -2;
|
||||
dataA[0] = (LaneType)-1;
|
||||
dataB[0] = (LaneType)1;
|
||||
dataA[1] = (LaneType)2;
|
||||
dataB[1] = (LaneType)-2;
|
||||
R a = dataA, b = dataB;
|
||||
Data<R> resC = v_absdiff(a, b);
|
||||
for (int i = 0; i < VTraits<R>::vlanes(); ++i)
|
||||
@@ -1008,9 +1008,9 @@ template<typename R> struct TheTest
|
||||
typedef typename VTraits<int_reg>::lane_type int_type;
|
||||
typedef typename VTraits<uint_reg>::lane_type uint_type;
|
||||
|
||||
Data<R> dataA, dataB(0), dataC, dataD(1), dataE(2);
|
||||
Data<R> dataA, dataB((LaneType)0), dataC, dataD((LaneType)1), dataE((LaneType)2);
|
||||
dataA[0] = (LaneType)std::numeric_limits<int_type>::max();
|
||||
dataA[1] *= (LaneType)-1;
|
||||
dataA[1] = (LaneType)(dataA[1] * (LaneType)-1);
|
||||
union
|
||||
{
|
||||
LaneType l;
|
||||
@@ -1025,7 +1025,7 @@ template<typename R> struct TheTest
|
||||
dataB[VTraits<R>::vlanes() / 2] = mask_one;
|
||||
dataC *= (LaneType)-1;
|
||||
R a = dataA, b = dataB, c = dataC, d = dataD, e = dataE;
|
||||
dataC[VTraits<R>::vlanes() - 1] = 0;
|
||||
dataC[VTraits<R>::vlanes() - 1] = (LaneType)0;
|
||||
R nl = dataC;
|
||||
|
||||
EXPECT_EQ(2, v_signmask(a));
|
||||
@@ -1586,14 +1586,15 @@ template<typename R> struct TheTest
|
||||
int i = 0;
|
||||
for (int j = i; j < i + 8; ++j) {
|
||||
SCOPED_TRACE(cv::format("i=%d j=%d", i, j));
|
||||
LaneType val = dataV[i] * data0[j] +
|
||||
LaneType val = (LaneType)(
|
||||
dataV[i] * data0[j] +
|
||||
dataV[i + 1] * data1[j] +
|
||||
dataV[i + 2] * data2[j] +
|
||||
dataV[i + 3] * data3[j] +
|
||||
dataV[i + 4] * data4[j] +
|
||||
dataV[i + 5] * data5[j] +
|
||||
dataV[i + 6] * data6[j] +
|
||||
dataV[i + 7] * data7[j];
|
||||
dataV[i + 7] * data7[j]);
|
||||
EXPECT_COMPARE_EQ(val, res[j]);
|
||||
}
|
||||
|
||||
@@ -1601,14 +1602,15 @@ template<typename R> struct TheTest
|
||||
i = 0;
|
||||
for (int j = i; j < i + 8; ++j) {
|
||||
SCOPED_TRACE(cv::format("i=%d j=%d", i, j));
|
||||
LaneType val = dataV[i] * data0[j] +
|
||||
LaneType val = (LaneType)(
|
||||
dataV[i] * data0[j] +
|
||||
dataV[i + 1] * data1[j] +
|
||||
dataV[i + 2] * data2[j] +
|
||||
dataV[i + 3] * data3[j] +
|
||||
dataV[i + 4] * data4[j] +
|
||||
dataV[i + 5] * data5[j] +
|
||||
dataV[i + 6] * data6[j] +
|
||||
data7[j];
|
||||
data7[j]);
|
||||
EXPECT_COMPARE_EQ(val, resAdd[j]);
|
||||
}
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user