Commit 3908319
authored
Fix vector type native adapters (#1263)
`Vector.from_native` and `Vector.to_native` both used to have alternative
implementations using NumPy or the Rust extensions when available to speed up
the process. It turns out, that both didn't follow the reference Python
implementation (internally relying on `struct.pack`/`struct.unpack`) for 32 bit
float values.
* Python 3.14+ preserves the signaling/quieting bit of `NaN` values whereas
NumPy doesn't and Rust doesn't make strong guarantees on how f64s are cast to
f32s:
https://github.com/rust-lang/rfcs/blob/master/text/3514-float-semantics.md
* Both NumPy and Rust turn large f64s into `inf` when cast to f32, while Python
raises an `OverflowError`.
To harmonize the behavior, only the Python implementation remains. It has been
significantly sped up by not iterating over the elements and calling
`struct.(un)pack` multiple times, but instead making use of the fact that the
format string allows to specify a number of values to (un)pack. With this the
performance of the Python implementation was never slower than 5 times of what
Rust/NumPy offered and for low dimension vectors even faster. It's deemed not
worth the effort of maintaining multiple implementations assuring their
behavioral parity for such a small performance gain.
The same multi-value (un)pack approach has been applied to the pure Python
implementation of the byte swapping to improve it's performance by a factor of
roughly 30 (still a factor of ~10 slower than using NumPy/Rust).1 parent 3a0c89e commit 3908319
File tree
3 files changed
+389
-551
lines changed- src/neo4j
- tests/unit/common/vector
3 files changed
+389
-551
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| |||
79 | 80 | | |
80 | 81 | | |
81 | 82 | | |
| 83 | + | |
82 | 84 | | |
83 | 85 | | |
84 | 86 | | |
| |||
0 commit comments