aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack O'Connor <[email protected]>2025-03-09 11:29:04 -0700
committerJack O'Connor <[email protected]>2025-03-11 13:03:59 -0700
commit97ce1c8c47940357f82b6dfa56cdd55d5f8ec1d4 (patch)
tree2ddbc2f37bf8933a8b79a6a8518ac34df61d0151
parentd9b49df0757f8bdfaa542e7181013fbf1555ff89 (diff)
tbb support in blake3_c_rust_bindingsrust_bindings_tbb
-rw-r--r--.github/workflows/ci.yml25
-rw-r--r--c/CMakeLists.txt2
-rw-r--r--c/blake3_c_rust_bindings/Cargo.toml2
-rw-r--r--c/blake3_c_rust_bindings/benches/bench.rs84
-rw-r--r--c/blake3_c_rust_bindings/build.rs26
-rw-r--r--c/blake3_c_rust_bindings/src/lib.rs17
-rw-r--r--c/blake3_c_rust_bindings/src/test.rs27
7 files changed, 182 insertions, 1 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4bb3aaf..51faeb1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -399,3 +399,28 @@ jobs:
# we might add more. If this accidentally picks up anything incompatible or
# slow, we can narrow it.
- run: cargo miri test miri
+
+ tbb_rust_bindings_tests:
+ name: TBB test bindings ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: ["ubuntu-latest", "macOS-latest"]
+ steps:
+ - uses: actions/checkout@v4
+ - uses: dtolnay/rust-toolchain@stable
+ - name: install TBB
+ if: matrix.os == 'ubuntu-latest'
+ run: |
+ sudo apt-get update
+ sudo apt-get install libtbb-dev libtbb12
+ - name: install TBB
+ if: matrix.os == 'macOS-latest'
+ run: |
+ brew install tbb
+ echo "CXXFLAGS=-I$(brew --prefix)/include $CPPFLAGS" >> $GITHUB_ENV
+ echo "RUSTFLAGS=-L$(brew --prefix)/lib $RUSTFLAGS" >> $GITHUB_ENV
+ - name: cargo test C bindings with TBB
+ run: cargo test --features=tbb
+ working-directory: ./c/blake3_c_rust_bindings
diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt
index ba88ed3..8a15d34 100644
--- a/c/CMakeLists.txt
+++ b/c/CMakeLists.txt
@@ -249,7 +249,7 @@ if(BLAKE3_USE_TBB)
set(APPEND BLAKE3_CXX_STANDARD_FLAGS_MSVC /std:c++20)
endif()
set(BLAKE3_CXXFLAGS_GNU "-fno-exceptions;-fno-rtti;${BLAKE3_CXX_STANDARD_FLAGS_GNU}" CACHE STRING "C++ flags used for compiling private BLAKE3 library components with GNU-like compiler frontends.")
- set(BLAKE3_CXXFLAGS_MSVC "/EHs-c-;/GR;${BLAKE3_CXX_STANDARD_FLAGS_MSVC}" CACHE STRING "C++ flags used for compiling private BLAKE3 library components with MSVC-like compiler frontends.")
+ set(BLAKE3_CXXFLAGS_MSVC "/EHs-c-;/GR-;${BLAKE3_CXX_STANDARD_FLAGS_MSVC}" CACHE STRING "C++ flags used for compiling private BLAKE3 library components with MSVC-like compiler frontends.")
# Get the C++ compiler name without extension
get_filename_component(BLAKE3_CMAKE_CXX_COMPILER_NAME "${CMAKE_CXX_COMPILER}" NAME_WE)
# Strip any trailing versioning from the C++ compiler name
diff --git a/c/blake3_c_rust_bindings/Cargo.toml b/c/blake3_c_rust_bindings/Cargo.toml
index e70f16b..4c3a252 100644
--- a/c/blake3_c_rust_bindings/Cargo.toml
+++ b/c/blake3_c_rust_bindings/Cargo.toml
@@ -16,6 +16,8 @@ prefer_intrinsics = []
# Activate NEON bindings. We don't currently do any CPU feature detection for
# this. If this Cargo feature is on, the NEON gets used.
neon = []
+# Enable TBB-based multithreading.
+tbb = []
[dev-dependencies]
arrayref = "0.3.5"
diff --git a/c/blake3_c_rust_bindings/benches/bench.rs b/c/blake3_c_rust_bindings/benches/bench.rs
index 5011347..b6c5704 100644
--- a/c/blake3_c_rust_bindings/benches/bench.rs
+++ b/c/blake3_c_rust_bindings/benches/bench.rs
@@ -371,6 +371,90 @@ fn bench_incremental_1024_kib(b: &mut Bencher) {
bench_incremental(b, 1024 * KIB);
}
+#[cfg(feature = "tbb")]
+fn bench_tbb(b: &mut Bencher, len: usize) {
+ let mut input = RandomInput::new(b, len);
+ b.iter(|| {
+ let mut hasher = blake3_c_rust_bindings::Hasher::new();
+ hasher.update_tbb(input.get());
+ let mut out = [0; 32];
+ hasher.finalize(&mut out);
+ out
+ });
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0001_block(b: &mut Bencher) {
+ bench_tbb(b, BLOCK_LEN);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0001_kib(b: &mut Bencher) {
+ bench_tbb(b, 1 * KIB);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0002_kib(b: &mut Bencher) {
+ bench_tbb(b, 2 * KIB);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0004_kib(b: &mut Bencher) {
+ bench_tbb(b, 4 * KIB);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0008_kib(b: &mut Bencher) {
+ bench_tbb(b, 8 * KIB);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0016_kib(b: &mut Bencher) {
+ bench_tbb(b, 16 * KIB);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0032_kib(b: &mut Bencher) {
+ bench_tbb(b, 32 * KIB);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0064_kib(b: &mut Bencher) {
+ bench_tbb(b, 64 * KIB);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0128_kib(b: &mut Bencher) {
+ bench_tbb(b, 128 * KIB);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0256_kib(b: &mut Bencher) {
+ bench_tbb(b, 256 * KIB);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_0512_kib(b: &mut Bencher) {
+ bench_tbb(b, 512 * KIB);
+}
+
+#[bench]
+#[cfg(feature = "tbb")]
+fn bench_tbb_1024_kib(b: &mut Bencher) {
+ bench_tbb(b, 1024 * KIB);
+}
+
// This checks that update() splits up its input in increasing powers of 2, so
// that it can recover a high degree of parallelism when the number of bytes
// hashed so far is uneven. The performance of this benchmark should be
diff --git a/c/blake3_c_rust_bindings/build.rs b/c/blake3_c_rust_bindings/build.rs
index c5dc927..e176dac 100644
--- a/c/blake3_c_rust_bindings/build.rs
+++ b/c/blake3_c_rust_bindings/build.rs
@@ -52,6 +52,21 @@ fn new_build() -> cc::Build {
build
}
+fn new_cpp_build() -> cc::Build {
+ let mut build = cc::Build::new();
+ build.cpp(true);
+ if is_windows_msvc() {
+ build.flag("/std:c++20");
+ build.flag("/EHs-c-");
+ build.flag("/GR-");
+ } else {
+ build.flag("-std=c++20");
+ build.flag("-fno-exceptions");
+ build.flag("-fno-rtti");
+ }
+ build
+}
+
fn c_dir_path(filename: &str) -> String {
// The `cross` tool doesn't support reading files in parent directories. As a hacky workaround
// in `cross_test.sh`, we move the c/ directory around and set BLAKE3_C_DIR_OVERRIDE. Regular
@@ -68,8 +83,19 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
base_build.file(c_dir_path("blake3.c"));
base_build.file(c_dir_path("blake3_dispatch.c"));
base_build.file(c_dir_path("blake3_portable.c"));
+ if cfg!(feature = "tbb") {
+ base_build.define("BLAKE3_USE_TBB", "1");
+ }
base_build.compile("blake3_base");
+ if cfg!(feature = "tbb") {
+ let mut tbb_build = new_cpp_build();
+ tbb_build.define("BLAKE3_USE_TBB", "1");
+ tbb_build.file(c_dir_path("blake3_tbb.cpp"));
+ tbb_build.compile("blake3_tbb");
+ println!("cargo::rustc-link-lib=tbb");
+ }
+
if is_x86_64() && !defined("CARGO_FEATURE_PREFER_INTRINSICS") {
// On 64-bit, use the assembly implementations, unless the
// "prefer_intrinsics" feature is enabled.
diff --git a/c/blake3_c_rust_bindings/src/lib.rs b/c/blake3_c_rust_bindings/src/lib.rs
index ce7185e..c2b3989 100644
--- a/c/blake3_c_rust_bindings/src/lib.rs
+++ b/c/blake3_c_rust_bindings/src/lib.rs
@@ -82,6 +82,17 @@ impl Hasher {
}
}
+ #[cfg(feature = "tbb")]
+ pub fn update_tbb(&mut self, input: &[u8]) {
+ unsafe {
+ ffi::blake3_hasher_update_tbb(
+ &mut self.0,
+ input.as_ptr() as *const c_void,
+ input.len(),
+ );
+ }
+ }
+
pub fn finalize(&self, output: &mut [u8]) {
unsafe {
ffi::blake3_hasher_finalize(&self.0, output.as_mut_ptr(), output.len());
@@ -140,6 +151,12 @@ pub mod ffi {
input: *const ::std::os::raw::c_void,
input_len: usize,
);
+ #[cfg(feature = "tbb")]
+ pub fn blake3_hasher_update_tbb(
+ self_: *mut blake3_hasher,
+ input: *const ::std::os::raw::c_void,
+ input_len: usize,
+ );
pub fn blake3_hasher_finalize(self_: *const blake3_hasher, out: *mut u8, out_len: usize);
pub fn blake3_hasher_finalize_seek(
self_: *const blake3_hasher,
diff --git a/c/blake3_c_rust_bindings/src/test.rs b/c/blake3_c_rust_bindings/src/test.rs
index 38cbd5f..6ff61ec 100644
--- a/c/blake3_c_rust_bindings/src/test.rs
+++ b/c/blake3_c_rust_bindings/src/test.rs
@@ -479,6 +479,15 @@ fn test_compare_reference_impl() {
let mut test_out = [0; OUT];
test_hasher.finalize(&mut test_out);
assert_eq!(test_out[..], expected_out[..]);
+
+ #[cfg(feature = "tbb")]
+ {
+ let mut tbb_hasher = crate::Hasher::new();
+ tbb_hasher.update_tbb(input);
+ let mut tbb_out = [0; OUT];
+ tbb_hasher.finalize(&mut tbb_out);
+ assert_eq!(tbb_out[..], expected_out[..]);
+ }
}
// keyed
@@ -493,6 +502,15 @@ fn test_compare_reference_impl() {
let mut test_out = [0; OUT];
test_hasher.finalize(&mut test_out);
assert_eq!(test_out[..], expected_out[..]);
+
+ #[cfg(feature = "tbb")]
+ {
+ let mut tbb_hasher = crate::Hasher::new_keyed(&TEST_KEY);
+ tbb_hasher.update_tbb(input);
+ let mut tbb_out = [0; OUT];
+ tbb_hasher.finalize(&mut tbb_out);
+ assert_eq!(tbb_out[..], expected_out[..]);
+ }
}
// derive_key
@@ -516,6 +534,15 @@ fn test_compare_reference_impl() {
let mut test_out_raw = [0; OUT];
test_hasher_raw.finalize(&mut test_out_raw);
assert_eq!(test_out_raw[..], expected_out[..]);
+
+ #[cfg(feature = "tbb")]
+ {
+ let mut tbb_hasher = crate::Hasher::new_derive_key(context);
+ tbb_hasher.update_tbb(input);
+ let mut tbb_out = [0; OUT];
+ tbb_hasher.finalize(&mut tbb_out);
+ assert_eq!(tbb_out[..], expected_out[..]);
+ }
}
}
}