@@ -22,7 +22,17 @@ namespace deglib::distances::fp16_ip {
2222 }
2323
2424 inline static float dot (const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
25- return deglib::distances::fp16::fp16_ip_naive (pVect1v, pVect2v, qty_ptr);
25+ const uint16_t * a = static_cast <const uint16_t *>(pVect1v);
26+ const uint16_t * b = static_cast <const uint16_t *>(pVect2v);
27+ size_t size = *((size_t *)qty_ptr);
28+
29+ float result = 0 .0f ;
30+ for (size_t i = 0 ; i < size; ++i) {
31+ float fa = deglib::distances::fp16::fp16_to_float (a[i]);
32+ float fb = deglib::distances::fp16::fp16_to_float (b[i]);
33+ result = std::fma (fa, fb, result);
34+ }
35+ return result;
2636 }
2737 };
2838
@@ -121,33 +131,33 @@ namespace deglib::distances::fp16_ip {
121131
122132 // -------------------------------------------------------------------
123133 // InnerProductFP16_8Ext — processes 8 FP16 values (16 bytes) per iteration.
124- // Uses SSE F16C (_mm_cvtph_ps) to convert 8 half-precision values to
125- // 8 single-precision floats, then accumulates with _mm256_fmadd_ps
126- // via two SSE loads combined into an AVX2 register.
134+ // Uses AVX2 F16C (_mm256_cvtph_ps) to convert 8 half-precision values
135+ // to 8 single-precision floats, then accumulates with _mm256_fmadd_ps.
127136 // -------------------------------------------------------------------
128137
129- class InnerProductFP16_8Ext_SSE {
138+ class InnerProductFP16_8Ext_AVX2 {
130139 public:
131- DEGLIB_TARGET_F16C inline static float compare (const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
140+ DEGLIB_TARGET_AVX2 inline static float compare (const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
132141 return 1 .f - dot (pVect1v, pVect2v, qty_ptr);
133142 }
134143
135- DEGLIB_TARGET_F16C inline static float dot (const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
144+ DEGLIB_TARGET_AVX2 inline static float dot (const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
136145 const uint16_t *a = static_cast <const uint16_t *>(pVect1v);
137146 const uint16_t *b = static_cast <const uint16_t *>(pVect2v);
138147 size_t size = *((size_t *) qty_ptr);
139148
140149 const uint16_t *last = a + size;
141150
142- __m128 sum128 = _mm_setzero_ps ();
151+ __m256 sum256 = _mm256_setzero_ps ();
143152 while (a < last) {
144- __m128 va = _mm_cvtph_ps (_mm_loadu_si128 (reinterpret_cast <const __m128i *>(a)));
145- __m128 vb = _mm_cvtph_ps (_mm_loadu_si128 (reinterpret_cast <const __m128i *>(b)));
146- sum128 = _mm_fmadd_ps (va, vb, sum128 );
153+ __m256 va = _mm256_cvtph_ps (_mm_loadu_si128 (reinterpret_cast <const __m128i *>(a)));
154+ __m256 vb = _mm256_cvtph_ps (_mm_loadu_si128 (reinterpret_cast <const __m128i *>(b)));
155+ sum256 = _mm256_fmadd_ps (va, vb, sum256 );
147156 a += 8 ;
148157 b += 8 ;
149158 }
150159
160+ __m128 sum128 = _mm_add_ps (_mm256_extractf128_ps (sum256, 0 ), _mm256_extractf128_ps (sum256, 1 ));
151161 alignas (32 ) float f[4 ];
152162 _mm_store_ps (f, sum128);
153163 return f[0 ] + f[1 ] + f[2 ] + f[3 ];
@@ -191,13 +201,13 @@ namespace deglib::distances::fp16_ip {
191201 }
192202 };
193203
194- class InnerProductFP16_8ExtResiduals_SSE {
204+ class InnerProductFP16_8ExtResiduals_AVX2 {
195205 public:
196- DEGLIB_TARGET_F16C inline static float compare (const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
206+ DEGLIB_TARGET_AVX2 inline static float compare (const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
197207 size_t qty = *((size_t *) qty_ptr);
198208
199209 size_t qty8 = qty >> 3 << 3 ;
200- float res = InnerProductFP16_8Ext_SSE ::dot (pVect1v, pVect2v, &qty8);
210+ float res = InnerProductFP16_8Ext_AVX2 ::dot (pVect1v, pVect2v, &qty8);
201211 const uint16_t *pVect1 = static_cast <const uint16_t *>(pVect1v) + qty8;
202212 const uint16_t *pVect2 = static_cast <const uint16_t *>(pVect2v) + qty8;
203213
@@ -213,10 +223,10 @@ namespace deglib::distances::fp16_ip {
213223#if defined(DEGLIB_X86)
214224 , InnerProductFP16_32Ext_AVX512,
215225 InnerProductFP16_16Ext_AVX2,
216- InnerProductFP16_8Ext_SSE ,
226+ InnerProductFP16_8Ext_AVX2 ,
217227 InnerProductFP16_32ExtResiduals_AVX512,
218228 InnerProductFP16_16ExtResiduals_AVX2,
219- InnerProductFP16_8ExtResiduals_SSE
229+ InnerProductFP16_8ExtResiduals_AVX2
220230#endif
221231 >;
222232
@@ -228,27 +238,21 @@ namespace deglib::distances::fp16_ip {
228238 else if (dim % 16 == 0 )
229239 return InnerProductFP16_16Ext_AVX2{};
230240 else if (dim % 8 == 0 )
231- return InnerProductFP16_8Ext_SSE {};
241+ return InnerProductFP16_8Ext_AVX2 {};
232242 else if (dim > 32 )
233243 return InnerProductFP16_32ExtResiduals_AVX512{};
234244 else if (dim > 8 )
235- return InnerProductFP16_8ExtResiduals_SSE {};
245+ return InnerProductFP16_8ExtResiduals_AVX2 {};
236246 }
237247 else if (deglib::cpu::has_avx2 ()) {
238248 if (dim % 16 == 0 )
239249 return InnerProductFP16_16Ext_AVX2{};
240250 else if (dim % 8 == 0 )
241- return InnerProductFP16_8Ext_SSE {};
251+ return InnerProductFP16_8Ext_AVX2 {};
242252 else if (dim > 16 )
243253 return InnerProductFP16_16ExtResiduals_AVX2{};
244254 else if (dim > 8 )
245- return InnerProductFP16_8ExtResiduals_SSE{};
246- }
247- else if (deglib::cpu::has_sse42 ()) {
248- if (dim % 8 == 0 )
249- return InnerProductFP16_8Ext_SSE{};
250- else if (dim > 8 )
251- return InnerProductFP16_8ExtResiduals_SSE{};
255+ return InnerProductFP16_8ExtResiduals_AVX2{};
252256 }
253257#endif
254258 return InnerProductFP16{};
0 commit comments