1
0
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:
HAN Liutong
2024-07-07 16:38:02 +08:00
committed by GitHub
parent 6a11847d57
commit 1d9ca7160b
4 changed files with 115 additions and 107 deletions
+27 -25
View File
@@ -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