44#include < random>
55#include < vector>
66#include " ../include/sqlite-vec-cpp/distances/cosine.hpp"
7+ #include " ../include/sqlite-vec-cpp/distances/hamming.hpp"
8+ #include " ../include/sqlite-vec-cpp/distances/inner_product.hpp"
79#include " ../include/sqlite-vec-cpp/distances/l1.hpp"
810#include " ../include/sqlite-vec-cpp/distances/l2.hpp"
911#include < benchmark/benchmark.h>
@@ -38,7 +40,7 @@ static void BM_L2_Float_128(benchmark::State& state) {
3840
3941 for (auto _ : state) {
4042 float result =
41- distance_l2_sqeuclidean (std::span<const float >(a), std::span<const float >(b));
43+ l2_distance (std::span<const float >(a), std::span<const float >(b));
4244 benchmark::DoNotOptimize (result);
4345 }
4446 state.SetItemsProcessed (state.iterations () * 128 );
@@ -51,7 +53,7 @@ static void BM_L2_Float_256(benchmark::State& state) {
5153
5254 for (auto _ : state) {
5355 float result =
54- distance_l2_sqeuclidean (std::span<const float >(a), std::span<const float >(b));
56+ l2_distance (std::span<const float >(a), std::span<const float >(b));
5557 benchmark::DoNotOptimize (result);
5658 }
5759 state.SetItemsProcessed (state.iterations () * 256 );
@@ -64,7 +66,7 @@ static void BM_L2_Float_512(benchmark::State& state) {
6466
6567 for (auto _ : state) {
6668 float result =
67- distance_l2_sqeuclidean (std::span<const float >(a), std::span<const float >(b));
69+ l2_distance (std::span<const float >(a), std::span<const float >(b));
6870 benchmark::DoNotOptimize (result);
6971 }
7072 state.SetItemsProcessed (state.iterations () * 512 );
@@ -77,7 +79,7 @@ static void BM_L2_Float_1536(benchmark::State& state) {
7779
7880 for (auto _ : state) {
7981 float result =
80- distance_l2_sqeuclidean (std::span<const float >(a), std::span<const float >(b));
82+ l2_distance (std::span<const float >(a), std::span<const float >(b));
8183 benchmark::DoNotOptimize (result);
8284 }
8385 state.SetItemsProcessed (state.iterations () * 1536 );
@@ -90,7 +92,7 @@ static void BM_L2_Int8_128(benchmark::State& state) {
9092
9193 for (auto _ : state) {
9294 float result =
93- distance_l2_sqeuclidean (std::span<const int8_t >(a), std::span<const int8_t >(b));
95+ l2_distance (std::span<const int8_t >(a), std::span<const int8_t >(b));
9496 benchmark::DoNotOptimize (result);
9597 }
9698 state.SetItemsProcessed (state.iterations () * 128 );
@@ -106,7 +108,7 @@ static void BM_L1_Float_128(benchmark::State& state) {
106108 auto b = generate_random_vector<float >(128 );
107109
108110 for (auto _ : state) {
109- float result = distance_l1 (std::span<const float >(a), std::span<const float >(b));
111+ auto result = l1_distance (std::span<const float >(a), std::span<const float >(b));
110112 benchmark::DoNotOptimize (result);
111113 }
112114 state.SetItemsProcessed (state.iterations () * 128 );
@@ -118,7 +120,7 @@ static void BM_L1_Float_1536(benchmark::State& state) {
118120 auto b = generate_random_vector<float >(1536 );
119121
120122 for (auto _ : state) {
121- float result = distance_l1 (std::span<const float >(a), std::span<const float >(b));
123+ auto result = l1_distance (std::span<const float >(a), std::span<const float >(b));
122124 benchmark::DoNotOptimize (result);
123125 }
124126 state.SetItemsProcessed (state.iterations () * 1536 );
@@ -134,7 +136,7 @@ static void BM_Cosine_Float_128(benchmark::State& state) {
134136 auto b = generate_random_vector<float >(128 );
135137
136138 for (auto _ : state) {
137- float result = distance_cosine (std::span<const float >(a), std::span<const float >(b));
139+ float result = cosine_distance (std::span<const float >(a), std::span<const float >(b));
138140 benchmark::DoNotOptimize (result);
139141 }
140142 state.SetItemsProcessed (state.iterations () * 128 );
@@ -146,7 +148,7 @@ static void BM_Cosine_Float_1536(benchmark::State& state) {
146148 auto b = generate_random_vector<float >(1536 );
147149
148150 for (auto _ : state) {
149- float result = distance_cosine (std::span<const float >(a), std::span<const float >(b));
151+ float result = cosine_distance (std::span<const float >(a), std::span<const float >(b));
150152 benchmark::DoNotOptimize (result);
151153 }
152154 state.SetItemsProcessed (state.iterations () * 1536 );
@@ -162,8 +164,8 @@ static void BM_Hamming_128(benchmark::State& state) {
162164 auto b = generate_random_vector<unsigned char >(128 , (unsigned char )0 , (unsigned char )255 );
163165
164166 for (auto _ : state) {
165- int result =
166- distance_hamming (std::span<const unsigned char >(a), std::span<const unsigned char >(b));
167+ float result =
168+ hamming_distance_u8 (std::span<const unsigned char >(a), std::span<const unsigned char >(b));
167169 benchmark::DoNotOptimize (result);
168170 }
169171 state.SetItemsProcessed (state.iterations () * 128 );
@@ -175,8 +177,8 @@ static void BM_Hamming_1536(benchmark::State& state) {
175177 auto b = generate_random_vector<unsigned char >(1536 , (unsigned char )0 , (unsigned char )255 );
176178
177179 for (auto _ : state) {
178- int result =
179- distance_hamming (std::span<const unsigned char >(a), std::span<const unsigned char >(b));
180+ float result =
181+ hamming_distance_u8 (std::span<const unsigned char >(a), std::span<const unsigned char >(b));
180182 benchmark::DoNotOptimize (result);
181183 }
182184 state.SetItemsProcessed (state.iterations () * 1536 );
@@ -196,7 +198,7 @@ static void BM_L2_Float_Batch_1000x128(benchmark::State& state) {
196198
197199 for (auto _ : state) {
198200 for (const auto & query : queries) {
199- float result = distance_l2_sqeuclidean (std::span<const float >(query),
201+ float result = l2_distance (std::span<const float >(query),
200202 std::span<const float >(target));
201203 benchmark::DoNotOptimize (result);
202204 }
@@ -253,6 +255,82 @@ static void BM_Int8_Cosine_NEON_DotProd_384(benchmark::State& state) {
253255}
254256BENCHMARK (BM_Int8_Cosine_NEON_DotProd_384);
255257
258+ static void BM_Int8_InnerProduct_NEON_DotProd_384 (benchmark::State& state) {
259+ auto a = generate_random_vector<int8_t >(384 , int8_t {-127 }, int8_t {127 });
260+ auto b = generate_random_vector<int8_t >(384 , int8_t {-127 }, int8_t {127 });
261+
262+ for (auto _ : state) {
263+ float result = simd::inner_product_int8_neon_dotprod (std::span<const int8_t >(a),
264+ std::span<const int8_t >(b));
265+ benchmark::DoNotOptimize (result);
266+ }
267+ state.SetItemsProcessed (state.iterations () * 384 );
268+ }
269+ BENCHMARK (BM_Int8_InnerProduct_NEON_DotProd_384);
270+
256271#endif // SQLITE_VEC_ENABLE_NEON && __ARM_FEATURE_DOTPROD
257272
273+ // ============================================================================
274+ // NEON int8 Benchmarks (widening, no DotProd required)
275+ // ============================================================================
276+
277+ #if defined(SQLITE_VEC_ENABLE_NEON)
278+ #ifndef __ARM_FEATURE_DOTPROD
279+ #include " ../include/sqlite-vec-cpp/simd/neon.hpp"
280+ #endif
281+
282+ static void BM_Int8_InnerProduct_NEON_384 (benchmark::State& state) {
283+ auto a = generate_random_vector<int8_t >(384 , int8_t {-127 }, int8_t {127 });
284+ auto b = generate_random_vector<int8_t >(384 , int8_t {-127 }, int8_t {127 });
285+
286+ for (auto _ : state) {
287+ float result = simd::inner_product_int8_neon (std::span<const int8_t >(a),
288+ std::span<const int8_t >(b));
289+ benchmark::DoNotOptimize (result);
290+ }
291+ state.SetItemsProcessed (state.iterations () * 384 );
292+ }
293+ BENCHMARK (BM_Int8_InnerProduct_NEON_384);
294+
295+ static void BM_Int8_Cosine_NEON_384 (benchmark::State& state) {
296+ auto a = generate_random_vector<int8_t >(384 , int8_t {-127 }, int8_t {127 });
297+ auto b = generate_random_vector<int8_t >(384 , int8_t {-127 }, int8_t {127 });
298+
299+ for (auto _ : state) {
300+ float result = simd::cosine_distance_int8_neon (std::span<const int8_t >(a),
301+ std::span<const int8_t >(b));
302+ benchmark::DoNotOptimize (result);
303+ }
304+ state.SetItemsProcessed (state.iterations () * 384 );
305+ }
306+ BENCHMARK (BM_Int8_Cosine_NEON_384);
307+
308+ static void BM_Int8_Cosine_Scalar_384 (benchmark::State& state) {
309+ auto a = generate_random_vector<int8_t >(384 , int8_t {-127 }, int8_t {127 });
310+ auto b = generate_random_vector<int8_t >(384 , int8_t {-127 }, int8_t {127 });
311+
312+ for (auto _ : state) {
313+ float result = cosine_distance_int (std::span<const int8_t >(a),
314+ std::span<const int8_t >(b));
315+ benchmark::DoNotOptimize (result);
316+ }
317+ state.SetItemsProcessed (state.iterations () * 384 );
318+ }
319+ BENCHMARK (BM_Int8_Cosine_Scalar_384);
320+
321+ static void BM_Int8_InnerProduct_Scalar_384 (benchmark::State& state) {
322+ auto a = generate_random_vector<int8_t >(384 , int8_t {-127 }, int8_t {127 });
323+ auto b = generate_random_vector<int8_t >(384 , int8_t {-127 }, int8_t {127 });
324+
325+ for (auto _ : state) {
326+ float result = inner_product_distance_int (std::span<const int8_t >(a),
327+ std::span<const int8_t >(b));
328+ benchmark::DoNotOptimize (result);
329+ }
330+ state.SetItemsProcessed (state.iterations () * 384 );
331+ }
332+ BENCHMARK (BM_Int8_InnerProduct_Scalar_384);
333+
334+ #endif // SQLITE_VEC_ENABLE_NEON
335+
258336BENCHMARK_MAIN ();
0 commit comments