diff --git a/.cargo/config.toml b/.cargo/config.toml index d5135e9..eaedddf 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,3 @@ [build] -rustflags = ["-C", "target-cpu=native"] \ No newline at end of file +rustflags = ["-C", "target-cpu=native"] +rustdocflags = ["-C", "target-cpu=native"] \ No newline at end of file diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index f3002de..a00fff2 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -14,6 +14,9 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Update rust + run: rustup update + - name: Benchmark run: cargo bench --bench throughput --features bench-plot @@ -33,7 +36,7 @@ jobs: run: rustup default nightly - name: Benchmark - run: cargo bench --bench throughput --features bench-plot + run: cargo bench --bench throughput --features bench-plot hybrid - uses: actions/upload-artifact@v3 with: @@ -47,6 +50,9 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Update rust + run: rustup update + - name: Benchmark run: cargo bench --bench throughput --features bench-plot diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 79713e8..da4a907 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -24,7 +24,7 @@ jobs: run: cargo build --release - name: Test - run: cargo test --release --lib + run: cargo test --release build_test_x86_avx2: name: Build & Test X86 AVX2 @@ -40,10 +40,10 @@ jobs: run: cargo rustc -- --version - name: Build - run: cargo build --release + run: cargo build --release --features hybrid - name: Test - run: cargo test --release --lib + run: cargo test --release --features hybrid build_test_arm: name: Build & Test ARM @@ -59,4 +59,4 @@ jobs: run: cargo build --release - name: Test - run: cargo test --release --lib \ No newline at end of file + run: cargo test --release \ No newline at end of file diff --git a/.github/workflows/cross_compile.yml b/.github/workflows/cross_compile.yml new file mode 100644 index 0000000..74ba953 --- /dev/null +++ b/.github/workflows/cross_compile.yml @@ -0,0 +1,66 @@ +name: Cross Compile + +on: + # Trigger when merged on main + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + # Manual trigger + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: "-C target-feature=+aes,+vaes,+avx2" + +jobs: + + build_x86: + name: Build + + strategy: + fail-fast: false + matrix: + include: + - from: ubuntu-latest + target: "aarch64-apple-darwin" + allow_failure_hybrid: true + - from: ubuntu-latest + target: "aarch64-unknown-linux-gnu" + allow_failure_hybrid: true + - from: ubuntu-latest + target: "aarch64-unknown-linux-musl" + allow_failure_hybrid: true + - from: ubuntu-latest + target: "i686-unknown-linux-gnu" + allow_failure_hybrid: true + - from: ubuntu-latest + target: "x86_64-pc-windows-msvc" + allow_failure_hybrid: true # Supposed to work as hybrid but not tested yet + - from: ubuntu-latest + target: "x86_64-unknown-linux-gnu" + allow_failure_hybrid: false + - from: macos-latest + target: "aarch64-apple-darwin" + allow_failure_hybrid: true + - from: macos-latest + target: "x86_64-unknown-linux-gnu" + allow_failure_hybrid: true # Supposed to work as hybrid but not tested yet + + runs-on: ${{ matrix.from }} + + steps: + - uses: actions/checkout@v3 + + - name: Install target + run: rustup target add ${{ matrix.target }} + + - name: Build + run: cargo build --release --target ${{ matrix.target }} + + - name: Switch to nightly rust + run: rustup default nightly + + - name: Build Hybrid + continue-on-error: ${{ matrix.allow_failure_hybrid }} + run: cargo build --release --features hybrid --target ${{ matrix.target }} \ No newline at end of file diff --git a/.github/workflows/rust_version.yml b/.github/workflows/rust_version.yml index 30e608f..7be35bc 100644 --- a/.github/workflows/rust_version.yml +++ b/.github/workflows/rust_version.yml @@ -1,6 +1,10 @@ name: Rust Version Compatibility on: + # Trigger when merged on main + push: + branches: [ "main" ] + # Manual trigger workflow_dispatch: env: @@ -24,5 +28,4 @@ jobs: run: rustup toolchain install ${{ matrix.version }} - name: Build - # RUSTFLAGS="-C target-cpu=native --cfg hybrid" - run: RUSTFLAGS="-C target-cpu=native" cargo +${{ matrix.version }} build --release \ No newline at end of file + run: cargo +${{ matrix.version }} build --release \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index a3d5df9..c93eb90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "gxhash" authors = ["Olivier Giniaux"] -version = "3.2.0" +version = "3.3.0" edition = "2021" description = "GxHash non-cryptographic algorithm" license = "MIT" @@ -17,11 +17,13 @@ exclude = ["article/*"] bench-csv = [] bench-md = [] bench-plot = [] +hybrid = [] [dependencies] -rand = "0.8" +# No dependencies! [dev-dependencies] +rand = "0.8" lazy_static = { version = "1.4" } itertools = "0.12.0" # Benchmarks @@ -35,9 +37,6 @@ seahash = "4.1.0" metrohash = "1.0.6" fnv = "1.0.3" -[build-dependencies] -rustc_version = "0.4.0" - [dev-dependencies.plotters] version = "0.3.5" default-features = false diff --git a/build.rs b/build.rs index 63571f7..cf74f49 100644 --- a/build.rs +++ b/build.rs @@ -1,19 +1,3 @@ -extern crate rustc_version; -use rustc_version::{version_meta, Channel}; - fn main() { - // When conditions permits, enable hybrid feature to leverage wider intrinsics for even more throughput - if version_meta().unwrap().channel == Channel::Nightly - && cfg!(target_arch = "x86_64") - && cfg!(target_feature = "avx2") - && cfg!(target_feature = "vaes") { - println!("cargo:rustc-cfg=hybrid"); - } - // If not cross compiling, make sure the aes feature is available - if std::env::var("HOST").unwrap_or_default() == std::env::var("TARGET").unwrap_or_default() - && cfg!(not(target_feature = "aes")) { - panic!("| GxHash requires target-feature 'aes' to be enabled.\n\ - | Build with RUSTFLAGS=\"-C target-cpu=native\" or RUSTFLAGS=\"-C target-feature=+aes\" to enable."); - } } \ No newline at end of file diff --git a/src/gxhash/platform/x86.rs b/src/gxhash/platform/x86.rs index 980c08d..62c058a 100644 --- a/src/gxhash/platform/x86.rs +++ b/src/gxhash/platform/x86.rs @@ -59,7 +59,7 @@ pub unsafe fn ld(array: *const u32) -> State { _mm_loadu_si128(array as *const State) } -#[cfg(not(hybrid))] +#[cfg(not(feature = "hybrid"))] #[inline(always)] pub unsafe fn compress_8(mut ptr: *const State, end_address: usize, hash_vector: State, len: usize) -> State { @@ -100,7 +100,7 @@ pub unsafe fn compress_8(mut ptr: *const State, end_address: usize, hash_vector: aes_encrypt(lane1, lane2) } -#[cfg(hybrid)] +#[cfg(feature = "hybrid")] #[inline(always)] pub unsafe fn compress_8(ptr: *const State, end_address: usize, hash_vector: State, len: usize) -> State { macro_rules! load_unaligned_x2 { diff --git a/src/hasher.rs b/src/hasher.rs index 01341d1..2254722 100644 --- a/src/hasher.rs +++ b/src/hasher.rs @@ -1,8 +1,5 @@ use std::collections::{HashMap, HashSet}; use std::hash::{BuildHasher, Hasher}; -use std::mem::MaybeUninit; - -use rand::RngCore; use crate::gxhash::platform::*; use crate::gxhash::*; @@ -138,13 +135,10 @@ pub struct GxBuildHasher(State); impl Default for GxBuildHasher { #[inline] fn default() -> GxBuildHasher { - let mut uninit: MaybeUninit = MaybeUninit::uninit(); - let mut rng = rand::thread_rng(); + let random_state = std::hash::RandomState::new(); unsafe { - let ptr = uninit.as_mut_ptr() as *mut u8; - let slice = std::slice::from_raw_parts_mut(ptr, VECTOR_SIZE); - rng.fill_bytes(slice); - GxBuildHasher(uninit.assume_init()) + let state: State = std::mem::transmute(random_state); + GxBuildHasher(state) } } } diff --git a/src/lib.rs b/src/lib.rs index 863d67e..692058f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,11 @@ // Hybrid SIMD width usage currently requires unstable 'stdsimd' -#![cfg_attr(hybrid, feature(stdarch_x86_avx512))] +#![cfg_attr(feature = "hybrid", feature(stdarch_x86_avx512))] + +#[cfg(all(feature = "hybrid", not(any(target_arch = "x86_64", target_feature = "aes", target_feature = "vaes", target_feature = "avx2"))))] +compile_error!{"Hybrid feature is only available on x86 processors with avx2 and vaes intrinsics."} + +#[cfg(not(target_feature = "aes"))] +compile_error!{"Gxhash requires aes intrinsics. Make sure the processor supports it and build with RUSTFLAGS=\"-C target-cpu=native\" or RUSTFLAGS=\"-C target-feature=+aes\"."} #[rustfmt::skip] mod gxhash;