Skip to content

Commit 16fa90f

Browse files
committed
Add: Introspect Rust builds
1 parent 908df0d commit 16fa90f

File tree

4 files changed

+156
-7
lines changed

4 files changed

+156
-7
lines changed

build.rs

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,73 @@
11
fn main() {
2-
cxx_build::bridge("rust/lib.rs")
2+
let mut build = cxx_build::bridge("rust/lib.rs");
3+
4+
build
35
.file("rust/lib.cpp")
4-
.flag_if_supported("-std=c++11")
6+
.file("simsimd/c/lib.c")
57
.flag_if_supported("-Wno-unknown-pragmas")
8+
.warnings(false)
69
.include("include")
710
.include("rust")
811
.include("fp16/include")
9-
.include("simsimd/include")
10-
.compile("usearch");
12+
.include("simsimd/include");
13+
14+
build
15+
.define("USEARCH_USE_SIMSIMD", "1")
16+
.define("SIMSIMD_DYNAMIC_DISPATCH", "1")
17+
.define("USEARCH_USE_OPENMP", "0")
18+
.define("USEARCH_USE_FP16LIB", "0");
19+
20+
// Conditional compilation depending on the target operating system.
21+
if cfg!(target_os = "linux") {
22+
build
23+
.flag_if_supported("-std=c++17")
24+
.flag_if_supported("-O3")
25+
.flag_if_supported("-ffast-math")
26+
.flag_if_supported("-fdiagnostics-color=always")
27+
.flag_if_supported("-g1"); // Simplify debugging
28+
} else if cfg!(target_os = "macos") {
29+
build
30+
.flag_if_supported("-mmacosx-version-min=10.15")
31+
.flag_if_supported("-std=c++17")
32+
.flag_if_supported("-O3")
33+
.flag_if_supported("-ffast-math")
34+
.flag_if_supported("-fcolor-diagnostics")
35+
.flag_if_supported("-g1"); // Simplify debugging
36+
} else if cfg!(target_os = "windows") {
37+
build
38+
.flag_if_supported("/std:c++17")
39+
.flag_if_supported("/O2")
40+
.flag_if_supported("/fp:fast")
41+
.flag_if_supported("/W1"); // Reduce warnings verbosity
42+
}
43+
44+
if build.try_compile("usearch").is_err() {
45+
print!("cargo:warning=Failed to compile with all SIMD backends...");
46+
47+
let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
48+
let flags_to_try = match target_arch.as_str() {
49+
"arm" | "aarch64" => vec!["SIMSIMD_TARGET_NEON", "SIMSIMD_TARGET_SVE"],
50+
_ => vec![
51+
"SIMSIMD_TARGET_SAPPHIRE",
52+
"SIMSIMD_TARGET_ICE",
53+
"SIMSIMD_TARGET_SKYLAKE",
54+
"SIMSIMD_TARGET_HASWELL",
55+
],
56+
};
57+
58+
for flag in flags_to_try.iter() {
59+
build.define(flag, "0");
60+
if build.try_compile("usearch").is_ok() {
61+
break;
62+
}
63+
64+
// Print the failed configuration
65+
println!(
66+
"cargo:warning=Failed to compile after disabling {}, trying next configuration...",
67+
flag
68+
);
69+
}
70+
}
1171

1272
println!("cargo:rerun-if-changed=rust/lib.rs");
1373
println!("cargo:rerun-if-changed=rust/lib.cpp");

rust/lib.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ void NativeIndex::view(rust::Str path) const {
7979

8080
void NativeIndex::reset() const { index_->reset(); }
8181
size_t NativeIndex::memory_usage() const { return index_->memory_usage(); }
82+
char const* NativeIndex::hardware_acceleration() const { return index_->metric().isa_name(); }
8283

8384
void NativeIndex::save_to_buffer(rust::Slice<uint8_t> buffer) const {
8485
index_->save(memory_mapped_file_t((byte_t*)buffer.data(), buffer.size())).error.raise();

rust/lib.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class NativeIndex {
5757
void view(rust::Str path) const;
5858
void reset() const;
5959
size_t memory_usage() const;
60+
char const* hardware_acceleration() const;
6061

6162
void save_to_buffer(rust::Slice<uint8_t> buffer) const;
6263
void load_from_buffer(rust::Slice<uint8_t const> buffer) const;

rust/lib.rs

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ pub mod ffi {
8585
pub fn view(self: &NativeIndex, path: &str) -> Result<()>;
8686
pub fn reset(self: &NativeIndex) -> Result<()>;
8787
pub fn memory_usage(self: &NativeIndex) -> usize;
88+
pub fn hardware_acceleration(self: &NativeIndex) -> *const c_char;
8889

8990
pub fn save_to_buffer(self: &NativeIndex, buffer: &mut [u8]) -> Result<()>;
9091
pub fn load_from_buffer(self: &NativeIndex, buffer: &[u8]) -> Result<()>;
@@ -202,6 +203,15 @@ impl Index {
202203
self.inner.change_expansion_search(n)
203204
}
204205

206+
/// Retrieves the hardware acceleration information.
207+
pub fn hardware_acceleration(&self) -> String {
208+
use core::ffi::CStr;
209+
unsafe {
210+
let c_str = CStr::from_ptr(self.inner.hardware_acceleration());
211+
c_str.to_string_lossy().into_owned()
212+
}
213+
}
214+
205215
/// Performs k-Approximate Nearest Neighbors (kANN) Search for closest vectors to the provided query.
206216
///
207217
/// # Arguments
@@ -438,6 +448,81 @@ mod tests {
438448
use crate::new_index;
439449
use crate::Index;
440450

451+
use std::env;
452+
453+
#[test]
454+
fn print_specs() {
455+
print!("--------------------------------------------------\n");
456+
println!("OS: {}", env::consts::OS);
457+
println!(
458+
"Rust version: {}",
459+
env::var("RUST_VERSION").unwrap_or_else(|_| "unknown".into())
460+
);
461+
462+
// Create indexes with different configurations
463+
let f64_index = Index::new(&IndexOptions {
464+
dimensions: 256,
465+
metric: MetricKind::Cos,
466+
quantization: ScalarKind::F64,
467+
..Default::default()
468+
})
469+
.unwrap();
470+
471+
let f32_index = Index::new(&IndexOptions {
472+
dimensions: 256,
473+
metric: MetricKind::Cos,
474+
quantization: ScalarKind::F32,
475+
..Default::default()
476+
})
477+
.unwrap();
478+
479+
let f16_index = Index::new(&IndexOptions {
480+
dimensions: 256,
481+
metric: MetricKind::Cos,
482+
quantization: ScalarKind::F16,
483+
..Default::default()
484+
})
485+
.unwrap();
486+
487+
let i8_index = Index::new(&IndexOptions {
488+
dimensions: 256,
489+
metric: MetricKind::Cos,
490+
quantization: ScalarKind::I8,
491+
..Default::default()
492+
})
493+
.unwrap();
494+
495+
let b1_index = Index::new(&IndexOptions {
496+
dimensions: 256,
497+
metric: MetricKind::Hamming,
498+
quantization: ScalarKind::B1,
499+
..Default::default()
500+
})
501+
.unwrap();
502+
503+
println!(
504+
"f64 hardware acceleration: {}",
505+
f64_index.hardware_acceleration()
506+
);
507+
println!(
508+
"f32 hardware acceleration: {}",
509+
f32_index.hardware_acceleration()
510+
);
511+
println!(
512+
"f16 hardware acceleration: {}",
513+
f16_index.hardware_acceleration()
514+
);
515+
println!(
516+
"i8 hardware acceleration: {}",
517+
i8_index.hardware_acceleration()
518+
);
519+
println!(
520+
"b1 hardware acceleration: {}",
521+
b1_index.hardware_acceleration()
522+
);
523+
print!("--------------------------------------------------\n");
524+
}
525+
441526
#[test]
442527
fn test_add_get_vector() {
443528
let mut options = IndexOptions::default();
@@ -494,17 +579,17 @@ mod tests {
494579
let mut found_slice = [0.0 as f32; 4];
495580
assert_eq!(index.get(id1, &mut found_slice).unwrap(), 1);
496581
assert!(index.remove(id1).is_ok());
497-
582+
498583
assert!(index.add(id2, &second).is_ok());
499584
let mut found_slice = [0.0 as f32; 4];
500585
assert_eq!(index.get(id2, &mut found_slice).unwrap(), 1);
501586
assert!(index.remove(id2).is_ok());
502-
587+
503588
assert!(index.add(id3, &second).is_ok());
504589
let mut found_slice = [0.0 as f32; 4];
505590
assert_eq!(index.get(id3, &mut found_slice).unwrap(), 1);
506591
assert!(index.remove(id3).is_ok());
507-
592+
508593
assert!(index.add(id4, &second).is_ok());
509594
let mut found_slice = [0.0 as f32; 4];
510595
assert_eq!(index.get(id4, &mut found_slice).unwrap(), 1);
@@ -532,6 +617,7 @@ mod tests {
532617
let first: [f32; 5] = [0.2, 0.1, 0.2, 0.1, 0.3];
533618
let second: [f32; 5] = [0.3, 0.2, 0.4, 0.0, 0.1];
534619

620+
print!("--------------------------------------------------\n");
535621
println!(
536622
"before add, memory_usage: {} \
537623
cap: {} \
@@ -566,6 +652,7 @@ mod tests {
566652
let results = index.search(&first, 10).unwrap();
567653
println!("{:?}", results);
568654
assert_eq!(results.keys.len(), 2);
655+
print!("--------------------------------------------------\n");
569656

570657
// Validate serialization
571658
assert!(index.save("index.rust.usearch").is_ok());

0 commit comments

Comments
 (0)