use std::hint::black_box;
use strided_basic::{
copy_into, map_into, with_execution_policy, ErasedRawStridedMut, ErasedRawStridedRef,
ErasedUpdatePlan, ExecContext, ExecutionPolicy, KernelDType, RawStridedMut, RawStridedRef,
StridedArray, StridedView, StridedViewMut, UpdateOp, UpdatePlan,
};
#[path = "support/mod.rs"]
mod support;
#[global_allocator]
static GLOBAL: support::CountingAllocator = support::CountingAllocator;
use support::{measure_case, print_table, CaseResult};
fn col_major_strides(dims: &[usize]) -> Vec<isize> {
let mut strides = Vec::with_capacity(dims.len());
let mut stride = 1isize;
for &dim in dims {
strides.push(stride);
stride *= dim as isize;
}
strides
}
#[derive(Clone, Copy)]
enum S3Baseline {
TypedUpdatePlan,
ErasedUpdatePlan,
}
fn s3_case(
dims: &[usize],
label: &'static str,
iterations: usize,
baseline: S3Baseline,
threshold: Option<f64>,
) -> CaseResult {
let len: usize = dims.iter().product();
let src_data: Vec<f64> = (0..len).map(|value| value as f64 + 1.0).collect();
let strides = col_major_strides(dims);
let src = StridedArray::from_parts(src_data.clone(), dims, &strides, 0).unwrap();
let mut dst = StridedArray::<f64>::col_major(dims);
let src_view = src.view();
let mut dst_view = dst.view_mut();
match baseline {
S3Baseline::TypedUpdatePlan => {
let mut raw_dst = vec![0.0f64; len];
let plan = UpdatePlan::compile(dims, &strides, &strides).unwrap();
let src_ref = RawStridedRef::new(&src_data, dims, &strides, 0).unwrap();
let mut dst_ref = RawStridedMut::new(&mut raw_dst, dims, &strides, 0).unwrap();
measure_case(
label,
"map_into per call vs compiled typed UpdatePlan",
iterations,
threshold,
|| {
map_into(&mut dst_view, &src_view, |value| value).unwrap();
black_box(dst_view.as_mut_ptr());
},
|| {
plan.execute(&mut dst_ref, &src_ref, 1.0, 0.0, |value| value)
.unwrap();
black_box(dst_ref.dims());
},
)
}
S3Baseline::ErasedUpdatePlan => {
let mut raw_dst = vec![0.0f64; len];
let plan =
ErasedUpdatePlan::compile(KernelDType::F64, dims, &strides, &strides).unwrap();
let src_ref = ErasedRawStridedRef::from_slice(&src_data, dims, &strides, 0).unwrap();
let mut dst_ref =
ErasedRawStridedMut::from_slice_mut(&mut raw_dst, dims, &strides, 0).unwrap();
let ctx = ExecContext::serial();
measure_case(
label,
"map_into per call vs compiled ErasedUpdatePlan",
iterations,
threshold,
|| {
map_into(&mut dst_view, &src_view, |value| value).unwrap();
black_box(dst_view.as_mut_ptr());
},
|| {
plan.execute(&ctx, &mut dst_ref, &src_ref, 1.0, 0.0, UpdateOp::Identity)
.unwrap();
black_box(dst_ref.dims());
},
)
}
}
}
fn s4_case(
dims: &[usize],
permuted_strides: &[isize],
label: &'static str,
iterations: usize,
) -> CaseResult {
let len: usize = dims.iter().product();
let src_data: Vec<f64> = (0..len).map(|value| value as f64 + 1.0).collect();
let contiguous = col_major_strides(dims);
let mut contiguous_dst = vec![0.0f64; len];
let mut permuted_dst = vec![0.0f64; len];
let permuted_src = StridedView::<f64>::new(&src_data, dims, permuted_strides, 0).unwrap();
let contiguous_src = StridedView::<f64>::new(&src_data, dims, &contiguous, 0).unwrap();
let mut permuted_out =
StridedViewMut::<f64>::new(&mut permuted_dst, dims, &contiguous, 0).unwrap();
let mut contiguous_out =
StridedViewMut::<f64>::new(&mut contiguous_dst, dims, &contiguous, 0).unwrap();
measure_case(
label,
"permuted copy_into vs contiguous copy_into",
iterations,
None,
|| {
copy_into(&mut permuted_out, &permuted_src).unwrap();
black_box(permuted_out.as_mut_ptr());
},
|| {
copy_into(&mut contiguous_out, &contiguous_src).unwrap();
black_box(contiguous_out.as_mut_ptr());
},
)
}
fn main() {
let cases = with_execution_policy(ExecutionPolicy::Sequential, || {
vec![
s3_case(&[16], "S3a", 20_000, S3Baseline::TypedUpdatePlan, Some(2.5)),
s3_case(
&[4, 4, 4],
"S3b",
10_000,
S3Baseline::TypedUpdatePlan,
Some(4.0),
),
s3_case(&[16], "S3c", 20_000, S3Baseline::ErasedUpdatePlan, None),
s3_case(
&[4, 4, 4],
"S3d",
10_000,
S3Baseline::ErasedUpdatePlan,
None,
),
s4_case(&[8, 8, 8], &[64, 8, 1], "S4a", 2_000),
s4_case(&[32, 32, 32], &[1024, 32, 1], "S4b", 200),
]
});
print_table(&cases, "### strided-basic overhead smoke");
support::exit_if_failed(&cases);
}