Struct mpi::datatype::UserDatatype
source · pub struct UserDatatype(/* private fields */);
Expand description
Implementations§
source§impl UserDatatype
impl UserDatatype
sourcepub fn contiguous<D>(count: Count, oldtype: &D) -> UserDatatypewhere
D: UncommittedDatatype,
pub fn contiguous<D>(count: Count, oldtype: &D) -> UserDatatypewhere
D: UncommittedDatatype,
Constructs a new datatype by concatenating count
repetitions of oldtype
§Examples
See examples/contiguous.rs
§Standard section(s)
4.1.2
Examples found in repository?
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
fn main() {
let universe = mpi::initialize().unwrap();
let world = universe.world();
let rank = world.rank();
let size = world.size();
let next_rank = (rank + 1) % size;
let next_process = world.process_at_rank(next_rank);
let previous_rank = (rank - 1 + size) % size;
let previous_process = world.process_at_rank(previous_rank);
let b1 = (1..).map(|x| rank * x).take(3).collect::<Vec<_>>();
let mut b2 = std::iter::repeat(-1).take(3).collect::<Vec<_>>();
println!("Rank {} sending message: {:?}.", rank, b1);
world.barrier();
let t = UserDatatype::contiguous(3, &Rank::equivalent_datatype());
let status;
{
let v1 = unsafe { View::with_count_and_datatype(&b1[..], 1, &t) };
let mut v2 = unsafe { MutView::with_count_and_datatype(&mut b2[..], 1, &t) };
status = p2p::send_receive_into(&v1, &next_process, &mut v2, &previous_process);
}
println!(
"Rank {} received message: {:?}, status: {:?}.",
rank, b2, status
);
world.barrier();
let b3 = (1..).map(|x| previous_rank * x).take(3).collect::<Vec<_>>();
assert_eq!(b3, b2);
}
More examples
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
fn main() {
let universe = mpi::initialize().unwrap();
let world = universe.world();
let root_rank = 0;
let count = world.size() as usize;
let i = 2_u64.pow(world.rank() as u32 + 1);
let mut a = vec![0u64; count];
world.all_gather_into(&i, &mut a[..]);
if world.rank() == root_rank {
println!("Root gathered sequence: {:?}.", a);
}
assert!(a
.iter()
.enumerate()
.all(|(a, &b)| b == 2u64.pow(a as u32 + 1)));
let factor = world.rank() as u64 + 1;
let a = (1_u64..)
.take(count)
.map(|x| x * factor)
.collect::<Vec<_>>();
let mut t = vec![0u64; count * count];
world.all_gather_into(&a[..], &mut t[..]);
if world.rank() == root_rank {
println!("Root gathered table:");
for r in t.chunks(count) {
println!("{:?}", r);
}
}
assert!((0_u64..)
.zip(t.iter())
.all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
let d = UserDatatype::contiguous(count as Count, &u64::equivalent_datatype());
t = vec![0u64; count * count];
{
let sv = unsafe { View::with_count_and_datatype(&a[..], 1, &d) };
let mut rv = unsafe { MutView::with_count_and_datatype(&mut t[..], count as Count, &d) };
world.all_gather_into(&sv, &mut rv);
}
if world.rank() == root_rank {
println!("Root gathered table:");
for r in t.chunks(count) {
println!("{:?}", r);
}
}
assert!((0_u64..)
.zip(t.iter())
.all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
}
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
fn main() {
let universe = mpi::initialize().unwrap();
let world = universe.world();
let root_rank = 0;
let count = world.size() as usize;
let i = 2_u64.pow(world.rank() as u32 + 1);
let mut a = vec![0u64; count];
mpi::request::scope(|scope| {
world
.immediate_all_gather_into(scope, &i, &mut a[..])
.wait();
});
if world.rank() == root_rank {
println!("Root gathered sequence: {:?}.", a);
}
assert!(a
.iter()
.enumerate()
.all(|(a, &b)| b == 2u64.pow(a as u32 + 1)));
let factor = world.rank() as u64 + 1;
let a = (1_u64..)
.take(count)
.map(|x| x * factor)
.collect::<Vec<_>>();
let mut t = vec![0u64; count * count];
mpi::request::scope(|scope| {
world
.immediate_all_gather_into(scope, &a[..], &mut t[..])
.wait();
});
if world.rank() == root_rank {
println!("Root gathered table:");
for r in t.chunks(count) {
println!("{:?}", r);
}
}
assert!((0_u64..)
.zip(t.iter())
.all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
let d = UserDatatype::contiguous(count as Count, &u64::equivalent_datatype());
t = vec![0u64; count * count];
{
let sv = unsafe { View::with_count_and_datatype(&a[..], 1, &d) };
let mut rv = unsafe { MutView::with_count_and_datatype(&mut t[..], count as Count, &d) };
mpi::request::scope(|scope| {
world.immediate_all_gather_into(scope, &sv, &mut rv).wait();
});
}
if world.rank() == root_rank {
println!("Root gathered table:");
for r in t.chunks(count) {
println!("{:?}", r);
}
}
assert!((0_u64..)
.zip(t.iter())
.all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
}
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
fn main() {
let universe = mpi::initialize().unwrap();
let world = universe.world();
let root_rank = 0;
let root_process = world.process_at_rank(root_rank);
let count = world.size() as usize;
let i = 2_u64.pow(world.rank() as u32 + 1);
if world.rank() == root_rank {
let mut a = vec![0u64; count];
root_process.gather_into_root(&i, &mut a[..]);
println!("Root gathered sequence: {:?}.", a);
assert!(a
.iter()
.enumerate()
.all(|(a, &b)| b == 2u64.pow(a as u32 + 1)));
} else {
root_process.gather_into(&i);
}
let factor = world.rank() as u64 + 1;
let a = (1_u64..)
.take(count)
.map(|x| x * factor)
.collect::<Vec<_>>();
if world.rank() == root_rank {
let mut t = vec![0u64; count * count];
root_process.gather_into_root(&a[..], &mut t[..]);
println!("Root gathered table:");
for r in t.chunks(count) {
println!("{:?}", r);
}
assert!((0_u64..)
.zip(t.iter())
.all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
} else {
root_process.gather_into(&a[..]);
}
let d = UserDatatype::contiguous(count as Count, &u64::equivalent_datatype());
let sv = unsafe { View::with_count_and_datatype(&a[..], 1, &d) };
if world.rank() == root_rank {
let mut t = vec![0u64; count * count];
{
let mut rv =
unsafe { MutView::with_count_and_datatype(&mut t[..], count as Count, &d) };
root_process.gather_into_root(&sv, &mut rv);
}
println!("Root gathered table:");
for r in t.chunks(count) {
println!("{:?}", r);
}
assert!((0_u64..)
.zip(t.iter())
.all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
} else {
root_process.gather_into(&sv);
}
}
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
fn main() {
let universe = mpi::initialize().unwrap();
let world = universe.world();
let root_rank = 0;
let root_process = world.process_at_rank(root_rank);
let count = world.size() as usize;
let i = 2_u64.pow(world.rank() as u32 + 1);
if world.rank() == root_rank {
let mut a = vec![0u64; count];
mpi::request::scope(|scope| {
root_process
.immediate_gather_into_root(scope, &i, &mut a[..])
.wait();
});
println!("Root gathered sequence: {:?}.", a);
assert!(a
.iter()
.enumerate()
.all(|(a, &b)| b == 2u64.pow(a as u32 + 1)));
} else {
mpi::request::scope(|scope| {
root_process.immediate_gather_into(scope, &i).wait();
});
}
let factor = world.rank() as u64 + 1;
let a = (1_u64..)
.take(count)
.map(|x| x * factor)
.collect::<Vec<_>>();
if world.rank() == root_rank {
let mut t = vec![0u64; count * count];
mpi::request::scope(|scope| {
root_process
.immediate_gather_into_root(scope, &a[..], &mut t[..])
.wait();
});
println!("Root gathered table:");
for r in t.chunks(count) {
println!("{:?}", r);
}
assert!((0_u64..)
.zip(t.iter())
.all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
} else {
mpi::request::scope(|scope| {
root_process.immediate_gather_into(scope, &a[..]).wait();
});
}
let d = UserDatatype::contiguous(count as Count, &u64::equivalent_datatype());
let sv = unsafe { View::with_count_and_datatype(&a[..], 1, &d) };
if world.rank() == root_rank {
let mut t = vec![0u64; count * count];
{
let mut rv =
unsafe { MutView::with_count_and_datatype(&mut t[..], count as Count, &d) };
mpi::request::scope(|scope| {
root_process
.immediate_gather_into_root(scope, &sv, &mut rv)
.wait();
});
}
println!("Root gathered table:");
for r in t.chunks(count) {
println!("{:?}", r);
}
assert!((0_u64..)
.zip(t.iter())
.all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
} else {
mpi::request::scope(|scope| {
root_process.immediate_gather_into(scope, &sv).wait();
});
}
}
sourcepub fn vector<D>(
count: Count,
blocklength: Count,
stride: Count,
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
pub fn vector<D>(
count: Count,
blocklength: Count,
stride: Count,
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
Construct a new datatype out of count
blocks of blocklength
elements of oldtype
concatenated with the start of consecutive blocks placed stride
elements apart.
§Examples
See examples/vector.rs
§Standard section(s)
4.1.2
Examples found in repository?
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
fn main() {
let universe = mpi::initialize().unwrap();
let world = universe.world();
let rank = world.rank();
let size = world.size();
let next_rank = (rank + 1) % size;
let next_process = world.process_at_rank(next_rank);
let previous_rank = (rank - 1 + size) % size;
let previous_process = world.process_at_rank(previous_rank);
let b1 = (1..).map(|x| rank * x).take(6).collect::<Vec<_>>();
let mut b2 = std::iter::repeat(-1).take(6).collect::<Vec<_>>();
println!("Rank {} sending message: {:?}.", rank, b1);
world.barrier();
let t = UserDatatype::vector(2, 2, 3, &Rank::equivalent_datatype());
let status;
{
let v1 = unsafe { View::with_count_and_datatype(&b1[..], 1, &t) };
let mut v2 = unsafe { MutView::with_count_and_datatype(&mut b2[..], 1, &t) };
status = p2p::send_receive_into(&v1, &next_process, &mut v2, &previous_process);
}
println!(
"Rank {} received message: {:?}, status: {:?}.",
rank, b2, status
);
world.barrier();
let b3 = (1..)
.map(|x| if x % 3 == 0 { -1 } else { previous_rank * x })
.take(6)
.collect::<Vec<_>>();
assert_eq!(b3, b2);
}
sourcepub fn heterogeneous_vector<D>(
count: Count,
blocklength: Count,
stride: Address,
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
pub fn heterogeneous_vector<D>(
count: Count,
blocklength: Count,
stride: Address,
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
Like vector()
but stride
is given in bytes rather than elements of oldtype
.
§Standard section(s)
4.1.2
sourcepub fn indexed<D>(
blocklengths: &[Count],
displacements: &[Count],
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
pub fn indexed<D>(
blocklengths: &[Count],
displacements: &[Count],
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
Constructs a new type out of multiple blocks of individual length and displacement.
Block i
will be blocklengths[i]
items of datytpe oldtype
long and displaced by
dispplacements[i]
items of the oldtype
.
§Standard section(s)
4.1.2
sourcepub fn heterogeneous_indexed<D>(
blocklengths: &[Count],
displacements: &[Address],
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
pub fn heterogeneous_indexed<D>(
blocklengths: &[Count],
displacements: &[Address],
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
Constructs a new type out of multiple blocks of individual length and displacement.
Block i
will be blocklengths[i]
items of datytpe oldtype
long and displaced by
dispplacements[i]
bytes.
§Standard section(s)
4.1.2
sourcepub fn indexed_block<D>(
blocklength: Count,
displacements: &[Count],
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
pub fn indexed_block<D>(
blocklength: Count,
displacements: &[Count],
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
Construct a new type out of blocks of the same length and individual displacements.
§Standard section(s)
4.1.2
sourcepub fn heterogeneous_indexed_block<D>(
blocklength: Count,
displacements: &[Address],
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
pub fn heterogeneous_indexed_block<D>(
blocklength: Count,
displacements: &[Address],
oldtype: &D
) -> UserDatatypewhere
D: UncommittedDatatype,
Construct a new type out of blocks of the same length and individual displacements. Displacements are in bytes.
§Standard section(s)
4.1.2
sourcepub fn structured<D>(
blocklengths: &[Count],
displacements: &[Address],
types: &[D]
) -> UserDatatype
pub fn structured<D>( blocklengths: &[Count], displacements: &[Address], types: &[D] ) -> UserDatatype
Constructs a new datatype out of blocks of different length, displacement and datatypes
§Examples
See examples/structured.rs
§Standard section(s)
4.1.2
Examples found in repository?
10 11 12 13 14 15 16 17 18 19 20 21
fn equivalent_datatype() -> Self::Out {
UserDatatype::structured(
&[1, 1, 1],
&[
// Order the logical fields in reverse of their storage order
(size_of::<i32>() * 2) as mpi::Address,
size_of::<i32>() as mpi::Address,
0,
],
&[i32::equivalent_datatype(); 3],
)
}
More examples
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn equivalent_datatype() -> Self::Out {
UserDatatype::structured(
&[1, 1, 1],
&[
offset_of!(ComplexDatatype, b) as Address,
offset_of!(ComplexDatatype, ints) as Address,
offset_of!(ComplexDatatype, tuple) as Address,
],
&[
bool::equivalent_datatype().into(),
UncommittedUserDatatype::contiguous(4, &i32::equivalent_datatype()).as_ref(),
UncommittedUserDatatype::structured(
&[2, 1],
&[
offset_of!(TupleType, 0) as Address,
offset_of!(TupleType, 1) as Address,
],
&[f32::equivalent_datatype(), u8::equivalent_datatype()],
)
.as_ref(),
],
)
}
sourcepub fn as_ref(&self) -> DatatypeRef<'_>
pub fn as_ref(&self) -> DatatypeRef<'_>
Creates a DatatypeRef from this datatype object.
Examples found in repository?
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
fn main() {
let universe = mpi::initialize().unwrap();
let world = universe.world();
let root_process = world.process_at_rank(0);
let int_type = i32::equivalent_datatype().dup();
let mut ints = if world.rank() == 0 {
[1i32, 2, 3, 4]
} else {
[0, 0, 0, 0]
};
let mut buffer =
unsafe { DynBufferMut::from_raw(ints.as_mut_ptr(), ints.count(), int_type.as_ref()) };
root_process.broadcast_into(&mut buffer);
assert_eq!([1, 2, 3, 4], ints);
}