fix(linalg): enforce cosine u8 length contract - #8737
Conversation
|
Blocked: The current-head linux-build check is blocked by runner memory exhaustion in an unrelated io_uring test. Remote head 5d0c78a contains the current main tip 5e38587; Rust run 32790844710, job 97631926922 failed only at lance-io::uring::tests::test_read_range because both io_uring workers returned Cannot allocate memory (os error 12). The live logs and branch diff were inspected: this PR changes only rust/lance-linalg/src/distance/cosine_u8.rs, so repairing lance-io here would be an unrelated speculative change. Rerun linux-build on a runner with sufficient memory; alternatively, run the failing lance-io test on an io_uring-enabled host with adequate memory and provide the result. |
|
I had an independent fix for #8638 on a branch and opened #8860 before checking this issue's timeline, which was my mistake. I am closing #8860 in favour of this one. Three things came out of reviewing my own version that apply here. The kernel-level asserts diverge from the two merged siblings. Coverage is not the reason to prefer one or the other, since both close the hole. The three The One measurement that may be useful in the description. Replacing the always-on checks with a no-op takes the new test to failed under |
|
Addressed in 69ff6fe: moved the always-on length check to the dispatcher boundary, restored debug-only assertions inside the SIMD kernels to match dot_u8 and l2_u8, and removed the cosine-only panic sections. The two-direction rstest remains unchanged. |
|
Blocked: The Ready PR is blocked by two unrelated current-head CI failures. Remote head ace45a7 contains the current main tip 108f78e. Rust run 33250719598, linux-arm job 99095818271 failed only in the randomized Float32 legacy IVF_PQ multivector test at recall 0.49 versus the 0.50 requirement (3,271 passed, 1 failed); the exact focused test passed locally on this same head. Python run 33250719594, windows job 99095818216 failed only in test_index_cast_centroids because Torch Inductor could not read its generated temporary module (PermissionError, errno 13; 1,363 passed, 1 failed). The live logs and diff were inspected: this PR changes only rust/lance-linalg/src/distance/cosine_u8.rs, not either failing Float32/Torch path, so changing code here would be speculative and unrelated. Rerun linux-arm and windows on clean runners. Alternatively, run the exact Rust test on ARM and the Python test on Windows with a writable Torch Inductor cache, then provide those results. |
There was a problem hiding this comment.
✅ Gate recommendation: approve.
The latest base sync preserves the reviewed cosine_u8 patch exactly. New adjacent changes widen dot/L2 accumulation but do not alter cosine routing or its scalar and dispatched validation boundaries, so the release-mode safety and mismatched-length behavior remain intact.
|
Thank you @Xuanwo |
Summary
Root cause
The safe u8 cosine dispatcher selected a backend whose only length guard was a debug assertion. Release builds removed that guard, while SIMD loops bounded loads by the left slice length and loaded from the right slice unchecked. The scalar path also silently truncated mismatched inputs through iterator zipping.
Validation
cargo fmt --all -- --checkcargo test -p lance-linalg --lib distance::cosine_u8(8 passed)cargo test -p lance-linalg --lib(250 passed, 1 ignored)cargo test --release -p lance-linalg --lib distance::cosine_u8::tests::rejects_mismatched_lengths(2 passed)cargo clippy --all --tests --benches -- -D warningscargo doc -p lance-linalg --no-depsFixes #8638