Measure distance between floating-point vectors in Rust
Hello Rustaceans!
This is a Rust library. Here you can do:
- Add this crate as a dependency of your Rust project:
cargo add floating-distance
- Check out the documentation and source codes (click the badges above for more information)
- Clone the GitHub repository and run the examples:
cargo run --example default
Examples
- Measure the cosine similarity between two vectors
v0andv1
use *;
feature = ["simd"]
What's special?
SIMD is the acronym for Single Instruction Multiple Data
Modern CPUs have special instructions. We can use them to accelerate vector computations!
How to start?
You can enable simd feature in this crate by the following steps:
- Specify
features = ["simd"]inCargo.tomlmanifest:
[dependencies]
floating-distance = { version = "*", features = ["simd"] }
- Compile with Rust nightly version. You can add this to
rust-toolchain.toml, which is next toCargo.toml:
[toolchain]
channel = "nightly"
- Choose the SIMD instruction sets which are supported by the target architecture. You can use
RUSTFLAGSenvironment variable and-C target-featurecompiler option like these:
RUSTFLAGS="-C target-feature=+ssse3" cargo build
RUSTFLAGS="-C target-feature=+avx,+sse3" cargo build --release
You can find all target features of Rust by this:
rustc --print target-features
The table shows how this library interprets target features:
| Unit width | Target features |
|---|---|
| 128-bits | sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3 |
| 256-bits | avx, avx2 |
| 512-bits | avx512vl |
How great is it?
I have run a simple benchmark on my laptop. Let's check out the results first!
SIMD 256-bits vs No SIMD, uses RUSTFLAGS="-C target-feature=+avx":
no_simd: 265,312 ns/iter (+/- 65,921)
simd: 37,681 ns/iter (+/- 11,822)
SIMD 128-bits vs No SIMD, uses RUSTFLAGS="-C target-feature=+ssse3":
no_simd: 267,294 ns/iter (+/- 70,412)
simd: 67,950 ns/iter (+/- 11,427)
| Unit type | Avarage time (ns/iter) | Rate (relative) |
|---|---|---|
| Packed 256-bits | 37681 | 7.07 |
| Packed 128-bits | 67950 | 3.92 |
| Scalar 32-bits | 266303 | 1.00 |
With the data above, we can see that SIMD can improve the performance by roughly Unit width / Scalar width times!
You can also benchmark it by repeating the following steps:
- Clone the repository and change it to the current directory
- Check target features in
.cargo/config.toml - Run this command:
(cargo +nightly bench -p benchmarks-no-simd &&
cargo +nightly bench -p benchmarks-simd) 2> /dev/null
Feature note
- This feature is built by experimental features of Rust
- Executing the program built with target features that are not supported by the target architecture may cause runtime errors