feat(agent): build the vector index in parallel by default
`parallel` joins the agent's default features, so the HNSW bulk build uses the thread pool: cold index build at 10K records 1152 -> ~380 ms in a same-moment A/B (the graph is identical either way). Nothing else on the measured paths changes — ingest, checkpoint, open and steady-state query times are the same with the feature on or off. Adds rayon to the default dependency set; opt out with `--no-default-features --features float16,hnsw`. Harness: `--e2e-only` runs the end-to-end section without the index benchmarks. Note for anyone comparing numbers: this machine's absolute timings drifted ~1.5x over a long session, so only same-moment A/B runs are comparable. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
8803d0754b
commit
f507803ec1
+3
-1
@@ -9,7 +9,9 @@
|
||||
With the `parallel` feature, planning and pruning run on a thread pool (10K:
|
||||
388 ms, 100K: ~21 s -> 5.9 s on 16 cores). The graph is deterministic and
|
||||
identical with or without the feature. `clawhdf5-agent`'s `parallel` feature
|
||||
now enables it for the agent's index.
|
||||
enables it for the agent's index and is now **on by default** (adds `rayon`
|
||||
to the default dependency set; build with `--no-default-features --features
|
||||
float16,hnsw` to opt out).
|
||||
- `clawhdf5-ann`: `HnswIndex::search` returned fewer than `k` results — often
|
||||
none — when the records nearest the query had been deleted: it collected `ef`
|
||||
candidates, *then* dropped the deleted ones, *then* took `k`. Deleted nodes
|
||||
|
||||
@@ -33,6 +33,8 @@ Cargo workspace with 16 crates under `crates/` (plus `libaec-sys`, an internal F
|
||||
the approximate `clawhdf5-ann` index for the vector stage (the index mirrors
|
||||
the cache and self-heals on drift). Build the agent with
|
||||
`--no-default-features --features float16` to force the exact linear cosine scan.
|
||||
The agent's `parallel` feature (also default) builds the index on a thread
|
||||
pool; the graph is identical with or without it.
|
||||
The index uses the HNSW paper's diversity heuristic for neighbour selection
|
||||
(plain closest-M capped recall on clustered data: 0.31 recall@10 at 100K). Its
|
||||
graph is saved to `<store>.h5.ann` at each checkpoint and reloaded by `open()`
|
||||
|
||||
@@ -45,7 +45,7 @@ name = "memory_bench"
|
||||
harness = false
|
||||
|
||||
[features]
|
||||
default = ["float16", "hnsw"]
|
||||
default = ["float16", "hnsw", "parallel"]
|
||||
float16 = ["half"]
|
||||
# Rayon-parallel brute-force search strategies, and a parallel bulk build of
|
||||
# the HNSW index (same graph, several times faster on a multi-core machine).
|
||||
|
||||
@@ -485,8 +485,12 @@ fn main() {
|
||||
|
||||
let mut json = Vec::new();
|
||||
println!("## Search harness");
|
||||
for &n in sizes {
|
||||
bench_ann(n, &mut json);
|
||||
// `--e2e-only` skips the index benchmarks, so the end-to-end section runs
|
||||
// in a process that has not already spun up a thread pool.
|
||||
if !args.iter().any(|a| a == "--e2e-only") {
|
||||
for &n in sizes {
|
||||
bench_ann(n, &mut json);
|
||||
}
|
||||
}
|
||||
|
||||
if ann_only {
|
||||
|
||||
Reference in New Issue
Block a user