Skip to content

Commit 9ba4fca

Browse files
committed
fix(ci): add missing SIMD target attributes and fix benchmark test timing
1 parent 16980e4 commit 9ba4fca

4 files changed

Lines changed: 33 additions & 19 deletions

File tree

cpp/deglib/include/config.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,18 @@
1414
#define DEGLIB_TARGET_AVX512
1515
#endif
1616

17-
// Compile methods with this attribute for F16C functions on GCC/Clang
17+
// Compile methods with this attribute for AVX2 F16C functions on GCC/Clang.
18+
// Covers AVX2, F16C, and FMA intrinsics used in fp16_ip.h and fp32_ip.h.
1819
#if defined(DEGLIB_X86) && (defined(__GNUC__) || defined(__clang__))
19-
#define DEGLIB_TARGET_F16C __attribute__((target("f16c,avx")))
20+
#define DEGLIB_TARGET_AVX2 __attribute__((target("avx2,f16c,fma")))
21+
#else
22+
#define DEGLIB_TARGET_AVX2
23+
#endif
24+
25+
// Compile methods with this attribute for F16C functions on GCC/Clang.
26+
// Includes FMA for _mm_fmadd_ps / _mm256_fmadd_ps used in SSE/AVX2 paths.
27+
#if defined(DEGLIB_X86) && (defined(__GNUC__) || defined(__clang__))
28+
#define DEGLIB_TARGET_F16C __attribute__((target("f16c,avx,fma")))
2029
#else
2130
#define DEGLIB_TARGET_F16C
2231
#endif

cpp/deglib/include/distance/fp16_ip.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,11 @@ namespace deglib::distances::fp16_ip {
8383

8484
class InnerProductFP16_16Ext_AVX2 {
8585
public:
86-
inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
86+
DEGLIB_TARGET_AVX2 inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
8787
return 1.f - dot(pVect1v, pVect2v, qty_ptr);
8888
}
8989

90-
inline static float dot(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
90+
DEGLIB_TARGET_AVX2 inline static float dot(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
9191
const uint16_t *a = static_cast<const uint16_t *>(pVect1v);
9292
const uint16_t *b = static_cast<const uint16_t *>(pVect2v);
9393
size_t size = *((size_t *) qty_ptr);
@@ -128,11 +128,11 @@ namespace deglib::distances::fp16_ip {
128128

129129
class InnerProductFP16_8Ext_SSE {
130130
public:
131-
inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
131+
DEGLIB_TARGET_F16C inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
132132
return 1.f - dot(pVect1v, pVect2v, qty_ptr);
133133
}
134134

135-
inline static float dot(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
135+
DEGLIB_TARGET_F16C inline static float dot(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
136136
const uint16_t *a = static_cast<const uint16_t *>(pVect1v);
137137
const uint16_t *b = static_cast<const uint16_t *>(pVect2v);
138138
size_t size = *((size_t *) qty_ptr);
@@ -177,7 +177,7 @@ namespace deglib::distances::fp16_ip {
177177

178178
class InnerProductFP16_16ExtResiduals_AVX2 {
179179
public:
180-
inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
180+
DEGLIB_TARGET_AVX2 inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
181181
size_t qty = *((size_t *) qty_ptr);
182182

183183
size_t qty16 = qty >> 4 << 4;
@@ -193,7 +193,7 @@ namespace deglib::distances::fp16_ip {
193193

194194
class InnerProductFP16_8ExtResiduals_SSE {
195195
public:
196-
inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
196+
DEGLIB_TARGET_F16C inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
197197
size_t qty = *((size_t *) qty_ptr);
198198

199199
size_t qty8 = qty >> 3 << 3;

cpp/deglib/include/distance/fp32_ip.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,15 @@ namespace deglib::distances::fp32_ip {
8888

8989
class InnerProductFloat16Ext_AVX2 {
9090
public:
91-
inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
91+
DEGLIB_TARGET_AVX2 inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
9292
return 1.f - dot(pVect1v, pVect2v, qty_ptr);
9393
}
9494

95-
inline static float dot(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
95+
DEGLIB_TARGET_AVX2 inline static float dot(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
9696
return ip_16ext(pVect1v, pVect2v, qty_ptr);
9797
}
9898

99-
inline static float ip_16ext(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
99+
DEGLIB_TARGET_AVX2 inline static float ip_16ext(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
100100
float *a = (float *) pVect1v;
101101
float *b = (float *) pVect2v;
102102
size_t size = *((size_t *) qty_ptr);
@@ -165,15 +165,15 @@ namespace deglib::distances::fp32_ip {
165165

166166
class InnerProductFloat8Ext_AVX2 {
167167
public:
168-
inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
168+
DEGLIB_TARGET_AVX2 inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
169169
return 1.f - dot(pVect1v, pVect2v, qty_ptr);
170170
}
171171

172-
inline static float dot(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
172+
DEGLIB_TARGET_AVX2 inline static float dot(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
173173
return ip_8ext(pVect1v, pVect2v, qty_ptr);
174174
}
175175

176-
inline static float ip_8ext(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
176+
DEGLIB_TARGET_AVX2 inline static float ip_8ext(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
177177
float *a = (float *) pVect1v;
178178
float *b = (float *) pVect2v;
179179
size_t size = *((size_t *) qty_ptr);
@@ -282,7 +282,7 @@ namespace deglib::distances::fp32_ip {
282282

283283
class InnerProductFloat16ExtResiduals_AVX2 {
284284
public:
285-
inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
285+
DEGLIB_TARGET_AVX2 inline static float compare(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
286286
size_t qty = *((size_t *) qty_ptr);
287287

288288
size_t qty16 = qty >> 4 << 4;

cpp/test/src/unit/test_fp16_conversions.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ TEST(FP16ConversionTest, CurrentVsHardwarePrecision) {
456456
// Prints time per 1M conversions in milliseconds.
457457
TEST(FP16ConversionTest, BenchmarkConversionSpeed) {
458458
const size_t count = 1000000;
459-
const int iterations = 10;
459+
const int iterations = 500;
460460

461461
std::vector<float> floats(count);
462462
std::vector<uint16_t> result(count);
@@ -497,7 +497,12 @@ TEST(FP16ConversionTest, BenchmarkConversionSpeed) {
497497
<< (current_ms / simd_ms) << "x" << std::endl;
498498
}
499499

500-
// Basic sanity: SIMD should not be slower than scalar
501-
EXPECT_LT(simd_ms, current_ms * 2.0)
502-
<< "SIMD path should not be significantly slower than scalar";
500+
// SIMD should be faster than scalar when F16C is available.
501+
// If F16C is not available, floats_to_fp16 falls back to scalar and
502+
// the timings would be equal — but in that case this benchmark is not
503+
// meaningful, so we only assert when F16C is present.
504+
if (deglib::cpu::has_f16c()) {
505+
EXPECT_LT(simd_ms, current_ms)
506+
<< "SIMD path should be faster than scalar when F16C is available";
507+
}
503508
}

0 commit comments

Comments
 (0)