usearch 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/prerelease.yml +12 -3
- package/Cargo.toml +1 -1
- package/conanfile.py +1 -1
- package/cpp/bench.cpp +1 -0
- package/include/usearch/index.hpp +48 -12
- package/include/usearch/index_dense.hpp +43 -20
- package/include/usearch/index_plugins.hpp +59 -13
- package/package.json +1 -1
- package/python/lib.cpp +133 -61
- package/python/usearch/index.py +112 -79
- package/simsimd/include/simsimd/simsimd.h +106 -40
- package/wasmer.toml +1 -1
|
@@ -45,6 +45,9 @@
|
|
|
45
45
|
#endif
|
|
46
46
|
#endif
|
|
47
47
|
|
|
48
|
+
#undef SIMSIMD_TARGET_X86
|
|
49
|
+
#undef SIMSIMD_TARGET_X86_AVX2
|
|
50
|
+
#undef SIMSIMD_TARGET_X86_AVX512
|
|
48
51
|
#define SIMSIMD_TARGET_X86 0
|
|
49
52
|
#define SIMSIMD_TARGET_X86_AVX2 0
|
|
50
53
|
#define SIMSIMD_TARGET_X86_AVX512 0
|
|
@@ -71,6 +74,9 @@
|
|
|
71
74
|
#endif
|
|
72
75
|
#endif
|
|
73
76
|
|
|
77
|
+
#undef SIMSIMD_TARGET_ARM
|
|
78
|
+
#undef SIMSIMD_TARGET_ARM_NEON
|
|
79
|
+
#undef SIMSIMD_TARGET_ARM_SVE
|
|
74
80
|
#define SIMSIMD_TARGET_ARM 0
|
|
75
81
|
#define SIMSIMD_TARGET_ARM_NEON 0
|
|
76
82
|
#define SIMSIMD_TARGET_ARM_SVE 0
|
|
@@ -143,7 +149,7 @@ simsimd_cos_f32_sve(simsimd_f32_t const* a, simsimd_f32_t const* b, size_t d) {
|
|
|
143
149
|
simsimd_f32_t ab = svaddv_f32(svptrue_b32(), ab_vec);
|
|
144
150
|
simsimd_f32_t a2 = svaddv_f32(svptrue_b32(), a2_vec);
|
|
145
151
|
simsimd_f32_t b2 = svaddv_f32(svptrue_b32(), b2_vec);
|
|
146
|
-
return 1 - ab / (
|
|
152
|
+
return 1 - ab / (sqrtf(a2) * sqrtf(b2));
|
|
147
153
|
}
|
|
148
154
|
|
|
149
155
|
__attribute__((target("+sve"))) inline static simsimd_f32_t //
|
|
@@ -184,7 +190,7 @@ simsimd_cos_f16_sve(simsimd_f16_t const* a_enum, simsimd_f16_t const* b_enum, si
|
|
|
184
190
|
simsimd_f16_t ab = svaddv_f16(svptrue_b16(), ab_vec);
|
|
185
191
|
simsimd_f16_t a2 = svaddv_f16(svptrue_b16(), a2_vec);
|
|
186
192
|
simsimd_f16_t b2 = svaddv_f16(svptrue_b16(), b2_vec);
|
|
187
|
-
return 1 - ab / (
|
|
193
|
+
return 1 - ab / (sqrtf(a2) * sqrtf(b2));
|
|
188
194
|
}
|
|
189
195
|
|
|
190
196
|
__attribute__((target("+sve+fp16"))) inline static simsimd_f32_t //
|
|
@@ -235,6 +241,18 @@ simsimd_dot_f32x4_neon(simsimd_f32_t const* a, simsimd_f32_t const* b, size_t d)
|
|
|
235
241
|
return 1 - vaddvq_f32(ab_vec);
|
|
236
242
|
}
|
|
237
243
|
|
|
244
|
+
__attribute__((target("+simd+fp16"))) inline static simsimd_f32_t //
|
|
245
|
+
simsimd_dot_f16x4_neon(simsimd_f16_t const* a, simsimd_f16_t const* b, size_t d) {
|
|
246
|
+
|
|
247
|
+
float32x4_t ab_vec = vdupq_n_f32(0);
|
|
248
|
+
for (size_t i = 0; i != d; i += 4) {
|
|
249
|
+
float32x4_t a_vec = vcvt_f32_f16(vld1_f16((float16_t const*)a + i));
|
|
250
|
+
float32x4_t b_vec = vcvt_f32_f16(vld1_f16((float16_t const*)b + i));
|
|
251
|
+
ab_vec = vfmaq_f32(ab_vec, a_vec, b_vec);
|
|
252
|
+
}
|
|
253
|
+
return 1 - vaddvq_f32(ab_vec);
|
|
254
|
+
}
|
|
255
|
+
|
|
238
256
|
__attribute__((target("+simd+fp16"))) inline static simsimd_f32_t //
|
|
239
257
|
simsimd_cos_f16x4_neon(simsimd_f16_t const* a, simsimd_f16_t const* b, size_t d) {
|
|
240
258
|
|
|
@@ -252,7 +270,7 @@ simsimd_cos_f16x4_neon(simsimd_f16_t const* a, simsimd_f16_t const* b, size_t d)
|
|
|
252
270
|
simsimd_f32_t ab = vaddvq_f32(ab_vec);
|
|
253
271
|
simsimd_f32_t a2 = vaddvq_f32(a2_vec);
|
|
254
272
|
simsimd_f32_t b2 = vaddvq_f32(b2_vec);
|
|
255
|
-
return 1 - ab / (
|
|
273
|
+
return 1 - ab / (sqrtf(a2) * sqrtf(b2));
|
|
256
274
|
}
|
|
257
275
|
|
|
258
276
|
__attribute__((target("+simd"))) inline static simsimd_f32_t //
|
|
@@ -290,7 +308,7 @@ simsimd_cos_i8x16_neon(int8_t const* a, int8_t const* b, size_t d) {
|
|
|
290
308
|
int32_t a2 = vget_lane_s32(vpadd_s32(a2_part, a2_part), 0);
|
|
291
309
|
int32x2_t b2_part = vadd_s32(vget_high_s32(b2_vec), vget_low_s32(b2_vec));
|
|
292
310
|
int32_t b2 = vget_lane_s32(vpadd_s32(b2_part, b2_part), 0);
|
|
293
|
-
return 1 - ab / (
|
|
311
|
+
return 1 - ab / (sqrtf(a2) * sqrtf(b2));
|
|
294
312
|
}
|
|
295
313
|
|
|
296
314
|
__attribute__((target("+simd"))) inline static simsimd_f32_t //
|
|
@@ -327,7 +345,7 @@ simsimd_cos_f32x4_neon(simsimd_f32_t const* a, simsimd_f32_t const* b, size_t d)
|
|
|
327
345
|
simsimd_f32_t ab = vaddvq_f32(ab_vec);
|
|
328
346
|
simsimd_f32_t a2 = vaddvq_f32(a2_vec);
|
|
329
347
|
simsimd_f32_t b2 = vaddvq_f32(b2_vec);
|
|
330
|
-
return 1 - ab / (
|
|
348
|
+
return 1 - ab / (sqrtf(a2) * sqrtf(b2));
|
|
331
349
|
}
|
|
332
350
|
|
|
333
351
|
__attribute__((target("+sve"))) inline static simsimd_f32_t //
|
|
@@ -385,7 +403,7 @@ simsimd_cos_f32x4_avx2(simsimd_f32_t const* a, simsimd_f32_t const* b, size_t d)
|
|
|
385
403
|
union simsimd_f32i32_t ab_union = {_mm_cvtsi128_si32(_mm_castps_si128(ab_vec))};
|
|
386
404
|
union simsimd_f32i32_t a2_union = {_mm_cvtsi128_si32(_mm_castps_si128(a2_vec))};
|
|
387
405
|
union simsimd_f32i32_t b2_union = {_mm_cvtsi128_si32(_mm_castps_si128(b2_vec))};
|
|
388
|
-
return 1 - ab_union.f / (
|
|
406
|
+
return 1 - ab_union.f / (sqrtf(a2_union.f) * sqrtf(b2_union.f));
|
|
389
407
|
}
|
|
390
408
|
|
|
391
409
|
__attribute__((target("avx2"))) //
|
|
@@ -407,16 +425,17 @@ __attribute__((target("avx2"))) //
|
|
|
407
425
|
__attribute__((target("f16c"))) //
|
|
408
426
|
__attribute__((target("fma"))) inline static simsimd_f32_t //
|
|
409
427
|
simsimd_dot_f16x8_avx2(simsimd_f16_t const* a, simsimd_f16_t const* b, size_t d) {
|
|
410
|
-
|
|
428
|
+
__m256 ab_vec = _mm256_set1_ps(0);
|
|
411
429
|
for (size_t i = 0; i != d; i += 8) {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
ab_vec =
|
|
430
|
+
__m256 a_vec = _mm256_cvtph_ps(_mm_loadu_si128((__m128i const*)(a + i)));
|
|
431
|
+
__m256 b_vec = _mm256_cvtph_ps(_mm_loadu_si128((__m128i const*)(b + i)));
|
|
432
|
+
ab_vec = _mm256_fmadd_ps(a_vec, b_vec, ab_vec);
|
|
415
433
|
}
|
|
416
|
-
ab_vec =
|
|
417
|
-
ab_vec =
|
|
434
|
+
ab_vec = _mm256_add_ps(_mm256_permute2f128_ps(ab_vec, ab_vec, 0x81), ab_vec);
|
|
435
|
+
ab_vec = _mm256_hadd_ps(ab_vec, ab_vec);
|
|
436
|
+
ab_vec = _mm256_hadd_ps(ab_vec, ab_vec);
|
|
418
437
|
float result[1];
|
|
419
|
-
_mm_store_ss(result, ab_vec);
|
|
438
|
+
_mm_store_ss(result, _mm256_castps256_ps128(ab_vec));
|
|
420
439
|
return 1 - result[0];
|
|
421
440
|
}
|
|
422
441
|
|
|
@@ -424,47 +443,94 @@ __attribute__((target("avx2"))) //
|
|
|
424
443
|
__attribute__((target("f16c"))) //
|
|
425
444
|
__attribute__((target("fma"))) inline static simsimd_f32_t //
|
|
426
445
|
simsimd_cos_f16x8_avx2(simsimd_f16_t const* a, simsimd_f16_t const* b, size_t d) {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
446
|
+
__m256 ab_vec = _mm256_set1_ps(0);
|
|
447
|
+
__m256 a2_vec = _mm256_set1_ps(0);
|
|
448
|
+
__m256 b2_vec = _mm256_set1_ps(0);
|
|
430
449
|
for (size_t i = 0; i != d; i += 8) {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
ab_vec =
|
|
434
|
-
a2_vec =
|
|
435
|
-
b2_vec =
|
|
450
|
+
__m256 a_vec = _mm256_cvtph_ps(_mm_loadu_si128((__m128i const*)(a + i)));
|
|
451
|
+
__m256 b_vec = _mm256_cvtph_ps(_mm_loadu_si128((__m128i const*)(b + i)));
|
|
452
|
+
ab_vec = _mm256_fmadd_ps(a_vec, b_vec, ab_vec);
|
|
453
|
+
a2_vec = _mm256_fmadd_ps(a_vec, a_vec, a2_vec);
|
|
454
|
+
b2_vec = _mm256_fmadd_ps(b_vec, b_vec, b2_vec);
|
|
436
455
|
}
|
|
437
|
-
ab_vec =
|
|
438
|
-
ab_vec =
|
|
439
|
-
|
|
440
|
-
a2_vec =
|
|
441
|
-
|
|
442
|
-
|
|
456
|
+
ab_vec = _mm256_add_ps(_mm256_permute2f128_ps(ab_vec, ab_vec, 0x81), ab_vec);
|
|
457
|
+
ab_vec = _mm256_hadd_ps(ab_vec, ab_vec);
|
|
458
|
+
ab_vec = _mm256_hadd_ps(ab_vec, ab_vec);
|
|
459
|
+
a2_vec = _mm256_add_ps(_mm256_permute2f128_ps(a2_vec, a2_vec, 0x81), a2_vec);
|
|
460
|
+
a2_vec = _mm256_hadd_ps(a2_vec, a2_vec);
|
|
461
|
+
a2_vec = _mm256_hadd_ps(a2_vec, a2_vec);
|
|
462
|
+
b2_vec = _mm256_add_ps(_mm256_permute2f128_ps(b2_vec, b2_vec, 0x81), b2_vec);
|
|
463
|
+
b2_vec = _mm256_hadd_ps(b2_vec, b2_vec);
|
|
464
|
+
b2_vec = _mm256_hadd_ps(b2_vec, b2_vec);
|
|
443
465
|
float ab_result[1], a2_result[1], b2_result[1];
|
|
444
|
-
_mm_store_ss(ab_result, ab_vec);
|
|
445
|
-
_mm_store_ss(a2_result, a2_vec);
|
|
446
|
-
_mm_store_ss(b2_result, b2_vec);
|
|
447
|
-
return 1 - ab_result[0] / (
|
|
466
|
+
_mm_store_ss(ab_result, _mm256_castps256_ps128(ab_vec));
|
|
467
|
+
_mm_store_ss(a2_result, _mm256_castps256_ps128(a2_vec));
|
|
468
|
+
_mm_store_ss(b2_result, _mm256_castps256_ps128(b2_vec));
|
|
469
|
+
return 1 - ab_result[0] / (sqrtf(a2_result[0]) * sqrtf(b2_result[0]));
|
|
448
470
|
}
|
|
449
471
|
|
|
450
472
|
__attribute__((target("avx2"))) //
|
|
451
473
|
__attribute__((target("f16c"))) //
|
|
452
474
|
__attribute__((target("fma"))) inline static simsimd_f32_t //
|
|
453
475
|
simsimd_l2sq_f16x8_avx2(simsimd_f16_t const* a, simsimd_f16_t const* b, size_t d) {
|
|
454
|
-
|
|
476
|
+
__m256 sum_vec = _mm256_set1_ps(0);
|
|
455
477
|
for (size_t i = 0; i != d; i += 8) {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
sum_vec =
|
|
478
|
+
__m256 a_vec = _mm256_cvtph_ps(_mm_loadu_si128((__m128i const*)(a + i)));
|
|
479
|
+
__m256 b_vec = _mm256_cvtph_ps(_mm_loadu_si128((__m128i const*)(b + i)));
|
|
480
|
+
__m256 diff_vec = _mm256_sub_ps(a_vec, b_vec);
|
|
481
|
+
sum_vec = _mm256_fmadd_ps(diff_vec, diff_vec, sum_vec);
|
|
460
482
|
}
|
|
461
|
-
sum_vec =
|
|
462
|
-
sum_vec =
|
|
483
|
+
sum_vec = _mm256_add_ps(_mm256_permute2f128_ps(sum_vec, sum_vec, 0x81), sum_vec);
|
|
484
|
+
sum_vec = _mm256_hadd_ps(sum_vec, sum_vec);
|
|
485
|
+
sum_vec = _mm256_hadd_ps(sum_vec, sum_vec);
|
|
463
486
|
float result[1];
|
|
464
|
-
_mm_store_ss(result, sum_vec);
|
|
487
|
+
_mm_store_ss(result, _mm256_castps256_ps128(sum_vec));
|
|
465
488
|
return result[0];
|
|
466
489
|
}
|
|
467
490
|
|
|
491
|
+
__attribute__((target("avx2"))) //
|
|
492
|
+
inline static simsimd_f32_t
|
|
493
|
+
simsimd_cos_i8x32_avx2(int8_t const* a, int8_t const* b, size_t d) {
|
|
494
|
+
|
|
495
|
+
__m256i ab_vec = _mm256_setzero_si256();
|
|
496
|
+
__m256i a2_vec = _mm256_setzero_si256();
|
|
497
|
+
__m256i b2_vec = _mm256_setzero_si256();
|
|
498
|
+
|
|
499
|
+
for (size_t i = 0; i != d; i += 32) {
|
|
500
|
+
__m256i a_vec = _mm256_loadu_si256((__m256i const*)(a + i));
|
|
501
|
+
__m256i b_vec = _mm256_loadu_si256((__m256i const*)(b + i));
|
|
502
|
+
|
|
503
|
+
// Multiply and add packed 8-bit integers
|
|
504
|
+
__m256i ab_part_vec = _mm256_maddubs_epi16(a_vec, b_vec);
|
|
505
|
+
__m256i a2_part_vec = _mm256_maddubs_epi16(a_vec, a_vec);
|
|
506
|
+
__m256i b2_part_vec = _mm256_maddubs_epi16(b_vec, b_vec);
|
|
507
|
+
|
|
508
|
+
ab_vec = _mm256_add_epi32(ab_vec, ab_part_vec);
|
|
509
|
+
a2_vec = _mm256_add_epi32(a2_vec, a2_part_vec);
|
|
510
|
+
b2_vec = _mm256_add_epi32(b2_vec, b2_part_vec);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Horizontal sum across the 256-bit register
|
|
514
|
+
__m128i ab_low = _mm256_extracti128_si256(ab_vec, 0);
|
|
515
|
+
__m128i ab_high = _mm256_extracti128_si256(ab_vec, 1);
|
|
516
|
+
__m128i ab_sum = _mm_add_epi32(ab_low, ab_high);
|
|
517
|
+
|
|
518
|
+
__m128i a2_low = _mm256_extracti128_si256(a2_vec, 0);
|
|
519
|
+
__m128i a2_high = _mm256_extracti128_si256(a2_vec, 1);
|
|
520
|
+
__m128i a2_sum = _mm_add_epi32(a2_low, a2_high);
|
|
521
|
+
|
|
522
|
+
__m128i b2_low = _mm256_extracti128_si256(b2_vec, 0);
|
|
523
|
+
__m128i b2_high = _mm256_extracti128_si256(b2_vec, 1);
|
|
524
|
+
__m128i b2_sum = _mm_add_epi32(b2_low, b2_high);
|
|
525
|
+
|
|
526
|
+
// Further reduce to a single sum for each vector
|
|
527
|
+
int ab = _mm_extract_epi32(_mm_hadd_epi32(_mm_hadd_epi32(ab_sum, ab_sum), ab_sum), 0);
|
|
528
|
+
int a2 = _mm_extract_epi32(_mm_hadd_epi32(_mm_hadd_epi32(a2_sum, a2_sum), a2_sum), 0);
|
|
529
|
+
int b2 = _mm_extract_epi32(_mm_hadd_epi32(_mm_hadd_epi32(b2_sum, b2_sum), b2_sum), 0);
|
|
530
|
+
|
|
531
|
+
return 1 - ab / (sqrtf(a2) * sqrtf(b2));
|
|
532
|
+
}
|
|
533
|
+
|
|
468
534
|
#endif // SIMSIMD_TARGET_X86_AVX2
|
|
469
535
|
|
|
470
536
|
#if SIMSIMD_TARGET_X86_AVX512
|
|
@@ -498,7 +564,7 @@ simsimd_cos_f16x16_avx512(simsimd_f16_t const* a, simsimd_f16_t const* b, size_t
|
|
|
498
564
|
simsimd_f32_t ab = _mm512_reduce_add_ps(ab_vec);
|
|
499
565
|
simsimd_f32_t a2 = _mm512_reduce_add_ps(a2_vec);
|
|
500
566
|
simsimd_f32_t b2 = _mm512_reduce_add_ps(b2_vec);
|
|
501
|
-
return 1 - ab / (
|
|
567
|
+
return 1 - ab / (sqrtf(a2) * sqrtf(b2));
|
|
502
568
|
}
|
|
503
569
|
|
|
504
570
|
__attribute__((target("avx512fp16"))) //
|