Add deployable CPU linear-scan backend - #2347
Conversation
|
@codex review |
|
To use Codex here, create a Codex account and connect to github. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 57025e7775
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uses the companion ampc-common checkpoint d3f443f for specialized FHD thresholds and multi-flow session striping. The public dependency pin remains unchanged until that AMPC commit is published.
5b621ff to
77cfb8b
Compare
| return Ok(ids | ||
| .iter() | ||
| .map(|id| store.get_vector_or_empty(id).clone()) | ||
| .collect()); |
There was a problem hiding this comment.
just thinking: Since this is behind a trait anyways can the cold-storage one not be a completely new struct, maybe wrapping the old worker pool, instead of doing a lot of selecting based on this option here?
(This was about the Option<ColdStorage>) in the worker)
| } | ||
|
|
||
| tracing::info!( | ||
| eye = %second_eye_side, | ||
| orientation = orientation_label(orientation), | ||
| requests = n_requests, | ||
| candidates = candidate_count, | ||
| "Running candidate-only linear-scan stage" | ||
| ); | ||
| metrics::counter!("linear_scan_second_eye_candidates_total").increment(candidate_count as u64); | ||
| let second_results = linear_scan_eye( | ||
| sessions, | ||
| search_queries, | ||
| &search_params, | ||
| LinearScanEyeContext { | ||
| eye: second_eye_side, |
There was a problem hiding this comment.
Probably does not take too long but this is the whole DB id set, right? Maybe the registries can just keep this around themselves instead of computing it here fresh?
(This was about the live_id creation block in linear_search_cascade)
Persistence - Startup modification replay advances version_id explicitly for reauth/identity-update/deletion rows, matching live persistence. The content-sensitive trigger left a replaying node one version behind its peers for idempotent writes (dummy -> dummy deletions, identical reset shares), which diverges registry set hashes and fails cold-eye exact-version reads closed. - update_iris_and_increment_version reports a missing row instead of bailing; process_job_result logs and counts it rather than exiting all parties on one out-of-range serial id. Linear-scan matching - Resolve the matching module's other-eye comparisons from the cascade results instead of a second is_match_batch pass. Every requested id was already evaluated on both eyes (strict matches are a subset of the anon-stats prefilter; LUC/OR-rule/reauth ids are unioned into the candidate stage), so this removes per-rotation cold-eye database reads from the MPC critical path and a second, different threshold circuit. - Cap match_ids and full_face_mirror_match_ids like the partial lists (CUDA reports at most ALL_MATCHES_LEN per device). - Apply the supermatch threshold only when return_partial_results is set, as the CUDA actor's match counters stay zero otherwise. - Reject SMPC__FULL_SCAN_SIDE_SWITCHING_ENABLED=true in linear-scan mode instead of silently ignoring it. HNSW/GPU scope - Keep HNSW anon-stats recording for skip_persistence requests; only the linear-scan backend mirrors the CUDA behavior. - Restore tolerant cuMemHostRegister handling in the GPU actor, logging a warning instead of panicking at startup. Cleanup - Remove the unreachable linear-scan branch from per_session; matching scans must use linear_scan_cascade. - Share one implementation across the from_cli* test constructors. - Drop the copied clippy allow from the new binary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAbAnQyfsSrWH6UGcRM1FF
- Cache the serial-ordered live VectorId list in SharedIrises, dropped by every mutation, and have linear_scan_cascade take it from the registry instead of re-enumerating millions of points per scan. All requests, sessions, and orientations of a batch now share one allocation. - full_rotation_dot_shares no longer demands DistanceMode::MinRotation: the exact scan is neither distance mode, it opens each of the 31 rotations separately. Keep the check that actually matters, that the query is the center rotation of the Hawk query layout. - In cold mode the non-resident registry is a copy of the resident one, so log a single resident checksum instead of two identical values that look like an independent check. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAbAnQyfsSrWH6UGcRM1FF
worldcoin/ampc-common#138 merged; a0b968c4 was its pre-merge head and is not an ancestor of ampc-common main. Pin 11bcd059, the current main head, which also carries the #140 threshold-path allocation reductions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAbAnQyfsSrWH6UGcRM1FF
A fresh Cargo.lock hash (the ampc-common re-pin) makes the release build consume most of the old budgets; unit-tests was then cancelled during its cache upload, keeping every later run cold, and the integration tests were cancelled mid-run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAbAnQyfsSrWH6UGcRM1FF
Summary
Adds the correctness baseline for a deployable ARM CPU exact-scan backend as a new
iris-mpc-linear-scantarget. It reuses the production Hawk request, MPC, persistence, and result pipeline, but replaces HNSW candidate search with the GPU actor's two-eye linear-scan semantics. Existing GPU and HNSW targets remain available and unchanged.This PR deliberately contains the simple scan implementation: no cold-eye cache/prefetch layer and no mixed-plane, fused mirror, NEON/UMMLA, or dot/MPC pipeline optimizations.
Depends on worldcoin/ampc-common#138; all four AMPC crates are pinned to
fa95ff78a91ef3cfb3c8020afab0e50eae0dc88a.Behavior and correctness
SMPC__MAX_BATCH_SIZE=1; the resident eye changes only on a coordinated restart throughSMPC__FULL_SCAN_SIDE.CPU/GPU equivalence was checked on 3 × A40 for public results and retained distance shares. A deterministic 100-request full-server sequence covering enroll, duplicate, mirror, deletion, reauth, reset, and recovery also produced identical canonical CPU/GPU result files with a 5,000-record database, larger than one CPU scan chunk.
Validation
cargo check -p iris-mpc-bins --bin iris-mpc-linear-scancargo clippy -p iris-mpc-cpu -p iris-mpc -p iris-mpc-bins --all-targets -- -D warningsdb_dependent.Deployment note
The additive binary, image workflow, and stage/prod manifests are introduced here, but production should deploy the complete stack through #2348. Do not run GPU and CPU consumers against the shared queues simultaneously; drain all three GPU consumers, then roll all three CPU parties together with the same full-scan side.
Review guide
iris-mpc-bins/bin/iris-mpc/server/iris_mpc_linear_scan.rsand mode selection iniris-mpc/src/server/mod.rs.iris-mpc-cpu/src/execution/hawk_main/search.rs.worker_pool_initializer.rsandiris_worker.rs.Stack