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::{Exec, 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, Exec::serial()).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<UpdatePlan, StridedError>
pub fn compile( dims: &[usize], dst_strides: &[isize], src_strides: &[isize], ) -> Result<UpdatePlan, StridedError>
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,
exec: Exec<'_>,
) -> Result<(), StridedError>
pub fn execute<T, F>( &self, dest: &mut RawStridedMut<'_, T>, src: &RawStridedRef<'_, T>, alpha: T, beta: T, f: F, exec: Exec<'_>, ) -> Result<(), StridedError>
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,
exec: Exec<'_>,
) -> Result<(), StridedError>
pub fn execute_uninit<T, F>( &self, dest: &mut RawStridedMut<'_, MaybeUninit<T>>, src: &RawStridedRef<'_, T>, alpha: T, f: F, exec: Exec<'_>, ) -> Result<(), StridedError>
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::{Exec, 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, Exec::serial()).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]);Trait Implementations§
Source§impl Clone for UpdatePlan
impl Clone for UpdatePlan
Source§fn clone(&self) -> UpdatePlan
fn clone(&self) -> UpdatePlan
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for UpdatePlan
impl RefUnwindSafe for UpdatePlan
impl Send for UpdatePlan
impl Sync for UpdatePlan
impl Unpin for UpdatePlan
impl UnsafeUnpin for UpdatePlan
impl UnwindSafe for UpdatePlan
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more