feat: Add native fixed-array dot - #28504
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #28504 +/- ##
==========================================
- Coverage 81.71% 79.08% -2.64%
==========================================
Files 1870 1871 +1
Lines 262992 263158 +166
Branches 3217 3220 +3
==========================================
- Hits 214917 208106 -6811
- Misses 47243 54221 +6978
+ Partials 832 831 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
c9347ef to
c28fe48
Compare
|
Possible follow-up, separate from this PR, is to fuse sibling df.select(
score_a=pl.col("embedding").arr.dot(query_a),
score_b=pl.col("embedding").arr.dot(query_b),
)Today each expression traverses embedding independently. Planner could read each embedding array once, compute both scores in one multi-query kernel, and still return two separately named columns. Expressions that cannot be fused would continue using existing Standalone Apple M4 experiment found this faster from two query vectors onward, but it has not been validated inside Polars and floating-point tolerance is unresolved. I don't want to mess with baseline. |
07fad23 to
1f2765f
Compare
1f2765f to
16dce81
Compare
|
Addressed raw-query-vector API mismatch. |
Allow Python lists, 1D NumPy arrays, and literal vectors to inherit the left Array dtype, matching embedding-scoring workflows without weakening strict dtype checks between columns.
Document null and floating-point behavior, and cover all-missing rows, special values, cancellation, fragmented inputs, and wide all-valid arrays.
d3df4a5 to
3e79306
Compare
|
@orlp , @ritchie46 , whenever you have time, this one is ready. I don't want to grow scope, it's reasonable with limitations and follow-up work. Happy to answer your questions. |
|
Verified current implementation explicitly on both produced identical results |
Closes #17456 and benefits embedding pipelines doing similarity scoring or candidate reranking.
Also, related to #24652 requesting vertical fixed-array aggregation Expr.sum() reducing Array rows into one Array.
Issue example uses
Expr.dot, which reduces columns to one scalar. This PR addsarr.dotbecause requested operation is row-wise over each fixed-size array.API distinction:
Existing equivalent materializes a
rows × widthmultiplication result before reducing:Native implementation reads both arrays and writes one scalar per row. For 1M rows of Array(Float32, width=768), this avoids roughly 2.86 GiB multiplication buffer.Attached benchmark in comments.
Scope:
Float32orFloat64inner dtypes;Limitations:
Update (2026-07-30):
arr.dotnow accepts Python sequences and one-dimensional NumPy arrays directly. These raw query vectors inherit complete Array dtype of the left expression. Explicit expressions and Series operands retain their dtype and must match the left operand.