initial record
[?]
2paXZqkGuqYVrdei2n8ZVCtynbH1mwewHrmi87LA9cto
Jan 19, 2022, 11:40 PM
VONQCLSVYJXL6KNNKFKZS53626BSQYKIXUDDPWCEDOCLUQOW3TPQCDependencies
- [2]
LDHPW77N
Change contents
- file addition: src[2.1]
- file addition: lib.rs[0.15]
use rayon::prelude::*;#[inline(always)]fn validate_bounds<T>(vs: &[T], indices: &[usize]) -> bool {let size = vs.len();indices.par_iter().any(|i| *i >= size)}#[derive(Copy, Clone)]struct TmpRef<T: Send + Sync>(*mut T);unsafe impl<T: Send + Sync> Send for TmpRef<T> {}unsafe impl<T: Sync + Send> Sync for TmpRef<T> {}/// Write `value` into `slice` with the given `indices` in parallelpub fn writes_par<T: Copy + Send + Sync>(slice: &mut [T], value: T, indices: &[usize]) -> bool {let oob = validate_bounds(slice, indices);if oob {return false;}let tref = TmpRef(slice.as_mut_ptr());indices.par_iter().for_each(move |i| {let tmp = tref.clone();unsafe {let p = tmp.0.add(*i);p.write(value);}});true}/// Write `value` into `slice` with the given `indices` in parallel, discarding/// the writes for any out of bound indexespub fn writes_par_discard<T: Copy + Send + Sync>(slice: &mut [T], value: T, indices: &[usize]) {let size = slice.len();let tref = TmpRef(slice.as_mut_ptr());indices.par_iter().for_each(move |i| {if *i < size {let tmp = tref.clone();unsafe {let p = tmp.0.add(*i);p.write(value);}}});} - file addition: benches[2.1]
- file addition: main.rs[0.1409]
use criterion::{black_box, criterion_group, criterion_main, Criterion};use slicefire::*;/// Sequentially write `value` into `slice` with the given `indices`pub fn writes<T: Copy>(slice: &mut [T], value: T, indices: &[usize]) -> bool {for i in indices {if *i >= slice.len() {return false;}}for i in indices {slice[*i] = value;}true}/// Sequentially write `value` into `slice` with the given `indices`, discarding/// the writes for any out of bound indexespub fn writes_discard<T: Copy>(vs: &mut [T], val: T, indices: &[usize]) {for i in indices {if *i < vs.len() {vs[*i] = val;}}}#[derive(Debug, Copy, Clone)]#[allow(unused)]struct Foo {x: i32,y: i64,}impl From<i32> for Foo {fn from(x: i32) -> Self {Self { x, y: x as i64 * 2 }}}fn indices(size: usize) -> (Vec<usize>, Vec<Foo>) {let indices = (0..(size)).map(|i| i % (size - 2)).collect::<Vec<usize>>();let vs = (0..size).map(|v| (v as i32).into()).collect::<Vec<Foo>>();(indices, vs)}fn write_single_value_with_size(size: usize, c: &mut Criterion) {let (indices, mut vs) = indices(size);let val = black_box(Foo::from(10));c.bench_function(&format!("writes {}", size), |b| {b.iter(|| writes(&mut vs, black_box(val), &indices))});c.bench_function(&format!("writes_discard {}", size), |b| {b.iter(|| writes_discard(&mut vs, black_box(val), &indices))});c.bench_function(&format!("writes_par {}", size), |b| {b.iter(|| writes_par(&mut vs, black_box(val), &indices))});c.bench_function(&format!("writes_par_discard {}", size), |b| {b.iter(|| writes_par_discard(&mut vs, black_box(val), &indices))});}fn write_values_with_size(size: usize, c: &mut Criterion) {let (indices, mut vs) = indices(size);let vals = (0..20).map(|v| v.into()).collect::<Vec<Foo>>();let vals = &vals;c.bench_function(&format!("writes vals {}", size), |b| {b.iter(|| {for val in vals {writes(&mut vs, black_box(*val), &indices);}})});c.bench_function(&format!("write_discards vals {}", size), |b| {b.iter(|| {for val in vals {writes_discard(&mut vs, black_box(*val), &indices);}})});c.bench_function(&format!("writes_par vals {}", size), |b| {b.iter(|| {for val in vals {writes_par(&mut vs, black_box(*val), &indices);}})});c.bench_function(&format!("writes_par_discard vals {}", size), |b| {b.iter(|| {for val in vals {writes_par_discard(&mut vs, black_box(*val), &indices);}})});}fn write_values(c: &mut Criterion) {write_values_with_size(1_000, c);write_values_with_size(10_000, c);write_values_with_size(100_000, c);}fn write_single_value(c: &mut Criterion) {write_single_value_with_size(1_000, c);write_single_value_with_size(10_000, c);write_single_value_with_size(100_000, c);}criterion_group!(benches, write_single_value, write_values);criterion_main!(benches); - file addition: Cargo.toml[2.1]
[package]name = "slicefire"version = "0.1.0"edition = "2021"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies]rayon = "1.5.1"[dev-dependencies]criterion = { version = "0.3", features = ["html_reports"]}[[bench]]name = "main"harness = false