This is a C++ vector search library currently implementing exact brute-force
Building secan requires CMake 3.15+ and a C++20-compliant compiler.
# Configure build
cmake -B build
# Build library, executable, and tests
cmake --build build
# Run test suite
ctest --test-dir build --output-on-failuresecan operates on flat contiguous row-major vector datasets and query vectors.
#include <iostream>
#include <vector>
#include "secan/search/search.h"
int main() {
// 3 vectors of dimension 2 (flat row-major layout: N * dim)
std::vector<float> dataset = {
1.0f, 2.0f,
3.0f, 4.0f,
5.0f, 6.0f
};
std::vector<float> query = {3.0f, 4.0f};
int top_k = 2;
// Search using "l2" (squared L2) or "cosine" distance
std::vector<SearchResult> results = linear_scan(dataset, query, top_k, "l2");
for (const auto &result : results) {
std::cout << "Index: " << result.index
<< ", Distance: " << result.distance << "\n";
}
return 0;
}Link against secan_lib in your CMakeLists.txt:
target_link_libraries(your_target PRIVATE secan_lib)Microbenchmarks are implemented using Google Benchmark v1.9.0 with memory clobber barriers (benchmark::DoNotOptimize) to prevent compiler dead-code elimination.
# Build and run microbenchmarks (Release mode required)
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
# 1. Individual vector distance microbenchmarks
./build/benchmarks/bench_distance
# 2. Exact linear scan working set scaling across cache hierarchy
./build/benchmarks/bench_exact_scan
# 3. Automated Memory Mountain sweep
python3 scripts/sweep_memory_mountain.pyBenchmarked on AMD Zen 4 Hawk Point (L1D 32 KiB, L2 1 MiB, L3 16 MiB, $D = 128$ float32).
Key Architectural Insight: Once the working set exceeds the 16 MiB L3 cache boundary (
$N > 32{,}000$ ), scan throughput drops by$4.73\times$ (from$67.63\text{ GiB/s}$ down to$14.28\text{ GiB/s}$ ), and IPC collapses from$3.27$ down to$1.08$ as SIMD execution units stall waiting for DRAM bus line fills.
Benchmarked on AMD Zen 4 Hawk Point 12-Core @ 4.30 GHz (Release -O3 -mavx2 -mfma -mavx512f -mavx512dq -mavx512bw -mavx512vl).
-
$L_2^2$ Vector Distance: Up to$50.3\times$ speedup over scalar baseline via AVX-512 dual accumulators ($4.64\text{ ns}$ for 128D, sustaining$>206\text{ GiB/s}$ peak bandwidth). -
Fused 1-Pass Cosine: Computes
$\sum a_i b_i$ ,$\sum a_i^2$ , and$\sum b_i^2$ in a single pass, eliminating redundant round-trips and cutting memory bus traffic by$66%$ ($20.7\times$ speedup).
Benchmarked on AMD Zen 4 Hawk Point ($D = 128$). Percentile clipping ($0.05\text{th}/99.95\text{th}$) preserves dynamic range while shrinking working memory by $4\times$.
| Metric ( |
FP32 AVX2 Baseline | SQ8 AVX2 (Compressed) | Improvement / Speedup |
|---|---|---|---|
| Full Dataset Memory Footprint |
|
||
| Exact Scan Query Latency |
|
|
|
| Scan Throughput | |||
| Reconstruction MSE |
|
Benchmarked on AMD Zen 4 Hawk Point ($D = 128$, $N = 100{,}000$). Evaluated against exact ground truth.
-
IvfFlatIndex: Achieves$92.9%$ Recall@10 at$12{,}900\text{ QPS}$ ($nprobe=8$ ), operating$33\times$ faster than exact flat scan. -
Curse of Dimensionality on KD-Trees: While spatial trees (FLANN) perform well in
$D \le 16$ , bounding-box overlap degrades recall to$<17%$ in 128D, demonstrating why Voronoi quantization (IVF) and graphs (HNSW) are required for modern high-dimensional embeddings.
IvfFlatIndex partitions high-dimensional vector spaces into
#include <iostream>
#include <vector>
#include "secan/index/ivf_flat.h"
int main() {
const size_t dim = 128;
const size_t nlist = 64; // 64 Voronoi clusters
const size_t n_vecs = 10000;
secan::IvfFlatIndex index(dim, nlist, secan::MetricType::L2);
// 1. Train cluster centroids
std::vector<float> train_data = /* ... 10,000 vectors ... */;
index.train(n_vecs, train_data.data(), 15);
// 2. Ingest vectors with IDs
std::vector<int32_t> ids(n_vecs);
for (size_t i = 0; i < n_vecs; ++i) ids[i] = static_cast<int32_t>(i);
index.add(n_vecs, ids.data(), train_data.data());
// 3. Multi-probe search (nprobe = 8 closest clusters, top k = 10)
std::vector<float> query = /* ... 128D query vector ... */;
std::vector<secan::SearchResult> hits = index.search(query.data(), 10, 8);
for (const auto &hit : hits) {
std::cout << "ID: " << hit.id << ", Distance: " << hit.distance << "\n";
}
return 0;
}- Scalar Baseline Distance Kernels (L2, IP, Cosine, Fast Reciprocal Cosine)
- Hardware Floating-Point State Control (FTZ/DAZ)
- AVX2 + FMA Single-Accumulator Distance Kernel
- AVX2 Multi-Accumulator ILP Unrolling (4-way register parallelism)
- Fused 1-Pass AVX2 Cosine Distance Kernel (66% cache bus traffic reduction)
- AVX-512 Distance Kernels (512-bit ZMM dual-accumulator unrolling)
- Memory scaling sweeps & cache eviction cliffs characterization (
$N \in [100, 10^6]$ ) - Memory-mapped zero-copy
.fvecsdataset ingestion with 2MB HugePages - Classical metric-space baseline: Randomized KD-Tree ensemble (
RandomizedKdTree) - Flat 2D Index (
Flat2DIndex) with cache-tiled batch scan (GEMV$\to$ GEMM$3.2\times$ throughput) - Cache-aligned Inverted File memory layout (
alignas(64)InvertedList) - IVF-Flat Index:
$k$ -means & spherical$k$ -means centroid training and multi-probe query routing (IvfFlatIndex) - Inverted list distribution diagnostics (
InvertedListStatsskew analysis) - Product Quantization (PQ) and Asymmetric Distance Computation (ADC)
- Scalar Quantization (SQ8) & AVX-512 VNNI Kernel (
_mm512_dpbusd_epi32INT8$4\times$ throughput compute) - 1-Bit Binary Quantization & AVX-512 Hamming Kernel (
_mm512_popcnt_epi64) - HNSW graph indexing for sub-millisecond approximate nearest neighbor search
MIT License. Copyright (c) 2026 Adheeb Ahmed.



