pub trait CompareExchangeEpsilonOps<T: ElementComparePartialEqOps>: LamellarArrayPrivate<T> {
// Provided methods
fn compare_exchange_epsilon<'a>(
&self,
index: usize,
current: T,
new: T,
eps: T,
) -> ArrayResultOpHandle<T> ⓘ { ... }
fn batch_compare_exchange_epsilon<'a>(
&self,
index: impl OpInput<'a, usize>,
current: T,
new: impl OpInput<'a, T>,
eps: T,
) -> ArrayResultBatchOpHandle<T> ⓘ { ... }
}Expand description
The interface for performing remote compare and exchange operations within a given epsilon on array elements
Useful for element types that only impl PartialEq instead of Eq (e.g f32,f64).
These operations can be performed using any safe LamellarWriteArray type for UnsafeArrays please see UnsafeCompareExchangeOps instead.
Both single element operations and batched element operations are provided
Generally if you are performing a large number of operations it will be better to use a batched version instead of multiple single element opertations. While the Runtime internally performs message aggregation for both single element and batched operations, single element operates have to be treated as individual requests, resulting in allocation and bookkeeping overheads. A single batched call on the other hand is treated as a single request by the runtime. (See ReadOnlyOps for an example comparing single vs batched load operations of a list of indices)
The results of a batched operation are returned to the user in the same order as the input indices.
§One-sided Operation
performing either single or batched operations are both one-sided, with the calling PE performing any necessary work to initate and execute active messages that are sent to remote PEs. For Ops that return results, the result will only be available on the calling PE.
§Note
For both single index and batched operations there are no guarantees to the order in which individual operations occur (an individal operation is guaranteed to be atomic though).
§Batched Types
Three types of batched operations can be performed
Currently only the indicies and new values can be batched, for all the batch types below you can only pass a single current val and a single epsilon which will be used in each individual operation of the batch
We plan to support batched current vals and epsilons in a future release.
§One Value - Many Indicies
In this type, the same value will be applied to the provided indices
use lamellar::array::prelude::*;
let world = LamellarWorldBuilder::new().build();
let array = AtomicArray::<f32>::new(&world,100,Distribution::Block).block();
let indices = vec![3,54,11,88,29,68];
let current = 0.0;
let new = 10.5;
let epsilon = 0.1;
array.batch_compare_exchange_epsilon(indices,current,new,epsilon).block();§Many Values - One Index
In this type, multiple values will be applied to the given index
use lamellar::array::prelude::*;
let world = LamellarWorldBuilder::new().build();
let array = AtomicArray::<f32>::new(&world,100,Distribution::Block).block();
let new_vals = vec![3.0,54.8,12.9,88.1,29.2,68.9];
let current = 0.0;
let index = 10;
let epsilon = 0.1;
array.batch_compare_exchange_epsilon(index,current,new_vals,epsilon).block();§Many Values - Many Indicies
In this type, values and indices have a one-to-one correspondance.
If the two lists are unequal in length, the longer of the two will be truncated so that it matches the length of the shorter
use lamellar::array::prelude::*;
let world = LamellarWorldBuilder::new().build();
let array = AtomicArray::<f32>::new(&world,100,Distribution::Block).block();
let indices = vec![3,54,12,88,29,68];
let new_vals = vec![12.1,2.321,1.7,10000.0,12.4,13.7];
let current = 0.0;
let epsilon = 0.1;
array.batch_compare_exchange_epsilon(indices,current,new_vals,epsilon).block();Provided Methods§
Sourcefn compare_exchange_epsilon<'a>(
&self,
index: usize,
current: T,
new: T,
eps: T,
) -> ArrayResultOpHandle<T> ⓘ
fn compare_exchange_epsilon<'a>( &self, index: usize, current: T, new: T, eps: T, ) -> ArrayResultOpHandle<T> ⓘ
This call stores the new value into the element specified by index if the current value is the same as current plus or minus epslion.
e.g. if current - epsilon < array[index] && array[index] < current + epsilon { array[index] = new }
The return value is a result indicating whether the new value was written into the element and contains the previous value.
On success this previous value is gauranteed to be within epsilon of current
A future is returned as the result of this call, which is used to detect when the operation has completed and retrieve the returned value.
§Note
This future is only lazy with respect to checking for completion, not with respect to launching the operation. That is, the operation will occur regardless of if the future is ever polled or not, Enabling a “fire and forget” programming model.
§Examples
use lamellar::array::prelude::*;
let world = LamellarWorldBuilder::new().build();
let array = AtomicArray::<f32>::new(&world,100,Distribution::Block).block();
let idx = 53;
let val = 10.3;
let current = 0.0;
let epsilon = 0.1;
let req = array.compare_exchange_epsilon(idx,current,val,epsilon);
let result = req.block();Sourcefn batch_compare_exchange_epsilon<'a>(
&self,
index: impl OpInput<'a, usize>,
current: T,
new: impl OpInput<'a, T>,
eps: T,
) -> ArrayResultBatchOpHandle<T> ⓘ
fn batch_compare_exchange_epsilon<'a>( &self, index: impl OpInput<'a, usize>, current: T, new: impl OpInput<'a, T>, eps: T, ) -> ArrayResultBatchOpHandle<T> ⓘ
This call performs a batched vesion of the compare_exchange_epsilon function,
Instead of a single value and index this function expects a list of (new)vals, or a list of indices or both.
Note that presently only a single current value and a single epsilon value can be provided, and they will be used for all operations in the batch.
Please see the general CompareExchangeEpsilonOps documentation for more information on batch operation input
A future is returned as the result of this call, which is used to retrieve the results after the (possibly remote) operations have finished.
§Note
This future is only lazy with respect to checking for completion, not with respect to launching the operation. That is, the operation will occur regardless of if the future is ever polled or not, Enabling a “fire and forget” programming model.
§Examples
use lamellar::array::prelude::*;
let world = LamellarWorldBuilder::new().build();
let array = AtomicArray::<f32>::new(&world,100,Distribution::Block).block();
let indices = vec![3,54,12,88,29,68];
let current = 0.0;
let epsilon = 0.001;
let req = array.batch_compare_exchange_epsilon(indices,current,10.321,epsilon);
let results = req.block();Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".