use futures_util::stream::FuturesOrdered;
use tracing::trace;
use crate::{
array::{
private::LamellarArrayPrivate,
r#unsafe::*,
rdma::private::{LamellarRdmaGet, LamellarRdmaPut, Sealed},
*,
},
lamellae::{RdmaGetBufferHandle, RdmaGetIntoBufferHandle},
memregion::{
AsLamellarBuffer, Dist, LamellarBuffer, MemregionRdmaInput, MemregionRdmaInputInner,
},
RdmaHandle,
};
impl<T: Dist> UnsafeArray<T> {
fn rdma_block_put<U: Into<MemregionRdmaInputInner<T>>>(
&self,
index: usize, buf: U,
unmanaged: bool,
) -> Vec<RdmaHandle<T>> {
let global_index = index + self.inner.offset;
let buf = buf.into();
let start_pe = match self.inner.pe_for_dist_index(index) {
Some(pe) => pe,
None => panic!("index out of bounds {:?} len {:?}", index, self.len()),
};
let end_pe = match self.inner.pe_for_dist_index(index + buf.len() - 1) {
Some(pe) => pe,
None => panic!(
"index out of bounds {:?} len {:?}",
index + buf.len() - 1,
self.len()
),
};
let mut dist_index = global_index;
let mut buf_index = 0;
let mut rdma_requests = Vec::new();
for pe in start_pe..=end_pe {
let mut full_num_elems_on_pe = self.inner.orig_elem_per_pe;
if pe < self.inner.orig_remaining_elems {
full_num_elems_on_pe += 1;
}
let pe_full_start_index = self.inner.global_start_index_for_pe(pe);
let offset = dist_index - pe_full_start_index;
let len = std::cmp::min(full_num_elems_on_pe - offset, buf.len() - buf_index);
if len > 0 {
unsafe {
if unmanaged {
self.mem_region.put_buffer_unmanaged(
pe,
offset,
buf.sub_region(buf_index..(buf_index + len)),
);
} else {
rdma_requests.push(self.mem_region.put_buffer(
pe,
offset,
buf.sub_region(buf_index..(buf_index + len)),
))
}
};
buf_index += len;
dist_index += len;
}
}
rdma_requests
}
fn rdma_block_get_buffer(
&self,
index: usize, num_elems: usize,
) -> FuturesOrdered<RdmaGetBufferHandle<T>> {
trace!("rdma_block_get_buffer index {index} num_elems {num_elems}");
let global_index = index + self.inner.offset;
let start_pe = match self.inner.pe_for_dist_index(index) {
Some(pe) => pe,
None => panic!("index out of bounds {:?} len {:?}", index, self.len()),
};
let end_pe = match self.inner.pe_for_dist_index(index + num_elems - 1) {
Some(pe) => pe,
None => panic!(
"index out of bounds {:?} len {:?}",
index + num_elems - 1,
self.len()
),
};
let mut dist_index = global_index;
let mut buf_index = 0;
let mut rdma_requests = FuturesOrdered::new();
trace!("rdma_block_get_buffer start pe {start_pe} end pe {end_pe}");
for pe in start_pe..=end_pe {
let mut full_num_elems_on_pe = self.inner.orig_elem_per_pe;
if pe < self.inner.orig_remaining_elems {
full_num_elems_on_pe += 1;
}
let pe_full_start_index = self.inner.global_start_index_for_pe(pe);
let offset = dist_index - pe_full_start_index;
let len = std::cmp::min(full_num_elems_on_pe - offset, num_elems - buf_index);
if len > 0 {
unsafe { rdma_requests.push_back(self.mem_region.get_buffer(pe, offset, len)) };
buf_index += len;
dist_index += len;
}
}
rdma_requests
}
fn rdma_block_get_into_buffer<B: AsLamellarBuffer<T>>(
&self,
index: usize, mut dst: LamellarBuffer<T, B>,
) -> FuturesOrdered<RdmaGetIntoBufferHandle<T, B>> {
let global_index = index + self.inner.offset;
let start_pe = match self.inner.pe_for_dist_index(index) {
Some(pe) => pe,
None => panic!("index out of bounds {:?} len {:?}", index, self.len()),
};
let end_pe = match self.inner.pe_for_dist_index(index + dst.len() - 1) {
Some(pe) => pe,
None => panic!(
"index out of bounds {:?} len {:?}",
index + dst.len() - 1,
self.len()
),
};
let mut dist_index = global_index;
let mut buf_index = 0;
let mut rdma_requests = FuturesOrdered::new();
let orig_len = dst.len();
for pe in start_pe..=end_pe {
let mut full_num_elems_on_pe = self.inner.orig_elem_per_pe;
if pe < self.inner.orig_remaining_elems {
full_num_elems_on_pe += 1;
}
let pe_full_start_index = self.inner.global_start_index_for_pe(pe);
let offset = dist_index - pe_full_start_index;
let len = std::cmp::min(full_num_elems_on_pe - offset, orig_len - buf_index);
if len > 0 {
let dsts = dst.split(len);
dst = dsts.1;
unsafe {
rdma_requests.push_back(self.mem_region.get_into_buffer(pe, offset, dsts.0))
};
buf_index += len;
dist_index += len;
}
}
rdma_requests
}
fn rdma_block_get_into_buffer_unmanaged<B: AsLamellarBuffer<T>>(
&self,
index: usize, mut dst: LamellarBuffer<T, B>,
) {
let global_index = index + self.inner.offset;
let start_pe = match self.inner.pe_for_dist_index(index) {
Some(pe) => pe,
None => panic!("index out of bounds {:?} len {:?}", index, self.len()),
};
let end_pe = match self.inner.pe_for_dist_index(index + dst.len() - 1) {
Some(pe) => pe,
None => panic!(
"index out of bounds {:?} len {:?}",
index + dst.len() - 1,
self.len()
),
};
let mut dist_index = global_index;
let mut buf_index = 0;
let orig_len = dst.len();
for pe in start_pe..=end_pe {
let mut full_num_elems_on_pe = self.inner.orig_elem_per_pe;
if pe < self.inner.orig_remaining_elems {
full_num_elems_on_pe += 1;
}
let pe_full_start_index = self.inner.global_start_index_for_pe(pe);
let offset = dist_index - pe_full_start_index;
let len = std::cmp::min(full_num_elems_on_pe - offset, orig_len - buf_index);
if len > 0 {
let dsts = dst.split(len);
dst = dsts.1;
unsafe {
self.mem_region
.get_into_buffer_unmanaged(pe, offset, dsts.0)
};
buf_index += len;
dist_index += len;
}
}
}
fn rdma_cyclic_put<U: Into<MemregionRdmaInputInner<T>>>(
&self,
index: usize, buf: U,
unmanaged: bool,
) -> Vec<RdmaHandle<T>> {
let global_index = index + self.inner.offset;
let buf = buf.into();
let num_pes = self.inner.data.team.num_pes();
let num_elems_pe = buf.len() / num_pes + 1; let start_pe = global_index % num_pes;
let mut rdma_requests = Vec::new();
let mut pe_data = vec![Vec::with_capacity(num_elems_pe); num_pes];
let pe_start_index = global_index / num_pes;
for (i, pe) in (0..buf.len()).map(|i| (i, (start_pe + i) % num_pes)) {
pe_data[pe].push(buf.as_slice()[i]);
}
for (pe, data) in pe_data.into_iter().enumerate() {
if data.len() > 0 {
let mut pe_index = pe_start_index;
if pe < start_pe {
pe_index += 1;
}
if unmanaged {
unsafe {
self.mem_region.put_buffer_unmanaged(pe, pe_index, data);
}
} else {
unsafe { rdma_requests.push(self.mem_region.put_buffer(pe, pe_index, data)) };
}
}
}
rdma_requests
}
fn rdma_cyclic_get_buffer(
&self,
index: usize, num_elems: usize,
) -> FuturesOrdered<RdmaGetBufferHandle<T>> {
let global_index = index + self.inner.offset;
let num_pes = self.inner.data.team.num_pes();
let start_pe = global_index % num_pes;
let num_elems_pe = num_elems / num_pes; let pe_start_index = global_index / num_pes;
let mut rdma_requests = FuturesOrdered::new();
let remainder = num_elems % num_pes;
for offset in 0..std::cmp::min(num_elems, num_pes) {
let pe = (start_pe + offset) % num_pes;
let mut pe_index = pe_start_index;
if pe < start_pe {
pe_index += 1;
}
let mut pe_num_elems = num_elems_pe;
if offset < remainder {
pe_num_elems += 1;
}
unsafe {
rdma_requests.push_back(self.mem_region.get_buffer(pe, pe_index, pe_num_elems))
}
}
rdma_requests
}
pub(crate) fn pes_for_range(
&self,
index: usize,
len: usize,
) -> Box<dyn Iterator<Item = usize>> {
self.inner.pes_for_range(index, len)
}
pub(crate) fn num_elements_on_pe_for_range(
&self,
pe: usize,
start_index: usize,
len: usize,
) -> Option<usize> {
self.inner
.num_elements_on_pe_for_range(pe, start_index, len)
}
}
impl<T: Dist> UnsafeArray<T> {
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put(&self, index: usize, data: T) -> ArrayRdmaPutHandle<T> {
<Self as LamellarRdmaPut<T>>::put(self, index, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_unmanaged(&self, index: usize, data: T) {
<Self as LamellarRdmaPut<T>>::put_unmanaged(self, index, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_buffer<U: Into<MemregionRdmaInput<T>>>(
&self,
index: usize,
buf: U,
) -> ArrayRdmaPutHandle<T> {
<Self as LamellarRdmaPut<T>>::put_buffer(self, index, buf.into(), Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_buffer_unmanaged<U: Into<MemregionRdmaInput<T>>>(
&self,
index: usize,
buf: U,
) {
<Self as LamellarRdmaPut<T>>::put_buffer_unmanaged(self, index, buf.into(), Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_pe(&self, pe: usize, offset: usize, data: T) -> ArrayRdmaPutHandle<T> {
<Self as LamellarRdmaPut<T>>::put_pe(self, pe, offset, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_pe_unmanaged(&self, pe: usize, offset: usize, data: T) {
<Self as LamellarRdmaPut<T>>::put_pe_unmanaged(self, pe, offset, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_pe_buffer<U: Into<MemregionRdmaInput<T>>>(
&self,
pe: usize,
offset: usize,
buf: U,
) -> ArrayRdmaPutHandle<T> {
<Self as LamellarRdmaPut<T>>::put_pe_buffer(self, pe, offset, buf.into(), Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_pe_buffer_unmanaged<U: Into<MemregionRdmaInput<T>>>(
&self,
pe: usize,
offset: usize,
buf: U,
) {
<Self as LamellarRdmaPut<T>>::put_pe_buffer_unmanaged(self, pe, offset, buf.into(), Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_all(&self, offset: usize, data: T) -> ArrayRdmaPutHandle<T> {
<Self as LamellarRdmaPut<T>>::put_all(self, offset, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_all_unmanaged(&self, offset: usize, data: T) {
<Self as LamellarRdmaPut<T>>::put_all_unmanaged(self, offset, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_all_buffer<U: Into<MemregionRdmaInput<T>>>(
&self,
offset: usize,
buf: U,
) -> ArrayRdmaPutHandle<T> {
<Self as LamellarRdmaPut<T>>::put_all_buffer(self, offset, buf.into(), Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn put_all_buffer_unmanaged<U: Into<MemregionRdmaInput<T>>>(
&self,
offset: usize,
buf: U,
) {
<Self as LamellarRdmaPut<T>>::put_all_buffer_unmanaged(self, offset, buf.into(), Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn get(&self, index: usize) -> ArrayRdmaGetHandle<T> {
<Self as LamellarRdmaGet<T>>::get(self, index, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn blocking_get(&self, index: usize) -> T {
if let Some((pe, offset)) = self.pe_and_rdma_offset_for_global_index(index) {
let res = self.mem_region.blocking_get(pe, offset);
res
} else {
panic!("index out of bounds in LamellarArray put");
}
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn get_buffer(&self, index: usize, num_elems: usize) -> ArrayRdmaGetBufferHandle<T> {
<Self as LamellarRdmaGet<T>>::get_buffer(self, index, num_elems, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn blocking_get_buffer(&self, index: usize, num_elems: usize) -> Vec<T> {
<Self as LamellarRdmaGet<T>>::blocking_get_buffer(self, index, num_elems, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn get_into_buffer<B: AsLamellarBuffer<T>>(
&self,
index: usize,
data: LamellarBuffer<T, B>,
) -> ArrayRdmaGetIntoBufferHandle<T, B> {
<Self as LamellarRdmaGet<T>>::get_into_buffer(self, index, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn blocking_get_into_buffer<B: AsLamellarBuffer<T>>(
&self,
index: usize,
data: LamellarBuffer<T, B>,
) {
<Self as LamellarRdmaGet<T>>::blocking_get_into_buffer(self, index, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn get_into_buffer_unmanaged<B: AsLamellarBuffer<T>>(
&self,
index: usize,
data: LamellarBuffer<T, B>,
) {
<Self as LamellarRdmaGet<T>>::get_into_buffer_unmanaged(self, index, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn get_pe(&self, pe: usize, offset: usize) -> ArrayRdmaGetHandle<T> {
<Self as LamellarRdmaGet<T>>::get_pe(self, pe, offset, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn blocking_get_pe(&self, pe: usize, offset: usize) -> T {
self.mem_region.blocking_get(pe, offset)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn get_buffer_pe(
&self,
pe: usize,
offset: usize,
num_elems: usize,
) -> ArrayRdmaGetBufferHandle<T> {
<Self as LamellarRdmaGet<T>>::get_buffer_pe(self, pe, offset, num_elems, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn blocking_get_buffer_pe(
&self,
pe: usize,
offset: usize,
num_elems: usize,
) -> Vec<T> {
<Self as LamellarRdmaGet<T>>::blocking_get_buffer_pe(self, pe, offset, num_elems, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn get_into_buffer_pe<B: AsLamellarBuffer<T>>(
&self,
pe: usize,
offset: usize,
data: LamellarBuffer<T, B>,
) -> ArrayRdmaGetIntoBufferHandle<T, B> {
<Self as LamellarRdmaGet<T>>::get_into_buffer_pe(self, pe, offset, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn blocking_get_into_buffer_pe<B: AsLamellarBuffer<T>>(
&self,
pe: usize,
offset: usize,
data: LamellarBuffer<T, B>,
) {
<Self as LamellarRdmaGet<T>>::blocking_get_into_buffer_pe(self, pe, offset, data, Sealed)
}
#[doc(alias("One-sided", "onesided"))]
pub unsafe fn get_into_buffer_unmanaged_pe<B: AsLamellarBuffer<T>>(
&self,
pe: usize,
offset: usize,
data: LamellarBuffer<T, B>,
) {
<Self as LamellarRdmaGet<T>>::get_into_buffer_unmanaged_pe(self, pe, offset, data, Sealed)
}
}
impl<T: Dist> LamellarRdmaPut<T> for UnsafeArray<T> {
unsafe fn put(&self, index: usize, data: T, _: Sealed) -> ArrayRdmaPutHandle<T> {
if let Some((pe, offset)) = self.pe_and_rdma_offset_for_global_index(index) {
let req = self.mem_region.put(pe, offset, data);
ArrayRdmaPutHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaPutState::RdmaPut(req),
spawned: false,
}
} else {
panic!("index out of bounds in LamellarArray put");
}
}
unsafe fn put_unmanaged(&self, index: usize, data: T, _: Sealed) {
if let Some((pe, offset)) = self.pe_and_rdma_offset_for_global_index(index) {
self.mem_region.put_unmanaged(pe, offset, data);
} else {
panic!("index out of bounds in LamellarArray put");
}
}
unsafe fn put_buffer<U: Into<MemregionRdmaInputInner<T>>>(
&self,
index: usize,
buf: U,
_: Sealed,
) -> ArrayRdmaPutHandle<T> {
let reqs = match self.inner.distribution {
Distribution::Block => self.rdma_block_put(index, buf, false),
Distribution::Cyclic => self.rdma_cyclic_put(index, buf, false),
};
ArrayRdmaPutHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaPutState::MultiRdmaPut(reqs),
spawned: false,
}
}
unsafe fn put_buffer_unmanaged<U: Into<MemregionRdmaInputInner<T>>>(
&self,
index: usize,
buf: U,
_: Sealed,
) {
match self.inner.distribution {
Distribution::Block => {
self.rdma_block_put(index, buf, true);
}
Distribution::Cyclic => {
self.rdma_cyclic_put(index, buf, true);
}
};
}
unsafe fn put_pe(&self, pe: usize, offset: usize, data: T, _: Sealed) -> ArrayRdmaPutHandle<T> {
let req = self.mem_region.put(pe, offset, data);
ArrayRdmaPutHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaPutState::RdmaPut(req),
spawned: false,
}
}
unsafe fn put_pe_unmanaged(&self, pe: usize, offset: usize, data: T, _: Sealed) {
self.mem_region.put_unmanaged(pe, offset, data);
}
unsafe fn put_pe_buffer<U: Into<MemregionRdmaInputInner<T>>>(
&self,
pe: usize,
offset: usize,
buf: U,
_: Sealed,
) -> ArrayRdmaPutHandle<T> {
let req = self.mem_region.put_buffer(pe, offset, buf);
ArrayRdmaPutHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaPutState::RdmaPut(req),
spawned: false,
}
}
unsafe fn put_pe_buffer_unmanaged<U: Into<MemregionRdmaInputInner<T>>>(
&self,
pe: usize,
offset: usize,
buf: U,
_: Sealed,
) {
self.mem_region.put_buffer_unmanaged(pe, offset, buf);
}
unsafe fn put_all(&self, offset: usize, data: T, _: Sealed) -> ArrayRdmaPutHandle<T> {
let req = self.mem_region.put_all(offset, data);
ArrayRdmaPutHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaPutState::RdmaPut(req),
spawned: false,
}
}
unsafe fn put_all_unmanaged(&self, offset: usize, data: T, _: Sealed) {
self.mem_region.put_all_unmanaged(offset, data);
}
unsafe fn put_all_buffer<U: Into<MemregionRdmaInputInner<T>>>(
&self,
offset: usize,
buf: U,
_: Sealed,
) -> ArrayRdmaPutHandle<T> {
let req = self.mem_region.put_all_buffer(offset, buf);
ArrayRdmaPutHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaPutState::RdmaPut(req),
spawned: false,
}
}
unsafe fn put_all_buffer_unmanaged<U: Into<MemregionRdmaInputInner<T>>>(
&self,
offset: usize,
buf: U,
_: Sealed,
) {
self.mem_region.put_all_buffer_unmanaged(offset, buf);
}
}
impl<T: Dist> LamellarRdmaGet<T> for UnsafeArray<T> {
unsafe fn get(&self, index: usize, _: Sealed) -> ArrayRdmaGetHandle<T> {
if let Some((pe, offset)) = self.pe_and_rdma_offset_for_global_index(index) {
let req = self.mem_region.get(pe, offset);
ArrayRdmaGetHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaGetState::RdmaGet(req),
spawned: false,
}
} else {
panic!("index out of bounds in LamellarArray put");
}
}
unsafe fn blocking_get(&self, index: usize, _: Sealed) -> T {
if let Some((pe, offset)) = self.pe_and_rdma_offset_for_global_index(index) {
self.mem_region.blocking_get(pe, offset)
} else {
panic!("index out of bounds in LamellarArray put");
}
}
unsafe fn get_buffer(
&self,
index: usize,
num_elems: usize,
_: Sealed,
) -> ArrayRdmaGetBufferHandle<T> {
match self.inner.distribution {
Distribution::Block => ArrayRdmaGetBufferHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaGetBufferState::MultiRdmaBlockGet(
self.rdma_block_get_buffer(index, num_elems).collect(),
),
spawned: false,
},
Distribution::Cyclic => ArrayRdmaGetBufferHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaGetBufferState::MultiRdmaCyclicGet(
self.rdma_cyclic_get_buffer(index, num_elems).collect(),
),
spawned: false,
},
}
}
unsafe fn blocking_get_buffer(&self, index: usize, num_elems: usize, _: Sealed) -> Vec<T> {
<Self as LamellarRdmaGet<T>>::get_buffer(self, index, num_elems, Sealed).block()
}
unsafe fn get_into_buffer<B: AsLamellarBuffer<T>>(
&self,
index: usize,
data: LamellarBuffer<T, B>,
_: Sealed,
) -> ArrayRdmaGetIntoBufferHandle<T, B> {
let num_elems = data.len();
match self.inner.distribution {
Distribution::Block => ArrayRdmaGetIntoBufferHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaGetIntoBufferState::MultiRdmaBlockGet(
self.rdma_block_get_into_buffer(index, data).collect(),
),
spawned: false,
},
Distribution::Cyclic => ArrayRdmaGetIntoBufferHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaGetIntoBufferState::MultiRdmaCyclicGet(
data,
self.rdma_cyclic_get_buffer(index, num_elems).collect(),
),
spawned: false,
},
}
}
unsafe fn blocking_get_into_buffer<B: AsLamellarBuffer<T>>(
&self,
index: usize,
data: LamellarBuffer<T, B>,
_: Sealed,
) {
<Self as LamellarRdmaGet<T>>::get_into_buffer(self, index, data, Sealed).block()
}
unsafe fn get_into_buffer_unmanaged<B: AsLamellarBuffer<T>>(
&self,
index: usize,
data: LamellarBuffer<T, B>,
_: Sealed,
) {
let num_elems = data.len();
match self.inner.distribution {
Distribution::Block => self.rdma_block_get_into_buffer_unmanaged(index, data),
Distribution::Cyclic => {
let _ = ArrayRdmaGetIntoBufferHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaGetIntoBufferState::MultiRdmaCyclicGet(
data,
self.rdma_cyclic_get_buffer(index, num_elems).collect(),
),
spawned: false,
}
.spawn();
}
}
}
unsafe fn get_pe(&self, pe: usize, offset: usize, _: Sealed) -> ArrayRdmaGetHandle<T> {
let req = self.mem_region.get(pe, offset);
ArrayRdmaGetHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaGetState::RdmaGet(req),
spawned: false,
}
}
unsafe fn blocking_get_pe(&self, pe: usize, offset: usize, _: Sealed) -> T {
self.mem_region.blocking_get(pe, offset)
}
unsafe fn get_buffer_pe(
&self,
pe: usize,
offset: usize,
num_elems: usize,
_: Sealed,
) -> ArrayRdmaGetBufferHandle<T> {
let req = self.mem_region.get_buffer(pe, offset, num_elems);
ArrayRdmaGetBufferHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaGetBufferState::RdmaGet(req),
spawned: false,
}
}
unsafe fn blocking_get_buffer_pe(
&self,
pe: usize,
offset: usize,
num_elems: usize,
_: Sealed,
) -> Vec<T> {
self.mem_region.blocking_get_buffer(pe, offset, num_elems)
}
unsafe fn get_into_buffer_pe<B: AsLamellarBuffer<T>>(
&self,
pe: usize,
offset: usize,
data: LamellarBuffer<T, B>,
_: Sealed,
) -> ArrayRdmaGetIntoBufferHandle<T, B> {
let req = self.mem_region.get_into_buffer(pe, offset, data);
ArrayRdmaGetIntoBufferHandle {
array: self.as_lamellar_byte_array(),
state: ArrayRdmaGetIntoBufferState::RdmaGet(req),
spawned: false,
}
}
unsafe fn blocking_get_into_buffer_pe<B: AsLamellarBuffer<T>>(
&self,
pe: usize,
offset: usize,
data: LamellarBuffer<T, B>,
_: Sealed,
) {
self.mem_region.blocking_get_into_buffer(pe, offset, data);
}
unsafe fn get_into_buffer_unmanaged_pe<B: AsLamellarBuffer<T>>(
&self,
pe: usize,
offset: usize,
data: LamellarBuffer<T, B>,
_: Sealed,
) {
self.mem_region.get_into_buffer_unmanaged(pe, offset, data);
}
}
impl __UnsafeByteArray {
pub(crate) unsafe fn local_elements_for_range(
&self,
index: usize,
len: usize,
) -> Option<(&mut [u8], Box<dyn Iterator<Item = usize>>)> {
self.inner.local_elements_for_range(index, len)
}
pub(crate) unsafe fn element_for_local_index(&self, index: usize) -> &mut [u8] {
self.inner.element_for_local_index(index)
}
pub(crate) unsafe fn ptr_for_local_index(&self, index: usize) -> *mut u8 {
self.inner.ptr_for_local_index(index)
}
}
impl UnsafeArrayInner {
pub(crate) fn pes_for_range(
&self,
index: usize,
len: usize,
) -> Box<dyn Iterator<Item = usize>> {
match self.distribution {
Distribution::Block => {
if let Some(start_pe) = self.pe_for_dist_index(index) {
if let Some(end_pe) = self.pe_for_dist_index(index + len - 1) {
return Box::new(start_pe..=end_pe);
}
}
return Box::new(0..0);
}
Distribution::Cyclic => {
let global_start = self.offset + index;
let global_end = global_start + len - 1; let num_pes = self.data.num_pes;
let mut pes = vec![];
for index in global_start..=global_end {
pes.push(index % num_pes);
if pes.len() == num_pes {
break;
}
}
return Box::new(pes.into_iter());
}
}
}
pub(crate) unsafe fn element_for_local_index(&self, index: usize) -> &mut [u8] {
&mut self.local_as_mut_slice()[index * self.elem_size..(index + 1) * self.elem_size]
}
pub(crate) unsafe fn ptr_for_local_index(&self, index: usize) -> *mut u8 {
self.local_as_mut_ptr().add(index * self.elem_size)
}
pub(crate) unsafe fn local_elements_for_range(
&self,
index: usize,
len: usize,
) -> Option<(&mut [u8], Box<dyn Iterator<Item = usize>>)> {
let my_pe = self.data.my_pe;
let start_pe = match self.pe_for_dist_index(index) {
Some(pe) => pe,
None => panic!(
"Index: {index} out of bounds for array of len {:?}",
self.size
),
};
let end_pe = match self.pe_for_dist_index(index + len - 1) {
Some(pe) => pe,
None => panic!(
"Index: {:?} out of bounds for array of len {:?}",
index + len - 1,
self.size
),
};
match self.distribution {
Distribution::Block => {
let num_elems_local = self.num_elems_local();
if my_pe > end_pe || my_pe < start_pe {
return None;
}
let subarray_start_index = self
.start_index_for_pe(my_pe)
.expect("array data exists on PE"); let (start_index, rem_elem) = if my_pe == start_pe {
(index - subarray_start_index, len)
} else {
(0, len - (subarray_start_index - index))
};
let end_index = if my_pe == end_pe {
start_index + rem_elem
} else {
num_elems_local
};
Some((
&mut self.local_as_mut_slice()
[start_index * self.elem_size..end_index * self.elem_size],
Box::new(start_index..end_index),
))
}
Distribution::Cyclic => {
let num_pes = self.data.num_pes;
let mut local_index = index; if my_pe >= start_pe {
local_index += my_pe - start_pe;
} else {
local_index += (num_pes - start_pe) + my_pe;
}
let start_index = local_index / num_pes;
let mut num_elems = len / num_pes;
if len % num_pes != 0 {
if start_pe <= end_pe {
if my_pe >= start_pe && my_pe <= end_pe {
num_elems += 1
}
} else {
if my_pe >= start_pe || my_pe <= end_pe {
num_elems += 1
}
}
}
if num_elems > 0 {
let end_index = start_index + num_elems;
Some((
&mut self.local_as_mut_slice()
[start_index * self.elem_size..end_index * self.elem_size],
Box::new(start_index..end_index),
))
} else {
None
}
}
}
}
pub(crate) fn num_elements_on_pe_for_range(
&self,
pe: usize,
index: usize,
len: usize,
) -> Option<usize> {
let start_pe = match self.pe_for_dist_index(index) {
Some(pe) => pe,
None => panic!(
"Index: {index} out of bounds for array of len {:?}",
self.size
),
};
let end_pe = match self.pe_for_dist_index(index + len - 1) {
Some(pe) => pe,
None => panic!(
"Index: {:?} out of bounds for array of len {:?}",
index + len - 1,
self.size
),
};
match self.distribution {
Distribution::Block => {
let num_elems_pe = self.num_elems_pe(pe);
if pe > end_pe || pe < start_pe {
return None;
}
let subarray_start_index = self
.start_index_for_pe(pe)
.expect("array data exists on PE"); let (start_index, rem_elem) = if pe == start_pe {
(index - subarray_start_index, len)
} else {
(0, len - (subarray_start_index - index))
};
let end_index = if pe == end_pe {
start_index + rem_elem
} else {
num_elems_pe
};
Some(end_index - start_index)
}
Distribution::Cyclic => {
let num_pes = self.data.num_pes;
let mut num_elems = len / num_pes;
if len % num_pes != 0 {
if start_pe <= end_pe {
if pe >= start_pe && pe <= end_pe {
num_elems += 1
}
} else {
if pe >= start_pe || pe <= end_pe {
num_elems += 1
}
}
}
if num_elems > 0 {
Some(num_elems)
} else {
None
}
}
}
}
}