usearch 2.14.0 → 2.15.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/README.md +1 -1
- package/cpp/bench.cpp +4 -0
- package/include/usearch/index.hpp +1 -1
- package/include/usearch/index_dense.hpp +1 -1
- package/include/usearch/index_plugins.hpp +33 -40
- package/package.json +1 -1
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
package/README.md
CHANGED
package/cpp/bench.cpp
CHANGED
|
@@ -468,6 +468,7 @@ struct args_t {
|
|
|
468
468
|
|
|
469
469
|
bool big = false;
|
|
470
470
|
|
|
471
|
+
bool quantize_bf16 = false;
|
|
471
472
|
bool quantize_f16 = false;
|
|
472
473
|
bool quantize_i8 = false;
|
|
473
474
|
bool quantize_b1 = false;
|
|
@@ -500,6 +501,8 @@ struct args_t {
|
|
|
500
501
|
}
|
|
501
502
|
|
|
502
503
|
scalar_kind_t quantization() const noexcept {
|
|
504
|
+
if (quantize_bf16)
|
|
505
|
+
return scalar_kind_t::bf16_k;
|
|
503
506
|
if (quantize_f16)
|
|
504
507
|
return scalar_kind_t::f16_k;
|
|
505
508
|
if (quantize_i8)
|
|
@@ -611,6 +614,7 @@ int main(int argc, char** argv) {
|
|
|
611
614
|
(option("--rows-skip") & value("integer", args.vectors_to_skip)).doc("Number of vectors to skip"),
|
|
612
615
|
(option("--rows-take") & value("integer", args.vectors_to_take)).doc("Number of vectors to take"),
|
|
613
616
|
( //
|
|
617
|
+
option("-bf16", "--bf16quant").set(args.quantize_bf16).doc("Enable `bf16_t` quantization") |
|
|
614
618
|
option("-f16", "--f16quant").set(args.quantize_f16).doc("Enable `f16_t` quantization") |
|
|
615
619
|
option("-i8", "--i8quant").set(args.quantize_i8).doc("Enable `i8_t` quantization") |
|
|
616
620
|
option("-b1", "--b1quant").set(args.quantize_b1).doc("Enable `b1x8_t` quantization")),
|
|
@@ -72,25 +72,8 @@ struct uuid_t {
|
|
|
72
72
|
class f16_bits_t;
|
|
73
73
|
class bf16_bits_t;
|
|
74
74
|
|
|
75
|
-
#if !USEARCH_USE_FP16LIB
|
|
76
|
-
#if USEARCH_USE_SIMSIMD
|
|
77
|
-
using f16_native_t = simsimd_f16_t;
|
|
78
|
-
using bf16_native_t = simsimd_bf16_t;
|
|
79
|
-
#elif defined(USEARCH_DEFINED_ARM)
|
|
80
|
-
using f16_native_t = __fp16;
|
|
81
|
-
using bf16_native_t = __fp16; // No better choice on most compilers!
|
|
82
|
-
#else
|
|
83
|
-
using f16_native_t = _Float16;
|
|
84
|
-
using bf16_native_t = _Float16; // No better choice on most compilers!
|
|
85
|
-
#endif
|
|
86
|
-
using f16_t = f16_native_t;
|
|
87
|
-
using bf16_t = bf16_native_t;
|
|
88
|
-
#else
|
|
89
|
-
using f16_native_t = void;
|
|
90
|
-
using bf16_native_t = void;
|
|
91
75
|
using f16_t = f16_bits_t;
|
|
92
76
|
using bf16_t = bf16_bits_t;
|
|
93
|
-
#endif
|
|
94
77
|
|
|
95
78
|
using f64_t = double;
|
|
96
79
|
using f32_t = float;
|
|
@@ -156,12 +139,6 @@ enum class scalar_kind_t : std::uint8_t {
|
|
|
156
139
|
i8_k = 23,
|
|
157
140
|
};
|
|
158
141
|
|
|
159
|
-
enum class prefetching_kind_t {
|
|
160
|
-
none_k,
|
|
161
|
-
cpu_k,
|
|
162
|
-
io_uring_k,
|
|
163
|
-
};
|
|
164
|
-
|
|
165
142
|
template <typename scalar_at> scalar_kind_t scalar_kind() noexcept {
|
|
166
143
|
if (std::is_same<scalar_at, b1x8_t>())
|
|
167
144
|
return scalar_kind_t::b1x8_k;
|
|
@@ -352,12 +329,14 @@ inline expected_gt<metric_kind_t> metric_from_name(char const* name) {
|
|
|
352
329
|
* @brief Convenience function to upcast a half-precision floating point number to a single-precision one.
|
|
353
330
|
*/
|
|
354
331
|
inline float f16_to_f32(std::uint16_t u16) noexcept {
|
|
355
|
-
#if
|
|
332
|
+
#if USEARCH_USE_FP16LIB
|
|
333
|
+
return fp16_ieee_to_fp32_value(u16);
|
|
334
|
+
#elif USEARCH_USE_SIMSIMD
|
|
335
|
+
return simsimd_uncompress_f16(u16);
|
|
336
|
+
#else
|
|
356
337
|
f16_native_t f16;
|
|
357
338
|
std::memcpy(&f16, &u16, sizeof(std::uint16_t));
|
|
358
339
|
return float(f16);
|
|
359
|
-
#else
|
|
360
|
-
return fp16_ieee_to_fp32_value(u16);
|
|
361
340
|
#endif
|
|
362
341
|
}
|
|
363
342
|
|
|
@@ -365,13 +344,15 @@ inline float f16_to_f32(std::uint16_t u16) noexcept {
|
|
|
365
344
|
* @brief Convenience function to downcast a single-precision floating point number to a half-precision one.
|
|
366
345
|
*/
|
|
367
346
|
inline std::uint16_t f32_to_f16(float f32) noexcept {
|
|
368
|
-
#if
|
|
347
|
+
#if USEARCH_USE_FP16LIB
|
|
348
|
+
return fp16_ieee_from_fp32_value(f32);
|
|
349
|
+
#elif USEARCH_USE_SIMSIMD
|
|
350
|
+
return simsimd_compress_f16(f32);
|
|
351
|
+
#else
|
|
369
352
|
f16_native_t f16 = f16_native_t(f32);
|
|
370
353
|
std::uint16_t u16;
|
|
371
354
|
std::memcpy(&u16, &f16, sizeof(std::uint16_t));
|
|
372
355
|
return u16;
|
|
373
|
-
#else
|
|
374
|
-
return fp16_ieee_from_fp32_value(f32);
|
|
375
356
|
#endif
|
|
376
357
|
}
|
|
377
358
|
|
|
@@ -380,6 +361,9 @@ inline std::uint16_t f32_to_f16(float f32) noexcept {
|
|
|
380
361
|
* https://github.com/ashvardanian/SimSIMD/blob/ff51434d90c66f916e94ff05b24530b127aa4cff/include/simsimd/types.h#L395-L410
|
|
381
362
|
*/
|
|
382
363
|
inline float bf16_to_f32(std::uint16_t u16) noexcept {
|
|
364
|
+
#if USEARCH_USE_SIMSIMD
|
|
365
|
+
return simsimd_uncompress_bf16(u16);
|
|
366
|
+
#else
|
|
383
367
|
union float_or_unsigned_int_t {
|
|
384
368
|
float f;
|
|
385
369
|
unsigned int i;
|
|
@@ -387,6 +371,7 @@ inline float bf16_to_f32(std::uint16_t u16) noexcept {
|
|
|
387
371
|
union float_or_unsigned_int_t result_union;
|
|
388
372
|
result_union.i = u16 << 16; // Zero extends the mantissa
|
|
389
373
|
return result_union.f;
|
|
374
|
+
#endif
|
|
390
375
|
}
|
|
391
376
|
|
|
392
377
|
/**
|
|
@@ -394,6 +379,9 @@ inline float bf16_to_f32(std::uint16_t u16) noexcept {
|
|
|
394
379
|
* https://github.com/ashvardanian/SimSIMD/blob/ff51434d90c66f916e94ff05b24530b127aa4cff/include/simsimd/types.h#L412-L425
|
|
395
380
|
*/
|
|
396
381
|
inline std::uint16_t f32_to_bf16(float f32) noexcept {
|
|
382
|
+
#if USEARCH_USE_SIMSIMD
|
|
383
|
+
return simsimd_compress_bf16(f32);
|
|
384
|
+
#else
|
|
397
385
|
union float_or_unsigned_int_t {
|
|
398
386
|
float f;
|
|
399
387
|
unsigned int i;
|
|
@@ -403,6 +391,7 @@ inline std::uint16_t f32_to_bf16(float f32) noexcept {
|
|
|
403
391
|
value.i >>= 16;
|
|
404
392
|
value.i &= 0xFFFF;
|
|
405
393
|
return (unsigned short)value.i;
|
|
394
|
+
#endif
|
|
406
395
|
}
|
|
407
396
|
|
|
408
397
|
/**
|
|
@@ -1047,6 +1036,10 @@ template <> struct cast_gt<f16_bits_t, f16_bits_t> {
|
|
|
1047
1036
|
static bool try_(byte_t const*, std::size_t, byte_t*) noexcept { return false; }
|
|
1048
1037
|
};
|
|
1049
1038
|
|
|
1039
|
+
template <> struct cast_gt<bf16_bits_t, bf16_bits_t> {
|
|
1040
|
+
static bool try_(byte_t const*, std::size_t, byte_t*) noexcept { return false; }
|
|
1041
|
+
};
|
|
1042
|
+
|
|
1050
1043
|
template <> struct cast_gt<i8_t, i8_t> {
|
|
1051
1044
|
static bool try_(byte_t const*, std::size_t, byte_t*) noexcept { return false; }
|
|
1052
1045
|
};
|
|
@@ -1119,23 +1112,23 @@ template <typename to_scalar_at> struct cast_from_i8_gt {
|
|
|
1119
1112
|
}
|
|
1120
1113
|
};
|
|
1121
1114
|
|
|
1122
|
-
template <> struct cast_gt<i8_t,
|
|
1123
|
-
template <> struct cast_gt<i8_t,
|
|
1115
|
+
template <> struct cast_gt<i8_t, f16_bits_t> : public cast_from_i8_gt<f16_t> {};
|
|
1116
|
+
template <> struct cast_gt<i8_t, bf16_bits_t> : public cast_from_i8_gt<bf16_t> {};
|
|
1124
1117
|
template <> struct cast_gt<i8_t, f32_t> : public cast_from_i8_gt<f32_t> {};
|
|
1125
1118
|
template <> struct cast_gt<i8_t, f64_t> : public cast_from_i8_gt<f64_t> {};
|
|
1126
1119
|
|
|
1127
|
-
template <> struct cast_gt<
|
|
1128
|
-
template <> struct cast_gt<
|
|
1120
|
+
template <> struct cast_gt<f16_bits_t, i8_t> : public cast_to_i8_gt<f16_t> {};
|
|
1121
|
+
template <> struct cast_gt<bf16_bits_t, i8_t> : public cast_to_i8_gt<bf16_t> {};
|
|
1129
1122
|
template <> struct cast_gt<f32_t, i8_t> : public cast_to_i8_gt<f32_t> {};
|
|
1130
1123
|
template <> struct cast_gt<f64_t, i8_t> : public cast_to_i8_gt<f64_t> {};
|
|
1131
1124
|
|
|
1132
|
-
template <> struct cast_gt<b1x8_t,
|
|
1133
|
-
template <> struct cast_gt<b1x8_t,
|
|
1125
|
+
template <> struct cast_gt<b1x8_t, f16_bits_t> : public cast_from_b1x8_gt<f16_t> {};
|
|
1126
|
+
template <> struct cast_gt<b1x8_t, bf16_bits_t> : public cast_from_b1x8_gt<bf16_t> {};
|
|
1134
1127
|
template <> struct cast_gt<b1x8_t, f32_t> : public cast_from_b1x8_gt<f32_t> {};
|
|
1135
1128
|
template <> struct cast_gt<b1x8_t, f64_t> : public cast_from_b1x8_gt<f64_t> {};
|
|
1136
1129
|
|
|
1137
|
-
template <> struct cast_gt<
|
|
1138
|
-
template <> struct cast_gt<
|
|
1130
|
+
template <> struct cast_gt<f16_bits_t, b1x8_t> : public cast_to_b1x8_gt<f16_t> {};
|
|
1131
|
+
template <> struct cast_gt<bf16_bits_t, b1x8_t> : public cast_to_b1x8_gt<bf16_t> {};
|
|
1139
1132
|
template <> struct cast_gt<f32_t, b1x8_t> : public cast_to_b1x8_gt<f32_t> {};
|
|
1140
1133
|
template <> struct cast_gt<f64_t, b1x8_t> : public cast_to_b1x8_gt<f64_t> {};
|
|
1141
1134
|
|
|
@@ -2088,7 +2081,7 @@ class flat_hash_multi_set_gt {
|
|
|
2088
2081
|
// Allocate new memory
|
|
2089
2082
|
data_ = (char*)allocator_t{}.allocate(other.buckets_ * bytes_per_bucket());
|
|
2090
2083
|
if (!data_)
|
|
2091
|
-
|
|
2084
|
+
__usearch_raise_runtime_error("failed memory allocation");
|
|
2092
2085
|
|
|
2093
2086
|
// Copy metadata
|
|
2094
2087
|
buckets_ = other.buckets_;
|
|
@@ -2128,7 +2121,7 @@ class flat_hash_multi_set_gt {
|
|
|
2128
2121
|
// Allocate new memory
|
|
2129
2122
|
data_ = (char*)allocator_t{}.allocate(other.buckets_ * bytes_per_bucket());
|
|
2130
2123
|
if (!data_)
|
|
2131
|
-
|
|
2124
|
+
__usearch_raise_runtime_error("failed memory allocation");
|
|
2132
2125
|
|
|
2133
2126
|
// Copy metadata
|
|
2134
2127
|
buckets_ = other.buckets_;
|
|
@@ -2501,7 +2494,7 @@ class flat_hash_multi_set_gt {
|
|
|
2501
2494
|
|
|
2502
2495
|
void reserve(std::size_t capacity) {
|
|
2503
2496
|
if (!try_reserve(capacity))
|
|
2504
|
-
|
|
2497
|
+
__usearch_raise_runtime_error("failed to reserve memory");
|
|
2505
2498
|
}
|
|
2506
2499
|
|
|
2507
2500
|
bool try_emplace(element_t const& element) noexcept {
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|