pub struct UpdatePlan { /* private fields */ }Expand description
A compiled read-modify-write traversal for one (dims, dst_strides, src_strides) layout pair.
execute computes dest = alpha * f(src) + beta * dest by
replaying the same fused pair traversal as CopyPlan: compile proves
the layout facts once (rank agreement, extent overflow, destination
injectivity) and each call only re-checks that the supplied views carry the
compiled layout before running monomorphized loops. Execute is
allocation-free for fused ranks at most
RAW_FUSED_RANK_LIMIT, and the injective
destination makes a large replay parallel-safe exactly as in CopyPlan.
Overlapping src/dest memory is not supported, matching the rest of the
crate.
§Example
use strided_basic::{RawStridedMut, RawStridedRef, UpdatePlan};
let dims = [2usize, 2];
let dst_strides = [1isize, 2];
let src_strides = [1isize, 2];
let plan = UpdatePlan::compile(&dims, &dst_strides, &src_strides).unwrap();
let src = [1.0f64, 2.0, 3.0, 4.0];
let mut dst = [10.0f64, 20.0, 30.0, 40.0];
let src_ref = RawStridedRef::new(&src, &dims, &src_strides, 0).unwrap();
let mut dst_mut = RawStridedMut::new(&mut dst, &dims, &dst_strides, 0).unwrap();
// dst = 2 * src + 3 * dst
plan.execute(&mut dst_mut, &src_ref, 2.0, 3.0, |x| x).unwrap();
assert_eq!(dst, [32.0, 64.0, 96.0, 128.0]);Implementations§
Source§impl UpdatePlan
impl UpdatePlan
Sourcepub fn compile(
dims: &[usize],
dst_strides: &[isize],
src_strides: &[isize],
) -> Result<Self>
pub fn compile( dims: &[usize], dst_strides: &[isize], src_strides: &[isize], ) -> Result<Self>
Compile an update plan for the given layout pair.
Performs the same layout validation as CopyPlan::compile:
dims,dst_strides, andsrc_stridesmust have equal length (StridedError::StrideLengthMismatch);- the total element count must not overflow
usize(StridedError::OffsetOverflow); - the destination layout must be injective
(
StridedError::NonInjectiveOutputLayout), so two logical indices never name one slot and a parallel replay writes each slot once.
Sourcepub fn execute<T, F>(
&self,
dest: &mut RawStridedMut<'_, T>,
src: &RawStridedRef<'_, T>,
alpha: T,
beta: T,
f: F,
) -> Result<()>where
T: Copy + MaybeSendSync + Add<Output = T> + Mul<Output = T> + Zero + One + PartialEq,
F: Fn(T) -> T + MaybeSendSync,
pub fn execute<T, F>(
&self,
dest: &mut RawStridedMut<'_, T>,
src: &RawStridedRef<'_, T>,
alpha: T,
beta: T,
f: F,
) -> Result<()>where
T: Copy + MaybeSendSync + Add<Output = T> + Mul<Output = T> + Zero + One + PartialEq,
F: Fn(T) -> T + MaybeSendSync,
dest = alpha * f(src) + beta * dest.
f is applied to the source element before scaling. When beta is
zero (-0.0 included; NaN is not zero) the replay is write-only: the
old destination element is never read, so a NaN-filled or uninitialized
destination cannot contaminate the result, matching BLAS beta = 0
semantics. Otherwise the old destination element is read through the
destination layout. Allocation-free for fused ranks at most
RAW_FUSED_RANK_LIMIT.
§Errors
StridedError::PlanLayoutMismatch when the supplied views do not
carry the compiled layout, before any write.
Sourcepub fn execute_uninit<T, F>(
&self,
dest: &mut RawStridedMut<'_, MaybeUninit<T>>,
src: &RawStridedRef<'_, T>,
alpha: T,
f: F,
) -> Result<()>
pub fn execute_uninit<T, F>( &self, dest: &mut RawStridedMut<'_, MaybeUninit<T>>, src: &RawStridedRef<'_, T>, alpha: T, f: F, ) -> Result<()>
dest = alpha * f(src) into a potentially uninitialized destination.
This is execute with beta = 0: the destination is
never read. On success every reachable logical destination element is
initialized; non-reachable holes in the backing allocation are not
written. Allocation-free for fused ranks at most
RAW_FUSED_RANK_LIMIT.
§Errors
StridedError::PlanLayoutMismatch when the supplied views do not
carry the compiled layout, before any write.
§Examples
use core::mem::MaybeUninit;
use strided_basic::{RawStridedMut, RawStridedRef, UpdatePlan};
let dims = [2usize, 2];
let strides = [1isize, 2];
let plan = UpdatePlan::compile(&dims, &strides, &strides).unwrap();
let src = [1.0f64, 2.0, 3.0, 4.0];
let mut storage = [MaybeUninit::<f64>::uninit(); 4];
let mut dst = RawStridedMut::new(&mut storage, &dims, &strides, 0).unwrap();
let source = RawStridedRef::new(&src, &dims, &strides, 0).unwrap();
// dst = 2 * src
plan.execute_uninit(&mut dst, &source, 2.0, |x| x).unwrap();
drop(dst);
// SAFETY: every reachable destination slot was initialized above.
let values: Vec<f64> = storage.iter().map(|v| unsafe { v.assume_init() }).collect();
assert_eq!(values, [2.0, 4.0, 6.0, 8.0]);